summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnnabel Dunstone <annabel.dunstone@gmail.com>2016-08-17 12:33:05 -0500
committerAnnabel Dunstone <annabel.dunstone@gmail.com>2016-08-17 12:33:05 -0500
commitab44aa7b34e85b498d5aba02e5ad902d6d16fe7f (patch)
tree53cf7e3a8913a2c14f96a8a3287e573fc6383146
parent2c23465d05fa1efa4213bd5d7b0e86b1cd521212 (diff)
parent095fcfc4473d7bfbca878bc2947ca8dfc59e387f (diff)
downloadgitlab-ce-ab44aa7b34e85b498d5aba02e5ad902d6d16fe7f.tar.gz
Merge master into branch
-rw-r--r--CHANGELOG1
-rw-r--r--app/assets/javascripts/dispatcher.js2
-rw-r--r--app/assets/javascripts/merge_conflict_data_provider.js.es6341
-rw-r--r--app/assets/javascripts/merge_conflict_resolver.js.es685
-rw-r--r--app/assets/javascripts/merge_request_tabs.js22
-rw-r--r--app/assets/javascripts/merge_request_widget.js4
-rw-r--r--app/assets/stylesheets/behaviors.scss5
-rw-r--r--app/assets/stylesheets/framework/mixins.scss7
-rw-r--r--app/assets/stylesheets/highlight/dark.scss7
-rw-r--r--app/assets/stylesheets/highlight/monokai.scss7
-rw-r--r--app/assets/stylesheets/highlight/solarized_dark.scss7
-rw-r--r--app/assets/stylesheets/highlight/solarized_light.scss13
-rw-r--r--app/assets/stylesheets/highlight/white.scss13
-rw-r--r--app/assets/stylesheets/pages/merge_conflicts.scss238
-rw-r--r--app/assets/stylesheets/pages/pipelines.scss12
-rw-r--r--app/controllers/projects/merge_requests_controller.rb72
-rw-r--r--app/helpers/commits_helper.rb45
-rw-r--r--app/helpers/nav_helper.rb1
-rw-r--r--app/models/diff_note.rb2
-rw-r--r--app/models/merge_request.rb37
-rw-r--r--app/models/repository.rb8
-rw-r--r--app/services/merge_requests/resolve_service.rb31
-rw-r--r--app/views/projects/ci/pipelines/_pipeline.html.haml20
-rw-r--r--app/views/projects/commit/_pipelines_list.haml17
-rw-r--r--app/views/projects/merge_requests/_show.html.haml14
-rw-r--r--app/views/projects/merge_requests/conflicts.html.haml29
-rw-r--r--app/views/projects/merge_requests/conflicts/_commit_stats.html.haml20
-rw-r--r--app/views/projects/merge_requests/conflicts/_inline_view.html.haml28
-rw-r--r--app/views/projects/merge_requests/conflicts/_parallel_view.html.haml27
-rw-r--r--app/views/projects/merge_requests/conflicts/_submit_form.html.haml15
-rw-r--r--app/views/projects/merge_requests/show/_builds.html.haml1
-rw-r--r--app/views/projects/merge_requests/show/_pipelines.html.haml1
-rw-r--r--app/views/projects/merge_requests/widget/_merged.html.haml2
-rw-r--r--app/views/projects/merge_requests/widget/_open.html.haml10
-rw-r--r--app/views/projects/merge_requests/widget/_show.html.haml3
-rw-r--r--app/views/projects/merge_requests/widget/open/_conflicts.html.haml13
-rw-r--r--config/routes.rb3
-rw-r--r--doc/user/project/merge_requests/img/conflict_section.pngbin0 -> 247537 bytes
-rw-r--r--doc/user/project/merge_requests/img/merge_request_widget.pngbin0 -> 32292 bytes
-rw-r--r--doc/user/project/merge_requests/resolve_conflicts.md41
-rw-r--r--lib/gitlab/conflict/file.rb186
-rw-r--r--lib/gitlab/conflict/file_collection.rb57
-rw-r--r--lib/gitlab/conflict/parser.rb62
-rw-r--r--lib/gitlab/diff/line.rb20
-rw-r--r--lib/gitlab/downtime_check/message.rb19
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb136
-rw-r--r--spec/features/merge_requests/conflicts_spec.rb72
-rw-r--r--spec/features/merge_requests/pipelines_spec.rb48
-rw-r--r--spec/lib/gitlab/conflict/file_collection_spec.rb24
-rw-r--r--spec/lib/gitlab/conflict/file_spec.rb261
-rw-r--r--spec/lib/gitlab/conflict/parser_spec.rb188
-rw-r--r--spec/lib/gitlab/downtime_check/message_spec.rb26
-rw-r--r--spec/models/merge_request_spec.rb79
-rw-r--r--spec/support/test_env.rb44
-rw-r--r--vendor/assets/javascripts/vue-resource.full.js1318
-rw-r--r--vendor/assets/javascripts/vue-resource.js.erb2
-rw-r--r--vendor/assets/javascripts/vue-resource.min.js7
-rw-r--r--vendor/assets/javascripts/vue.full.js10073
-rw-r--r--vendor/assets/javascripts/vue.js.erb2
-rw-r--r--vendor/assets/javascripts/vue.min.js9
60 files changed, 13748 insertions, 89 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 971111c4fc1..7bade93cffe 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -121,6 +121,7 @@ v 8.11.0 (unreleased)
- Fix a memory leak caused by Banzai::Filter::SanitizationFilter
- Speed up todos queries by limiting the projects set we join with
- Ensure file editing in UI does not overwrite commited changes without warning user
+ - Eliminate unneeded calls to Repository#blob_at when listing commits with no path
v 8.10.6
- Upgrade Rails to 4.2.7.1 for security fixes. !5781
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index 7160fa71ce5..1163edd8547 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -88,6 +88,8 @@
new ZenMode();
new MergedButtons();
break;
+ case "projects:merge_requests:conflicts":
+ window.mcui = new MergeConflictResolver()
case 'projects:merge_requests:index':
shortcut_handler = new ShortcutsNavigation();
Issuable.init();
diff --git a/app/assets/javascripts/merge_conflict_data_provider.js.es6 b/app/assets/javascripts/merge_conflict_data_provider.js.es6
new file mode 100644
index 00000000000..cd92df8ddc5
--- /dev/null
+++ b/app/assets/javascripts/merge_conflict_data_provider.js.es6
@@ -0,0 +1,341 @@
+const HEAD_HEADER_TEXT = 'HEAD//our changes';
+const ORIGIN_HEADER_TEXT = 'origin//their changes';
+const HEAD_BUTTON_TITLE = 'Use ours';
+const ORIGIN_BUTTON_TITLE = 'Use theirs';
+
+
+class MergeConflictDataProvider {
+
+ getInitialData() {
+ const diffViewType = $.cookie('diff_view');
+
+ return {
+ isLoading : true,
+ hasError : false,
+ isParallel : diffViewType === 'parallel',
+ diffViewType : diffViewType,
+ isSubmitting : false,
+ conflictsData : {},
+ resolutionData : {}
+ }
+ }
+
+
+ decorateData(vueInstance, data) {
+ this.vueInstance = vueInstance;
+
+ if (data.type === 'error') {
+ vueInstance.hasError = true;
+ data.errorMessage = data.message;
+ }
+ else {
+ data.shortCommitSha = data.commit_sha.slice(0, 7);
+ data.commitMessage = data.commit_message;
+
+ this.setParallelLines(data);
+ this.setInlineLines(data);
+ this.updateResolutionsData(data);
+ }
+
+ vueInstance.conflictsData = data;
+ vueInstance.isSubmitting = false;
+
+ const conflictsText = this.getConflictsCount() > 1 ? 'conflicts' : 'conflict';
+ vueInstance.conflictsData.conflictsText = conflictsText;
+ }
+
+
+ updateResolutionsData(data) {
+ const vi = this.vueInstance;
+
+ data.files.forEach( (file) => {
+ file.sections.forEach( (section) => {
+ if (section.conflict) {
+ vi.$set(`resolutionData['${section.id}']`, false);
+ }
+ });
+ });
+ }
+
+
+ setParallelLines(data) {
+ data.files.forEach( (file) => {
+ file.filePath = this.getFilePath(file);
+ file.iconClass = `fa-${file.blob_icon}`;
+ file.blobPath = file.blob_path;
+ file.parallelLines = [];
+ const linesObj = { left: [], right: [] };
+
+ file.sections.forEach( (section) => {
+ const { conflict, lines, id } = section;
+
+ if (conflict) {
+ linesObj.left.push(this.getOriginHeaderLine(id));
+ linesObj.right.push(this.getHeadHeaderLine(id));
+ }
+
+ lines.forEach( (line) => {
+ const { type } = line;
+
+ if (conflict) {
+ if (type === 'old') {
+ linesObj.left.push(this.getLineForParallelView(line, id, 'conflict'));
+ }
+ else if (type === 'new') {
+ linesObj.right.push(this.getLineForParallelView(line, id, 'conflict', true));
+ }
+ }
+ else {
+ const lineType = type || 'context';
+
+ linesObj.left.push (this.getLineForParallelView(line, id, lineType));
+ linesObj.right.push(this.getLineForParallelView(line, id, lineType, true));
+ }
+ });
+
+ this.checkLineLengths(linesObj);
+ });
+
+ for (let i = 0, len = linesObj.left.length; i < len; i++) {
+ file.parallelLines.push([
+ linesObj.right[i],
+ linesObj.left[i]
+ ]);
+ }
+
+ });
+ }
+
+
+ checkLineLengths(linesObj) {
+ let { left, right } = linesObj;
+
+ if (left.length !== right.length) {
+ if (left.length > right.length) {
+ const diff = left.length - right.length;
+ for (let i = 0; i < diff; i++) {
+ right.push({ lineType: 'emptyLine', richText: '' });
+ }
+ }
+ else {
+ const diff = right.length - left.length;
+ for (let i = 0; i < diff; i++) {
+ left.push({ lineType: 'emptyLine', richText: '' });
+ }
+ }
+ }
+ }
+
+
+ setInlineLines(data) {
+ data.files.forEach( (file) => {
+ file.iconClass = `fa-${file.blob_icon}`;
+ file.blobPath = file.blob_path;
+ file.filePath = this.getFilePath(file);
+ file.inlineLines = []
+
+ file.sections.forEach( (section) => {
+ let currentLineType = 'new';
+ const { conflict, lines, id } = section;
+
+ if (conflict) {
+ file.inlineLines.push(this.getHeadHeaderLine(id));
+ }
+
+ lines.forEach( (line) => {
+ const { type } = line;
+
+ if ((type === 'new' || type === 'old') && currentLineType !== type) {
+ currentLineType = type;
+ file.inlineLines.push({ lineType: 'emptyLine', richText: '' });
+ }
+
+ this.decorateLineForInlineView(line, id, conflict);
+ file.inlineLines.push(line);
+ })
+
+ if (conflict) {
+ file.inlineLines.push(this.getOriginHeaderLine(id));
+ }
+ });
+ });
+ }
+
+
+ handleSelected(sectionId, selection) {
+ const vi = this.vueInstance;
+
+ vi.resolutionData[sectionId] = selection;
+ vi.conflictsData.files.forEach( (file) => {
+ file.inlineLines.forEach( (line) => {
+ if (line.id === sectionId && (line.hasConflict || line.isHeader)) {
+ this.markLine(line, selection);
+ }
+ });
+
+ file.parallelLines.forEach( (lines) => {
+ const left = lines[0];
+ const right = lines[1];
+ const hasSameId = right.id === sectionId || left.id === sectionId;
+ const isLeftMatch = left.hasConflict || left.isHeader;
+ const isRightMatch = right.hasConflict || right.isHeader;
+
+ if (hasSameId && (isLeftMatch || isRightMatch)) {
+ this.markLine(left, selection);
+ this.markLine(right, selection);
+ }
+ })
+ });
+ }
+
+
+ updateViewType(newType) {
+ const vi = this.vueInstance;
+
+ if (newType === vi.diffView || !(newType === 'parallel' || newType === 'inline')) {
+ return;
+ }
+
+ vi.diffView = newType;
+ vi.isParallel = newType === 'parallel';
+ $.cookie('diff_view', newType); // TODO: Make sure that cookie path added.
+ $('.content-wrapper .container-fluid').toggleClass('container-limited');
+ }
+
+
+ markLine(line, selection) {
+ if (selection === 'head' && line.isHead) {
+ line.isSelected = true;
+ line.isUnselected = false;
+ }
+ else if (selection === 'origin' && line.isOrigin) {
+ line.isSelected = true;
+ line.isUnselected = false;
+ }
+ else {
+ line.isSelected = false;
+ line.isUnselected = true;
+ }
+ }
+
+
+ getConflictsCount() {
+ return Object.keys(this.vueInstance.resolutionData).length;
+ }
+
+
+ getResolvedCount() {
+ let count = 0;
+ const data = this.vueInstance.resolutionData;
+
+ for (const id in data) {
+ const resolution = data[id];
+ if (resolution) {
+ count++;
+ }
+ }
+
+ return count;
+ }
+
+
+ isReadyToCommit() {
+ const { conflictsData, isSubmitting } = this.vueInstance
+ const allResolved = this.getConflictsCount() === this.getResolvedCount();
+ const hasCommitMessage = $.trim(conflictsData.commitMessage).length;
+
+ return !isSubmitting && hasCommitMessage && allResolved;
+ }
+
+
+ getCommitButtonText() {
+ const initial = 'Commit conflict resolution';
+ const inProgress = 'Committing...';
+ const vue = this.vueInstance;
+
+ return vue ? vue.isSubmitting ? inProgress : initial : initial;
+ }
+
+
+ decorateLineForInlineView(line, id, conflict) {
+ const { type } = line;
+ line.id = id;
+ line.hasConflict = conflict;
+ line.isHead = type === 'new';
+ line.isOrigin = type === 'old';
+ line.hasMatch = type === 'match';
+ line.richText = line.rich_text;
+ line.isSelected = false;
+ line.isUnselected = false;
+ }
+
+ getLineForParallelView(line, id, lineType, isHead) {
+ const { old_line, new_line, rich_text } = line;
+ const hasConflict = lineType === 'conflict';
+
+ return {
+ id,
+ lineType,
+ hasConflict,
+ isHead : hasConflict && isHead,
+ isOrigin : hasConflict && !isHead,
+ hasMatch : lineType === 'match',
+ lineNumber : isHead ? new_line : old_line,
+ section : isHead ? 'head' : 'origin',
+ richText : rich_text,
+ isSelected : false,
+ isUnselected : false
+ }
+ }
+
+
+ getHeadHeaderLine(id) {
+ return {
+ id : id,
+ richText : HEAD_HEADER_TEXT,
+ buttonTitle : HEAD_BUTTON_TITLE,
+ type : 'new',
+ section : 'head',
+ isHeader : true,
+ isHead : true,
+ isSelected : false,
+ isUnselected: false
+ }
+ }
+
+
+ getOriginHeaderLine(id) {
+ return {
+ id : id,
+ richText : ORIGIN_HEADER_TEXT,
+ buttonTitle : ORIGIN_BUTTON_TITLE,
+ type : 'old',
+ section : 'origin',
+ isHeader : true,
+ isOrigin : true,
+ isSelected : false,
+ isUnselected: false
+ }
+ }
+
+
+ handleFailedRequest(vueInstance, data) {
+ vueInstance.hasError = true;
+ vueInstance.conflictsData.errorMessage = 'Something went wrong!';
+ }
+
+
+ getCommitData() {
+ return {
+ commit_message: this.vueInstance.conflictsData.commitMessage,
+ sections: this.vueInstance.resolutionData
+ }
+ }
+
+
+ getFilePath(file) {
+ const { old_path, new_path } = file;
+ return old_path === new_path ? new_path : `${old_path} → ${new_path}`;
+ }
+
+}
diff --git a/app/assets/javascripts/merge_conflict_resolver.js.es6 b/app/assets/javascripts/merge_conflict_resolver.js.es6
new file mode 100644
index 00000000000..77bffbcb403
--- /dev/null
+++ b/app/assets/javascripts/merge_conflict_resolver.js.es6
@@ -0,0 +1,85 @@
+//= require vue
+
+class MergeConflictResolver {
+
+ constructor() {
+ this.dataProvider = new MergeConflictDataProvider()
+ this.initVue()
+ }
+
+
+ initVue() {
+ const that = this;
+ this.vue = new Vue({
+ el : '#conflicts',
+ name : 'MergeConflictResolver',
+ data : this.dataProvider.getInitialData(),
+ created : this.fetchData(),
+ computed : this.setComputedProperties(),
+ methods : {
+ handleSelected(sectionId, selection) {
+ that.dataProvider.handleSelected(sectionId, selection);
+ },
+ handleViewTypeChange(newType) {
+ that.dataProvider.updateViewType(newType);
+ },
+ commit() {
+ that.commit();
+ }
+ }
+ })
+ }
+
+
+ setComputedProperties() {
+ const dp = this.dataProvider;
+
+ return {
+ conflictsCount() { return dp.getConflictsCount() },
+ resolvedCount() { return dp.getResolvedCount() },
+ readyToCommit() { return dp.isReadyToCommit() },
+ commitButtonText() { return dp.getCommitButtonText() }
+ }
+ }
+
+
+ fetchData() {
+ const dp = this.dataProvider;
+
+ $.get($('#conflicts').data('conflictsPath'))
+ .done((data) => {
+ dp.decorateData(this.vue, data);
+ })
+ .error((data) => {
+ dp.handleFailedRequest(this.vue, data);
+ })
+ .always(() => {
+ this.vue.isLoading = false;
+
+ this.vue.$nextTick(() => {
+ $('#conflicts .js-syntax-highlight').syntaxHighlight();
+ });
+
+ if (this.vue.diffViewType === 'parallel') {
+ $('.content-wrapper .container-fluid').removeClass('container-limited');
+ }
+ })
+ }
+
+
+ commit() {
+ this.vue.isSubmitting = true;
+
+ $.post($('#conflicts').data('resolveConflictsPath'), this.dataProvider.getCommitData())
+ .done((data) => {
+ window.location.href = data.redirect_to;
+ })
+ .error(() => {
+ new Flash('Something went wrong!');
+ })
+ .always(() => {
+ this.vue.isSubmitting = false;
+ });
+ }
+
+}
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index 52c2ed61012..1bba69a255a 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -9,6 +9,8 @@
MergeRequestTabs.prototype.buildsLoaded = false;
+ MergeRequestTabs.prototype.pipelinesLoaded = false;
+
MergeRequestTabs.prototype.commitsLoaded = false;
function MergeRequestTabs(opts) {
@@ -50,6 +52,9 @@
} else if (action === 'builds') {
this.loadBuilds($target.attr('href'));
this.expandView();
+ } else if (action === 'pipelines') {
+ this.loadPipelines($target.attr('href'));
+ this.expandView();
} else {
this.expandView();
}
@@ -81,7 +86,7 @@
if (action === 'show') {
action = 'notes';
}
- new_state = this._location.pathname.replace(/\/(commits|diffs|builds)(\.html)?\/?$/, '');
+ new_state = this._location.pathname.replace(/\/(commits|diffs|builds|pipelines)(\.html)?\/?$/, '');
if (action !== 'notes') {
new_state += "/" + action;
}
@@ -177,6 +182,21 @@
});
};
+ MergeRequestTabs.prototype.loadPipelines = function(source) {
+ if (this.pipelinesLoaded) {
+ return;
+ }
+ return this._get({
+ url: source + ".json",
+ success: function(data) {
+ $('#pipelines').html(data.html);
+ gl.utils.localTimeAgo($('.js-timeago', '#pipelines'));
+ this.pipelinesLoaded = true;
+ return this.scrollToElement("#pipelines");
+ }.bind(this)
+ });
+ };
+
MergeRequestTabs.prototype.toggleLoading = function(status) {
return $('.mr-loading-status .loading').toggle(status);
};
diff --git a/app/assets/javascripts/merge_request_widget.js b/app/assets/javascripts/merge_request_widget.js
index 362aaa906d0..bd35b6f679d 100644
--- a/app/assets/javascripts/merge_request_widget.js
+++ b/app/assets/javascripts/merge_request_widget.js
@@ -28,7 +28,7 @@
MergeRequestWidget.prototype.addEventListeners = function() {
var allowedPages;
- allowedPages = ['show', 'commits', 'builds', 'changes'];
+ allowedPages = ['show', 'commits', 'builds', 'pipelines', 'changes'];
return $(document).on('page:change.merge_request', (function(_this) {
return function() {
var page;
@@ -53,7 +53,7 @@
return function(data) {
var callback, urlSuffix;
if (data.state === "merged") {
- urlSuffix = deleteSourceBranch ? '?delete_source=true' : '';
+ urlSuffix = deleteSourceBranch ? '?deleted_source_branch=true' : '';
return window.location.href = window.location.pathname + urlSuffix;
} else if (data.merge_error) {
return $('.mr-widget-body').html("<h4>" + data.merge_error + "</h4>");
diff --git a/app/assets/stylesheets/behaviors.scss b/app/assets/stylesheets/behaviors.scss
index 542a53f0377..a6b9efc49c9 100644
--- a/app/assets/stylesheets/behaviors.scss
+++ b/app/assets/stylesheets/behaviors.scss
@@ -20,3 +20,8 @@
.turn-off { display: block; }
}
}
+
+
+[v-cloak] {
+ display: none;
+}
diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss
index 5ec5a96a597..d2d60ed7196 100644
--- a/app/assets/stylesheets/framework/mixins.scss
+++ b/app/assets/stylesheets/framework/mixins.scss
@@ -123,4 +123,9 @@
}
}
}
-} \ No newline at end of file
+}
+
+@mixin dark-diff-match-line {
+ color: rgba(255, 255, 255, 0.3);
+ background: rgba(255, 255, 255, 0.1);
+}
diff --git a/app/assets/stylesheets/highlight/dark.scss b/app/assets/stylesheets/highlight/dark.scss
index 77a73dc379b..16ffbe57a99 100644
--- a/app/assets/stylesheets/highlight/dark.scss
+++ b/app/assets/stylesheets/highlight/dark.scss
@@ -21,6 +21,10 @@
// Diff line
.line_holder {
+ &.match .line_content {
+ @include dark-diff-match-line;
+ }
+
td.diff-line-num.hll:not(.empty-cell),
td.line_content.hll:not(.empty-cell) {
background-color: #557;
@@ -36,8 +40,7 @@
}
.line_content.match {
- color: rgba(255, 255, 255, 0.3);
- background: rgba(255, 255, 255, 0.1);
+ @include dark-diff-match-line;
}
}
diff --git a/app/assets/stylesheets/highlight/monokai.scss b/app/assets/stylesheets/highlight/monokai.scss
index 80a509a7c1a..7de920e074b 100644
--- a/app/assets/stylesheets/highlight/monokai.scss
+++ b/app/assets/stylesheets/highlight/monokai.scss
@@ -21,6 +21,10 @@
// Diff line
.line_holder {
+ &.match .line_content {
+ @include dark-diff-match-line;
+ }
+
td.diff-line-num.hll:not(.empty-cell),
td.line_content.hll:not(.empty-cell) {
background-color: #49483e;
@@ -36,8 +40,7 @@
}
.line_content.match {
- color: rgba(255, 255, 255, 0.3);
- background: rgba(255, 255, 255, 0.1);
+ @include dark-diff-match-line;
}
}
diff --git a/app/assets/stylesheets/highlight/solarized_dark.scss b/app/assets/stylesheets/highlight/solarized_dark.scss
index c62bd021aef..b11499c71ee 100644
--- a/app/assets/stylesheets/highlight/solarized_dark.scss
+++ b/app/assets/stylesheets/highlight/solarized_dark.scss
@@ -21,6 +21,10 @@
// Diff line
.line_holder {
+ &.match .line_content {
+ @include dark-diff-match-line;
+ }
+
td.diff-line-num.hll:not(.empty-cell),
td.line_content.hll:not(.empty-cell) {
background-color: #174652;
@@ -36,8 +40,7 @@
}
.line_content.match {
- color: rgba(255, 255, 255, 0.3);
- background: rgba(255, 255, 255, 0.1);
+ @include dark-diff-match-line;
}
}
diff --git a/app/assets/stylesheets/highlight/solarized_light.scss b/app/assets/stylesheets/highlight/solarized_light.scss
index 524cfaf90c3..657bb5e3cd9 100644
--- a/app/assets/stylesheets/highlight/solarized_light.scss
+++ b/app/assets/stylesheets/highlight/solarized_light.scss
@@ -1,4 +1,10 @@
/* https://gist.github.com/qguv/7936275 */
+
+@mixin matchLine {
+ color: $black-transparent;
+ background: rgba(255, 255, 255, 0.4);
+}
+
.code.solarized-light {
// Line numbers
.line-numbers, .diff-line-num {
@@ -21,6 +27,10 @@
// Diff line
.line_holder {
+ &.match .line_content {
+ @include matchLine;
+ }
+
td.diff-line-num.hll:not(.empty-cell),
td.line_content.hll:not(.empty-cell) {
background-color: #ddd8c5;
@@ -36,8 +46,7 @@
}
.line_content.match {
- color: $black-transparent;
- background: rgba(255, 255, 255, 0.4);
+ @include matchLine;
}
}
diff --git a/app/assets/stylesheets/highlight/white.scss b/app/assets/stylesheets/highlight/white.scss
index 31a4e3deaac..36a80a916b2 100644
--- a/app/assets/stylesheets/highlight/white.scss
+++ b/app/assets/stylesheets/highlight/white.scss
@@ -1,4 +1,10 @@
/* https://github.com/aahan/pygments-github-style */
+
+@mixin matchLine {
+ color: $black-transparent;
+ background-color: $match-line;
+}
+
.code.white {
// Line numbers
.line-numbers, .diff-line-num {
@@ -22,6 +28,10 @@
// Diff line
.line_holder {
+ &.match .line_content {
+ @include matchLine;
+ }
+
.diff-line-num {
&.old {
background-color: $line-number-old;
@@ -57,8 +67,7 @@
}
&.match {
- color: $black-transparent;
- background-color: $match-line;
+ @include matchLine;
}
&.hll:not(.empty-cell) {
diff --git a/app/assets/stylesheets/pages/merge_conflicts.scss b/app/assets/stylesheets/pages/merge_conflicts.scss
new file mode 100644
index 00000000000..1f499897c16
--- /dev/null
+++ b/app/assets/stylesheets/pages/merge_conflicts.scss
@@ -0,0 +1,238 @@
+$colors: (
+ white_header_head_neutral : #e1fad7,
+ white_line_head_neutral : #effdec,
+ white_button_head_neutral : #9adb84,
+
+ white_header_head_chosen : #baf0a8,
+ white_line_head_chosen : #e1fad7,
+ white_button_head_chosen : #52c22d,
+
+ white_header_origin_neutral : #e0f0ff,
+ white_line_origin_neutral : #f2f9ff,
+ white_button_origin_neutral : #87c2fa,
+
+ white_header_origin_chosen : #add8ff,
+ white_line_origin_chosen : #e0f0ff,
+ white_button_origin_chosen : #268ced,
+
+ white_header_not_chosen : #f0f0f0,
+ white_line_not_chosen : #f9f9f9,
+
+
+ dark_header_head_neutral : rgba(#3f3, .2),
+ dark_line_head_neutral : rgba(#3f3, .1),
+ dark_button_head_neutral : #40874f,
+
+ dark_header_head_chosen : rgba(#3f3, .33),
+ dark_line_head_chosen : rgba(#3f3, .2),
+ dark_button_head_chosen : #258537,
+
+ dark_header_origin_neutral : rgba(#2878c9, .4),
+ dark_line_origin_neutral : rgba(#2878c9, .3),
+ dark_button_origin_neutral : #2a5c8c,
+
+ dark_header_origin_chosen : rgba(#2878c9, .6),
+ dark_line_origin_chosen : rgba(#2878c9, .4),
+ dark_button_origin_chosen : #1d6cbf,
+
+ dark_header_not_chosen : rgba(#fff, .25),
+ dark_line_not_chosen : rgba(#fff, .1),
+
+
+ monokai_header_head_neutral : rgba(#a6e22e, .25),
+ monokai_line_head_neutral : rgba(#a6e22e, .1),
+ monokai_button_head_neutral : #376b20,
+
+ monokai_header_head_chosen : rgba(#a6e22e, .4),
+ monokai_line_head_chosen : rgba(#a6e22e, .25),
+ monokai_button_head_chosen : #39800d,
+
+ monokai_header_origin_neutral : rgba(#60d9f1, .35),
+ monokai_line_origin_neutral : rgba(#60d9f1, .15),
+ monokai_button_origin_neutral : #38848c,
+
+ monokai_header_origin_chosen : rgba(#60d9f1, .5),
+ monokai_line_origin_chosen : rgba(#60d9f1, .35),
+ monokai_button_origin_chosen : #3ea4b2,
+
+ monokai_header_not_chosen : rgba(#76715d, .24),
+ monokai_line_not_chosen : rgba(#76715d, .1),
+
+
+ solarized_light_header_head_neutral : rgba(#859900, .37),
+ solarized_light_line_head_neutral : rgba(#859900, .2),
+ solarized_light_button_head_neutral : #afb262,
+
+ solarized_light_header_head_chosen : rgba(#859900, .5),
+ solarized_light_line_head_chosen : rgba(#859900, .37),
+ solarized_light_button_head_chosen : #94993d,
+
+ solarized_light_header_origin_neutral : rgba(#2878c9, .37),
+ solarized_light_line_origin_neutral : rgba(#2878c9, .15),
+ solarized_light_button_origin_neutral : #60a1bf,
+
+ solarized_light_header_origin_chosen : rgba(#2878c9, .6),
+ solarized_light_line_origin_chosen : rgba(#2878c9, .37),
+ solarized_light_button_origin_chosen : #2482b2,
+
+ solarized_light_header_not_chosen : rgba(#839496, .37),
+ solarized_light_line_not_chosen : rgba(#839496, .2),
+
+
+ solarized_dark_header_head_neutral : rgba(#859900, .35),
+ solarized_dark_line_head_neutral : rgba(#859900, .15),
+ solarized_dark_button_head_neutral : #376b20,
+
+ solarized_dark_header_head_chosen : rgba(#859900, .5),
+ solarized_dark_line_head_chosen : rgba(#859900, .35),
+ solarized_dark_button_head_chosen : #39800d,
+
+ solarized_dark_header_origin_neutral : rgba(#2878c9, .35),
+ solarized_dark_line_origin_neutral : rgba(#2878c9, .15),
+ solarized_dark_button_origin_neutral : #086799,
+
+ solarized_dark_header_origin_chosen : rgba(#2878c9, .6),
+ solarized_dark_line_origin_chosen : rgba(#2878c9, .35),
+ solarized_dark_button_origin_chosen : #0082cc,
+
+ solarized_dark_header_not_chosen : rgba(#839496, .25),
+ solarized_dark_line_not_chosen : rgba(#839496, .15)
+);
+
+
+@mixin color-scheme($color) {
+ .header.line_content, .diff-line-num {
+ &.origin {
+ background-color: map-get($colors, #{$color}_header_origin_neutral);
+ border-color: map-get($colors, #{$color}_header_origin_neutral);
+
+ button {
+ background-color: map-get($colors, #{$color}_button_origin_neutral);
+ border-color: darken(map-get($colors, #{$color}_button_origin_neutral), 15);
+ }
+
+ &.selected {
+ background-color: map-get($colors, #{$color}_header_origin_chosen);
+ border-color: map-get($colors, #{$color}_header_origin_chosen);
+
+ button {
+ background-color: map-get($colors, #{$color}_button_origin_chosen);
+ border-color: darken(map-get($colors, #{$color}_button_origin_chosen), 15);
+ }
+ }
+
+ &.unselected {
+ background-color: map-get($colors, #{$color}_header_not_chosen);
+ border-color: map-get($colors, #{$color}_header_not_chosen);
+
+ button {
+ background-color: lighten(map-get($colors, #{$color}_button_origin_neutral), 15);
+ border-color: map-get($colors, #{$color}_button_origin_neutral);
+ }
+ }
+ }
+ &.head {
+ background-color: map-get($colors, #{$color}_header_head_neutral);
+ border-color: map-get($colors, #{$color}_header_head_neutral);
+
+ button {
+ background-color: map-get($colors, #{$color}_button_head_neutral);
+ border-color: darken(map-get($colors, #{$color}_button_head_neutral), 15);
+ }
+
+ &.selected {
+ background-color: map-get($colors, #{$color}_header_head_chosen);
+ border-color: map-get($colors, #{$color}_header_head_chosen);
+
+ button {
+ background-color: map-get($colors, #{$color}_button_head_chosen);
+ border-color: darken(map-get($colors, #{$color}_button_head_chosen), 15);
+ }
+ }
+
+ &.unselected {
+ background-color: map-get($colors, #{$color}_header_not_chosen);
+ border-color: map-get($colors, #{$color}_header_not_chosen);
+
+ button {
+ background-color: lighten(map-get($colors, #{$color}_button_head_neutral), 15);
+ border-color: map-get($colors, #{$color}_button_head_neutral);
+ }
+ }
+ }
+ }
+
+ .line_content {
+ &.origin {
+ background-color: map-get($colors, #{$color}_line_origin_neutral);
+
+ &.selected {
+ background-color: map-get($colors, #{$color}_line_origin_chosen);
+ }
+
+ &.unselected {
+ background-color: map-get($colors, #{$color}_line_not_chosen);
+ }
+ }
+ &.head {
+ background-color: map-get($colors, #{$color}_line_head_neutral);
+
+ &.selected {
+ background-color: map-get($colors, #{$color}_line_head_chosen);
+ }
+
+ &.unselected {
+ background-color: map-get($colors, #{$color}_line_not_chosen);
+ }
+ }
+ }
+}
+
+
+#conflicts {
+
+ .white {
+ @include color-scheme('white')
+ }
+
+ .dark {
+ @include color-scheme('dark')
+ }
+
+ .monokai {
+ @include color-scheme('monokai')
+ }
+
+ .solarized-light {
+ @include color-scheme('solarized_light')
+ }
+
+ .solarized-dark {
+ @include color-scheme('solarized_dark')
+ }
+
+ .diff-wrap-lines .line_content {
+ white-space: normal;
+ min-height: 19px;
+ }
+
+ .line_content.header {
+ position: relative;
+
+ button {
+ border-radius: 2px;
+ font-size: 10px;
+ position: absolute;
+ right: 10px;
+ padding: 0;
+ outline: none;
+ color: #fff;
+ width: 75px; // static width to make 2 buttons have same width
+ height: 19px;
+ }
+ }
+
+ .btn-success .fa-spinner {
+ color: #fff;
+ }
+}
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index 30239d609bc..ce1c424624f 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -410,3 +410,15 @@
color: $dropdown-header-color;
}
}
+
+.pipelines.tab-pane {
+
+ .content-list.pipelines {
+ overflow: scroll;
+ }
+
+ .stage {
+ max-width: 60px;
+ width: 60px;
+ }
+}
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 139680d2df9..bb793cce223 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -9,15 +9,15 @@ class Projects::MergeRequestsController < Projects::ApplicationController
before_action :module_enabled
before_action :merge_request, only: [
- :edit, :update, :show, :diffs, :commits, :builds, :merge, :merge_check,
- :ci_status, :toggle_subscription, :cancel_merge_when_build_succeeds, :remove_wip
+ :edit, :update, :show, :diffs, :commits, :conflicts, :builds, :pipelines, :merge, :merge_check,
+ :ci_status, :toggle_subscription, :cancel_merge_when_build_succeeds, :remove_wip, :resolve_conflicts
]
- before_action :validates_merge_request, only: [:show, :diffs, :commits, :builds]
- before_action :define_show_vars, only: [:show, :diffs, :commits, :builds]
+ before_action :validates_merge_request, only: [:show, :diffs, :commits, :builds, :pipelines]
+ before_action :define_show_vars, only: [:show, :diffs, :commits, :conflicts, :builds, :pipelines]
before_action :define_widget_vars, only: [:merge, :cancel_merge_when_build_succeeds, :merge_check]
before_action :define_commit_vars, only: [:diffs]
before_action :define_diff_comment_vars, only: [:diffs]
- before_action :ensure_ref_fetched, only: [:show, :diffs, :commits, :builds]
+ before_action :ensure_ref_fetched, only: [:show, :diffs, :commits, :builds, :conflicts, :pipelines]
# Allow read any merge_request
before_action :authorize_read_merge_request!
@@ -28,6 +28,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
# Allow modify merge_request
before_action :authorize_update_merge_request!, only: [:close, :edit, :update, :remove_wip, :sort]
+ before_action :authorize_can_resolve_conflicts!, only: [:conflicts, :resolve_conflicts]
+
def index
terms = params['issue_search']
@merge_requests = merge_requests_collection
@@ -130,6 +132,47 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
end
+ def conflicts
+ respond_to do |format|
+ format.html { define_discussion_vars }
+
+ format.json do
+ if @merge_request.conflicts_can_be_resolved_in_ui?
+ render json: @merge_request.conflicts
+ elsif @merge_request.can_be_merged?
+ render json: {
+ message: 'The merge conflicts for this merge request have already been resolved. Please return to the merge request.',
+ type: 'error'
+ }
+ else
+ render json: {
+ message: 'The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally.',
+ type: 'error'
+ }
+ end
+ end
+ end
+ end
+
+ def resolve_conflicts
+ return render_404 unless @merge_request.conflicts_can_be_resolved_in_ui?
+
+ if @merge_request.can_be_merged?
+ render status: :bad_request, json: { message: 'The merge conflicts for this merge request have already been resolved.' }
+ return
+ end
+
+ begin
+ MergeRequests::ResolveService.new(@merge_request.source_project, current_user, params).execute(@merge_request)
+
+ flash[:notice] = 'All merge conflicts were resolved. The merge request can now be merged.'
+
+ render json: { redirect_to: namespace_project_merge_request_url(@project.namespace, @project, @merge_request, resolved_conflicts: true) }
+ rescue Gitlab::Conflict::File::MissingResolution => e
+ render status: :bad_request, json: { message: e.message }
+ end
+ end
+
def builds
respond_to do |format|
format.html do
@@ -141,6 +184,19 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
end
+ def pipelines
+ @pipelines = @merge_request.all_pipelines
+
+ respond_to do |format|
+ format.html do
+ define_discussion_vars
+
+ render 'show'
+ end
+ format.json { render json: { html: view_to_html_string('projects/merge_requests/show/_pipelines') } }
+ end
+ end
+
def new
build_merge_request
@noteable = @merge_request
@@ -338,6 +394,10 @@ class Projects::MergeRequestsController < Projects::ApplicationController
return render_404 unless can?(current_user, :admin_merge_request, @merge_request)
end
+ def authorize_can_resolve_conflicts!
+ return render_404 unless @merge_request.conflicts_can_be_resolved_by?(current_user)
+ end
+
def module_enabled
return render_404 unless @project.merge_requests_enabled
end
@@ -412,7 +472,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
noteable_id: @merge_request.id
}
- @use_legacy_diff_notes = !@merge_request.support_new_diff_notes?
+ @use_legacy_diff_notes = !@merge_request.has_complete_diff_refs?
@grouped_diff_discussions = @merge_request.notes.inc_author_project_award_emoji.grouped_diff_discussions
Banzai::NoteRenderer.render(
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index 7a02d0b10d9..33dcee49aee 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -98,28 +98,31 @@ module CommitsHelper
end
def link_to_browse_code(project, commit)
- if current_controller?(:projects, :commits)
- if @repo.blob_at(commit.id, @path)
- return link_to(
- "Browse File",
- namespace_project_blob_path(project.namespace, project,
- tree_join(commit.id, @path)),
- class: "btn btn-default"
- )
- elsif @path.present?
- return link_to(
- "Browse Directory",
- namespace_project_tree_path(project.namespace, project,
- tree_join(commit.id, @path)),
- class: "btn btn-default"
- )
- end
+ if @path.blank?
+ return link_to(
+ "Browse Files",
+ namespace_project_tree_path(project.namespace, project, commit),
+ class: "btn btn-default"
+ )
+ end
+
+ return unless current_controller?(:projects, :commits)
+
+ if @repo.blob_at(commit.id, @path)
+ return link_to(
+ "Browse File",
+ namespace_project_blob_path(project.namespace, project,
+ tree_join(commit.id, @path)),
+ class: "btn btn-default"
+ )
+ elsif @path.present?
+ return link_to(
+ "Browse Directory",
+ namespace_project_tree_path(project.namespace, project,
+ tree_join(commit.id, @path)),
+ class: "btn btn-default"
+ )
end
- link_to(
- "Browse Files",
- namespace_project_tree_path(project.namespace, project, commit),
- class: "btn btn-default"
- )
end
def revert_commit_link(commit, continue_to_path, btn_class: nil, has_tooltip: true)
diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb
index 3ff8be5e284..6c1cc6ef072 100644
--- a/app/helpers/nav_helper.rb
+++ b/app/helpers/nav_helper.rb
@@ -24,6 +24,7 @@ module NavHelper
current_path?('merge_requests#diffs') ||
current_path?('merge_requests#commits') ||
current_path?('merge_requests#builds') ||
+ current_path?('merge_requests#conflicts') ||
current_path?('issues#show')
if cookies[:collapsed_gutter] == 'true'
"page-gutter right-sidebar-collapsed"
diff --git a/app/models/diff_note.rb b/app/models/diff_note.rb
index c816deb4e0c..e02a3d54c36 100644
--- a/app/models/diff_note.rb
+++ b/app/models/diff_note.rb
@@ -75,7 +75,7 @@ class DiffNote < Note
private
def supported?
- !self.for_merge_request? || self.noteable.support_new_diff_notes?
+ !self.for_merge_request? || self.noteable.has_complete_diff_refs?
end
def noteable_diff_refs
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index fe799382fd0..4304ef04767 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -674,10 +674,21 @@ class MergeRequest < ActiveRecord::Base
diverged_commits_count > 0
end
+ def commits_sha
+ commits.map(&:sha)
+ end
+
def pipeline
@pipeline ||= source_project.pipeline(diff_head_sha, source_branch) if diff_head_sha && source_project
end
+ def all_pipelines
+ @all_pipelines ||=
+ if diff_head_sha && source_project
+ source_project.pipelines.order(id: :desc).where(sha: commits_sha, ref: source_branch)
+ end
+ end
+
def merge_commit
@merge_commit ||= project.commit(merge_commit_sha) if merge_commit_sha
end
@@ -690,12 +701,12 @@ class MergeRequest < ActiveRecord::Base
merge_commit
end
- def support_new_diff_notes?
+ def has_complete_diff_refs?
diff_sha_refs && diff_sha_refs.complete?
end
def update_diff_notes_positions(old_diff_refs:, new_diff_refs:)
- return unless support_new_diff_notes?
+ return unless has_complete_diff_refs?
return if new_diff_refs == old_diff_refs
active_diff_notes = self.notes.diff_notes.select do |note|
@@ -723,4 +734,26 @@ class MergeRequest < ActiveRecord::Base
def keep_around_commit
project.repository.keep_around(self.merge_commit_sha)
end
+
+ def conflicts
+ @conflicts ||= Gitlab::Conflict::FileCollection.new(self)
+ end
+
+ def conflicts_can_be_resolved_by?(user)
+ access = ::Gitlab::UserAccess.new(user, project: source_project)
+ access.can_push_to_branch?(source_branch)
+ end
+
+ def conflicts_can_be_resolved_in_ui?
+ return @conflicts_can_be_resolved_in_ui if defined?(@conflicts_can_be_resolved_in_ui)
+
+ return @conflicts_can_be_resolved_in_ui = false unless cannot_be_merged?
+ return @conflicts_can_be_resolved_in_ui = false unless has_complete_diff_refs?
+
+ begin
+ @conflicts_can_be_resolved_in_ui = conflicts.files.each(&:lines)
+ rescue Gitlab::Conflict::Parser::ParserError, Gitlab::Conflict::FileCollection::ConflictSideMissing
+ @conflicts_can_be_resolved_in_ui = false
+ end
+ end
end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index e56bac509a4..01b02ccc0dc 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -869,6 +869,14 @@ class Repository
end
end
+ def resolve_conflicts(user, branch, params)
+ commit_with_hooks(user, branch) do
+ committer = user_to_committer(user)
+
+ Rugged::Commit.create(rugged, params.merge(author: committer, committer: committer))
+ end
+ end
+
def check_revert_content(commit, base_branch)
source_sha = find_branch(base_branch).target.sha
args = [commit.id, source_sha]
diff --git a/app/services/merge_requests/resolve_service.rb b/app/services/merge_requests/resolve_service.rb
new file mode 100644
index 00000000000..adc71b0c2bc
--- /dev/null
+++ b/app/services/merge_requests/resolve_service.rb
@@ -0,0 +1,31 @@
+module MergeRequests
+ class ResolveService < MergeRequests::BaseService
+ attr_accessor :conflicts, :rugged, :merge_index
+
+ def execute(merge_request)
+ @conflicts = merge_request.conflicts
+ @rugged = project.repository.rugged
+ @merge_index = conflicts.merge_index
+
+ conflicts.files.each do |file|
+ write_resolved_file_to_index(file, params[:sections])
+ end
+
+ commit_params = {
+ message: params[:commit_message] || conflicts.default_commit_message,
+ parents: [conflicts.our_commit, conflicts.their_commit].map(&:oid),
+ tree: merge_index.write_tree(rugged)
+ }
+
+ project.repository.resolve_conflicts(current_user, merge_request.source_branch, commit_params)
+ end
+
+ def write_resolved_file_to_index(file, resolutions)
+ new_file = file.resolve_lines(resolutions).map(&:text).join("\n")
+ our_path = file.our_path
+
+ merge_index.add(path: our_path, oid: rugged.write(new_file, :blob), mode: file.our_mode)
+ merge_index.conflict_remove(our_path)
+ end
+ end
+end
diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml
index 78709a92aed..be387201f8d 100644
--- a/app/views/projects/ci/pipelines/_pipeline.html.haml
+++ b/app/views/projects/ci/pipelines/_pipeline.html.haml
@@ -2,19 +2,21 @@
%tr.commit
%td.commit-link
= link_to namespace_project_pipeline_path(@project.namespace, @project, pipeline.id) do
- = ci_status_with_icon(status)
-
-
+ - if defined?(status_icon_only) && status_icon_only
+ = ci_icon_for_status(status)
+ - else
+ = ci_status_with_icon(status)
%td
.branch-commit
= link_to namespace_project_pipeline_path(@project.namespace, @project, pipeline.id) do
%span ##{pipeline.id}
- if pipeline.ref
- .icon-container
- = pipeline.tag? ? icon('tag') : icon('code-fork')
- = link_to pipeline.ref, namespace_project_commits_path(@project.namespace, @project, pipeline.ref), class: "monospace branch-name"
- .icon-container
- = custom_icon("icon_commit")
+ - unless defined?(hide_branch) && hide_branch
+ .icon-container
+ = pipeline.tag? ? icon('tag') : icon('code-fork')
+ = link_to pipeline.ref, namespace_project_commits_path(@project.namespace, @project, pipeline.ref), class: "monospace branch-name"
+ .icon-container
+ = custom_icon("icon_commit")
= link_to pipeline.short_sha, namespace_project_commit_path(@project.namespace, @project, pipeline.sha), class: "commit-id monospace"
- if pipeline.latest?
%span.label.label-success.has-tooltip{ title: 'Latest build for this branch' } latest
@@ -53,7 +55,7 @@
- if pipeline.finished_at
%p.finished-at
= icon("calendar")
- #{time_ago_with_tooltip(pipeline.finished_at, short_format: true, skip_js: true)}
+ #{time_ago_with_tooltip(pipeline.finished_at, short_format: false, skip_js: true)}
%td.pipeline-actions
.controls.hidden-xs.pull-right
diff --git a/app/views/projects/commit/_pipelines_list.haml b/app/views/projects/commit/_pipelines_list.haml
new file mode 100644
index 00000000000..29f4ef8f49e
--- /dev/null
+++ b/app/views/projects/commit/_pipelines_list.haml
@@ -0,0 +1,17 @@
+%ul.content-list.pipelines
+ - if pipelines.blank?
+ %li
+ .nothing-here-block No pipelines to show
+ - else
+ .table-holder
+ %table.table.builds
+ %tbody
+ %th Status
+ %th Commit
+ - pipelines.stages.each do |stage|
+ %th.stage
+ %span.has-tooltip{ title: "#{stage.titleize}" }
+ = stage.titleize
+ %th
+ %th
+ = render pipelines, commit_sha: true, stage: true, allow_retry: true, stages: pipelines.stages, status_icon_only: true, hide_branch: true
diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml
index 269198adf91..a1313064725 100644
--- a/app/views/projects/merge_requests/_show.html.haml
+++ b/app/views/projects/merge_requests/_show.html.haml
@@ -45,20 +45,24 @@
- if @commits_count.nonzero?
%ul.merge-request-tabs.nav-links.no-top.no-bottom
%li.notes-tab
- = link_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#notes', action: 'notes', toggle: 'tab'} do
+ = link_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: 'div#notes', action: 'notes', toggle: 'tab' } do
Discussion
%span.badge= @merge_request.mr_and_commit_notes.user.count
%li.commits-tab
- = link_to commits_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#commits', action: 'commits', toggle: 'tab'} do
+ = link_to commits_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: 'div#commits', action: 'commits', toggle: 'tab' } do
Commits
%span.badge= @commits_count
- if @pipeline
+ %li.pipelines-tab
+ = link_to pipelines_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: '#pipelines', action: 'pipelines', toggle: 'tab' } do
+ Pipelines
+ %span.badge= @merge_request.all_pipelines.size
%li.builds-tab
- = link_to builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: '#builds', action: 'builds', toggle: 'tab'} do
+ = link_to builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: '#builds', action: 'builds', toggle: 'tab' } do
Builds
%span.badge= @statuses.size
%li.diffs-tab
- = link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#diffs', action: 'diffs', toggle: 'tab'} do
+ = link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: 'div#diffs', action: 'diffs', toggle: 'tab' } do
Changes
%span.badge= @merge_request.diff_size
@@ -76,6 +80,8 @@
- # This tab is always loaded via AJAX
#builds.builds.tab-pane
- # This tab is always loaded via AJAX
+ #pipelines.pipelines.tab-pane
+ - # This tab is always loaded via AJAX
#diffs.diffs.tab-pane
- # This tab is always loaded via AJAX
diff --git a/app/views/projects/merge_requests/conflicts.html.haml b/app/views/projects/merge_requests/conflicts.html.haml
new file mode 100644
index 00000000000..a524936f73c
--- /dev/null
+++ b/app/views/projects/merge_requests/conflicts.html.haml
@@ -0,0 +1,29 @@
+- class_bindings = "{ |
+ 'head': line.isHead, |
+ 'origin': line.isOrigin, |
+ 'match': line.hasMatch, |
+ 'selected': line.isSelected, |
+ 'unselected': line.isUnselected }"
+
+- page_title "Merge Conflicts", "#{@merge_request.title} (#{@merge_request.to_reference}", "Merge Requests"
+= render "projects/merge_requests/show/mr_title"
+
+.merge-request-details.issuable-details
+ = render "projects/merge_requests/show/mr_box"
+
+= render 'shared/issuable/sidebar', issuable: @merge_request
+
+#conflicts{"v-cloak" => "true", data: { conflicts_path: conflicts_namespace_project_merge_request_path(@merge_request.project.namespace, @merge_request.project, @merge_request, format: :json),
+ resolve_conflicts_path: resolve_conflicts_namespace_project_merge_request_path(@merge_request.project.namespace, @merge_request.project, @merge_request) } }
+ .loading{"v-if" => "isLoading"}
+ %i.fa.fa-spinner.fa-spin
+
+ .nothing-here-block{"v-if" => "hasError"}
+ {{conflictsData.errorMessage}}
+
+ = render partial: "projects/merge_requests/conflicts/commit_stats"
+
+ .files-wrapper{"v-if" => "!isLoading && !hasError"}
+ = render partial: "projects/merge_requests/conflicts/parallel_view", locals: { class_bindings: class_bindings }
+ = render partial: "projects/merge_requests/conflicts/inline_view", locals: { class_bindings: class_bindings }
+ = render partial: "projects/merge_requests/conflicts/submit_form"
diff --git a/app/views/projects/merge_requests/conflicts/_commit_stats.html.haml b/app/views/projects/merge_requests/conflicts/_commit_stats.html.haml
new file mode 100644
index 00000000000..457c467fba9
--- /dev/null
+++ b/app/views/projects/merge_requests/conflicts/_commit_stats.html.haml
@@ -0,0 +1,20 @@
+.content-block.oneline-block.files-changed{"v-if" => "!isLoading && !hasError"}
+ .inline-parallel-buttons
+ .btn-group
+ %a.btn{ |
+ ":class" => "{'active': !isParallel}", |
+ "@click" => "handleViewTypeChange('inline')"}
+ Inline
+ %a.btn{ |
+ ":class" => "{'active': isParallel}", |
+ "@click" => "handleViewTypeChange('parallel')"}
+ Side-by-side
+
+ .js-toggle-container
+ .commit-stat-summary
+ Showing
+ %strong.cred {{conflictsCount}} {{conflictsData.conflictsText}}
+ between
+ %strong {{conflictsData.source_branch}}
+ and
+ %strong {{conflictsData.target_branch}}
diff --git a/app/views/projects/merge_requests/conflicts/_inline_view.html.haml b/app/views/projects/merge_requests/conflicts/_inline_view.html.haml
new file mode 100644
index 00000000000..19c7da4b5e3
--- /dev/null
+++ b/app/views/projects/merge_requests/conflicts/_inline_view.html.haml
@@ -0,0 +1,28 @@
+.files{"v-show" => "!isParallel"}
+ .diff-file.file-holder.conflict.inline-view{"v-for" => "file in conflictsData.files"}
+ .file-title
+ %i.fa.fa-fw{":class" => "file.iconClass"}
+ %strong {{file.filePath}}
+ .file-actions
+ %a.btn.view-file.btn-file-option{":href" => "file.blobPath"}
+ View file @{{conflictsData.shortCommitSha}}
+
+ .diff-content.diff-wrap-lines
+ .diff-wrap-lines.code.file-content.js-syntax-highlight
+ %table
+ %tr.line_holder.diff-inline{"v-for" => "line in file.inlineLines"}
+ %template{"v-if" => "!line.isHeader"}
+ %td.diff-line-num.new_line{":class" => class_bindings}
+ %a {{line.new_line}}
+ %td.diff-line-num.old_line{":class" => class_bindings}
+ %a {{line.old_line}}
+ %td.line_content{":class" => class_bindings}
+ {{{line.richText}}}
+
+ %template{"v-if" => "line.isHeader"}
+ %td.diff-line-num.header{":class" => class_bindings}
+ %td.diff-line-num.header{":class" => class_bindings}
+ %td.line_content.header{":class" => class_bindings}
+ %strong {{{line.richText}}}
+ %button.btn{"@click" => "handleSelected(line.id, line.section)"}
+ {{line.buttonTitle}}
diff --git a/app/views/projects/merge_requests/conflicts/_parallel_view.html.haml b/app/views/projects/merge_requests/conflicts/_parallel_view.html.haml
new file mode 100644
index 00000000000..2e6f67c2eaf
--- /dev/null
+++ b/app/views/projects/merge_requests/conflicts/_parallel_view.html.haml
@@ -0,0 +1,27 @@
+.files{"v-show" => "isParallel"}
+ .diff-file.file-holder.conflict.parallel-view{"v-for" => "file in conflictsData.files"}
+ .file-title
+ %i.fa.fa-fw{":class" => "file.iconClass"}
+ %strong {{file.filePath}}
+ .file-actions
+ %a.btn.view-file.btn-file-option{":href" => "file.blobPath"}
+ View file @{{conflictsData.shortCommitSha}}
+
+ .diff-content.diff-wrap-lines
+ .diff-wrap-lines.code.file-content.js-syntax-highlight
+ %table
+ %tr.line_holder.parallel{"v-for" => "section in file.parallelLines"}
+ %template{"v-for" => "line in section"}
+
+ %template{"v-if" => "line.isHeader"}
+ %td.diff-line-num.header{":class" => class_bindings}
+ %td.line_content.header{":class" => class_bindings}
+ %strong {{line.richText}}
+ %button.btn{"@click" => "handleSelected(line.id, line.section)"}
+ {{line.buttonTitle}}
+
+ %template{"v-if" => "!line.isHeader"}
+ %td.diff-line-num.old_line{":class" => class_bindings}
+ {{line.lineNumber}}
+ %td.line_content.parallel{":class" => class_bindings}
+ {{{line.richText}}}
diff --git a/app/views/projects/merge_requests/conflicts/_submit_form.html.haml b/app/views/projects/merge_requests/conflicts/_submit_form.html.haml
new file mode 100644
index 00000000000..78bd4133ea2
--- /dev/null
+++ b/app/views/projects/merge_requests/conflicts/_submit_form.html.haml
@@ -0,0 +1,15 @@
+.content-block.oneline-block.files-changed
+ %strong.resolved-count {{resolvedCount}}
+ of
+ %strong.total-count {{conflictsCount}}
+ conflicts have been resolved
+
+ .commit-message-container.form-group
+ .max-width-marker
+ %textarea.form-control.js-commit-message{"v-model" => "conflictsData.commitMessage"}
+ {{{conflictsData.commitMessage}}}
+
+ %button{type: "button", class: "btn btn-success js-submit-button", ":disabled" => "!readyToCommit", "@click" => "commit()"}
+ %span {{commitButtonText}}
+
+ = link_to "Cancel", namespace_project_merge_request_path(@merge_request.project.namespace, @merge_request.project, @merge_request), class: "btn btn-cancel"
diff --git a/app/views/projects/merge_requests/show/_builds.html.haml b/app/views/projects/merge_requests/show/_builds.html.haml
index 81de60f116c..808ef7fed27 100644
--- a/app/views/projects/merge_requests/show/_builds.html.haml
+++ b/app/views/projects/merge_requests/show/_builds.html.haml
@@ -1,2 +1 @@
= render "projects/commit/pipeline", pipeline: @pipeline, link_to_commit: true
-
diff --git a/app/views/projects/merge_requests/show/_pipelines.html.haml b/app/views/projects/merge_requests/show/_pipelines.html.haml
new file mode 100644
index 00000000000..afe3f3430c6
--- /dev/null
+++ b/app/views/projects/merge_requests/show/_pipelines.html.haml
@@ -0,0 +1 @@
+= render "projects/commit/pipelines_list", pipelines: @pipelines, link_to_commit: true
diff --git a/app/views/projects/merge_requests/widget/_merged.html.haml b/app/views/projects/merge_requests/widget/_merged.html.haml
index 19b5d0ff066..7794d6d7df2 100644
--- a/app/views/projects/merge_requests/widget/_merged.html.haml
+++ b/app/views/projects/merge_requests/widget/_merged.html.haml
@@ -6,7 +6,7 @@
- if @merge_request.merge_event
by #{link_to_member(@project, @merge_request.merge_event.author, avatar: true)}
#{time_ago_with_tooltip(@merge_request.merge_event.created_at)}
- - if !@merge_request.source_branch_exists? || (params[:delete_source] == 'true')
+ - if !@merge_request.source_branch_exists? || params[:deleted_source_branch]
%p
The changes were merged into
#{link_to @merge_request.target_branch, namespace_project_commits_path(@project.namespace, @project, @merge_request.target_branch), class: "label-branch"}.
diff --git a/app/views/projects/merge_requests/widget/_open.html.haml b/app/views/projects/merge_requests/widget/_open.html.haml
index dc18f715f25..6f5ee5f16c5 100644
--- a/app/views/projects/merge_requests/widget/_open.html.haml
+++ b/app/views/projects/merge_requests/widget/_open.html.haml
@@ -1,6 +1,12 @@
.mr-state-widget
= render 'projects/merge_requests/widget/heading'
.mr-widget-body
+ -# After conflicts are resolved, the user is redirected back to the MR page.
+ -# There is a short window before background workers run and GitLab processes
+ -# the new push and commits, during which it will think the conflicts still exist.
+ -# We send this param to get the widget to treat the MR as having no more conflicts.
+ - resolved_conflicts = params[:resolved_conflicts]
+
- if @project.archived?
= render 'projects/merge_requests/widget/open/archived'
- elsif @merge_request.commits.blank?
@@ -9,7 +15,7 @@
= render 'projects/merge_requests/widget/open/missing_branch'
- elsif @merge_request.unchecked?
= render 'projects/merge_requests/widget/open/check'
- - elsif @merge_request.cannot_be_merged?
+ - elsif @merge_request.cannot_be_merged? && !resolved_conflicts
= render 'projects/merge_requests/widget/open/conflicts'
- elsif @merge_request.work_in_progress?
= render 'projects/merge_requests/widget/open/wip'
@@ -19,7 +25,7 @@
= render 'projects/merge_requests/widget/open/not_allowed'
- elsif !@merge_request.mergeable_ci_state? && @pipeline && @pipeline.failed?
= render 'projects/merge_requests/widget/open/build_failed'
- - elsif @merge_request.can_be_merged?
+ - elsif @merge_request.can_be_merged? || resolved_conflicts
= render 'projects/merge_requests/widget/open/accept'
- if mr_closes_issues.present?
diff --git a/app/views/projects/merge_requests/widget/_show.html.haml b/app/views/projects/merge_requests/widget/_show.html.haml
index d9efe81701f..ea618263a4a 100644
--- a/app/views/projects/merge_requests/widget/_show.html.haml
+++ b/app/views/projects/merge_requests/widget/_show.html.haml
@@ -23,7 +23,8 @@
preparing: "{{status}} build",
normal: "Build {{status}}"
},
- builds_path: "#{builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}"
+ builds_path: "#{builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}",
+ pipelines_path: "#{pipelines_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}"
};
if (typeof merge_request_widget !== 'undefined') {
diff --git a/app/views/projects/merge_requests/widget/open/_conflicts.html.haml b/app/views/projects/merge_requests/widget/open/_conflicts.html.haml
index f000cc38a65..af3096f04d9 100644
--- a/app/views/projects/merge_requests/widget/open/_conflicts.html.haml
+++ b/app/views/projects/merge_requests/widget/open/_conflicts.html.haml
@@ -3,7 +3,18 @@
This merge request contains merge conflicts
%p
- Please resolve these conflicts or
+ Please
+ - if @merge_request.conflicts_can_be_resolved_by?(current_user)
+ - if @merge_request.conflicts_can_be_resolved_in_ui?
+ = link_to "resolve these conflicts", conflicts_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)
+ - else
+ %span.has-tooltip{title: "These conflicts cannot be resolved through GitLab"}
+ resolve these conflicts locally
+ - else
+ resolve these conflicts
+
+ or
+
- if @merge_request.can_be_merged_via_command_line_by?(current_user)
#{link_to "merge this request manually", "#modal_merge_info", class: "how_to_merge_link vlink", "data-toggle" => "modal"}.
- else
diff --git a/config/routes.rb b/config/routes.rb
index 63a8827a6a2..58e824c0476 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -727,7 +727,9 @@ Rails.application.routes.draw do
member do
get :commits
get :diffs
+ get :conflicts
get :builds
+ get :pipelines
get :merge_check
post :merge
post :cancel_merge_when_build_succeeds
@@ -736,6 +738,7 @@ Rails.application.routes.draw do
post :toggle_award_emoji
post :remove_wip
get :diff_for_path
+ post :resolve_conflicts
end
collection do
diff --git a/doc/user/project/merge_requests/img/conflict_section.png b/doc/user/project/merge_requests/img/conflict_section.png
new file mode 100644
index 00000000000..842e50b14b2
--- /dev/null
+++ b/doc/user/project/merge_requests/img/conflict_section.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/merge_request_widget.png b/doc/user/project/merge_requests/img/merge_request_widget.png
new file mode 100644
index 00000000000..ffb96b17b07
--- /dev/null
+++ b/doc/user/project/merge_requests/img/merge_request_widget.png
Binary files differ
diff --git a/doc/user/project/merge_requests/resolve_conflicts.md b/doc/user/project/merge_requests/resolve_conflicts.md
new file mode 100644
index 00000000000..44b76ffc8e6
--- /dev/null
+++ b/doc/user/project/merge_requests/resolve_conflicts.md
@@ -0,0 +1,41 @@
+# Merge conflict resolution
+
+> [Introduced][ce-5479] in GitLab 8.11.
+
+When a merge request has conflicts, GitLab may provide the option to resolve
+those conflicts in the GitLab UI. (See
+[conflicts available for resolution](#conflicts-available-for-resolution) for
+more information on when this is available.) If this is an option, you will see
+a **resolve these conflicts** link in the merge request widget:
+
+![Merge request widget](img/merge_request_widget.png)
+
+Clicking this will show a list of files with conflicts, with conflict sections
+highlighted:
+
+![Conflict section](img/conflict_section.png)
+
+Once all conflicts have been marked as using 'ours' or 'theirs', the conflict
+can be resolved. This will perform a merge of the target branch of the merge
+request into the source branch, resolving the conflicts using the options
+chosen. If the source branch is `feature` and the target branch is `master`,
+this is similar to performing `git checkout feature; git merge master` locally.
+
+## Conflicts available for resolution
+
+GitLab allows resolving conflicts in a file where all of the below are true:
+
+- The file is text, not binary
+- The file does not already contain conflict markers
+- The file, with conflict markers added, is not over 200 KB in size
+- The file exists under the same path in both branches
+
+If any file with conflicts in that merge request does not meet all of these
+criteria, the conflicts for that merge request cannot be resolved in the UI.
+
+Additionally, GitLab does not detect conflicts in renames away from a path. For
+example, this will not create a conflict: on branch `a`, doing `git mv file1
+file2`; on branch `b`, doing `git mv file1 file3`. Instead, both files will be
+present in the branch after the merge request is merged.
+
+[ce-5479]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5479
diff --git a/lib/gitlab/conflict/file.rb b/lib/gitlab/conflict/file.rb
new file mode 100644
index 00000000000..0a1fd27ced5
--- /dev/null
+++ b/lib/gitlab/conflict/file.rb
@@ -0,0 +1,186 @@
+module Gitlab
+ module Conflict
+ class File
+ include Gitlab::Routing.url_helpers
+ include IconsHelper
+
+ class MissingResolution < StandardError
+ end
+
+ CONTEXT_LINES = 3
+
+ attr_reader :merge_file_result, :their_path, :our_path, :our_mode, :merge_request, :repository
+
+ def initialize(merge_file_result, conflict, merge_request:)
+ @merge_file_result = merge_file_result
+ @their_path = conflict[:theirs][:path]
+ @our_path = conflict[:ours][:path]
+ @our_mode = conflict[:ours][:mode]
+ @merge_request = merge_request
+ @repository = merge_request.project.repository
+ @match_line_headers = {}
+ end
+
+ # Array of Gitlab::Diff::Line objects
+ def lines
+ @lines ||= Gitlab::Conflict::Parser.new.parse(merge_file_result[:data],
+ our_path: our_path,
+ their_path: their_path,
+ parent_file: self)
+ end
+
+ def resolve_lines(resolution)
+ section_id = nil
+
+ lines.map do |line|
+ unless line.type
+ section_id = nil
+ next line
+ end
+
+ section_id ||= line_code(line)
+
+ case resolution[section_id]
+ when 'head'
+ next unless line.type == 'new'
+ when 'origin'
+ next unless line.type == 'old'
+ else
+ raise MissingResolution, "Missing resolution for section ID: #{section_id}"
+ end
+
+ line
+ end.compact
+ end
+
+ def highlight_lines!
+ their_file = lines.reject { |line| line.type == 'new' }.map(&:text).join("\n")
+ our_file = lines.reject { |line| line.type == 'old' }.map(&:text).join("\n")
+
+ their_highlight = Gitlab::Highlight.highlight(their_path, their_file, repository: repository).lines
+ our_highlight = Gitlab::Highlight.highlight(our_path, our_file, repository: repository).lines
+
+ lines.each do |line|
+ if line.type == 'old'
+ line.rich_text = their_highlight[line.old_line - 1].try(:html_safe)
+ else
+ line.rich_text = our_highlight[line.new_line - 1].try(:html_safe)
+ end
+ end
+ end
+
+ def sections
+ return @sections if @sections
+
+ chunked_lines = lines.chunk { |line| line.type.nil? }.to_a
+ match_line = nil
+
+ sections_count = chunked_lines.size
+
+ @sections = chunked_lines.flat_map.with_index do |(no_conflict, lines), i|
+ section = nil
+
+ # We need to reduce context sections to CONTEXT_LINES. Conflict sections are
+ # always shown in full.
+ if no_conflict
+ conflict_before = i > 0
+ conflict_after = (sections_count - i) > 1
+
+ if conflict_before && conflict_after
+ # Create a gap in a long context section.
+ if lines.length > CONTEXT_LINES * 2
+ head_lines = lines.first(CONTEXT_LINES)
+ tail_lines = lines.last(CONTEXT_LINES)
+
+ # Ensure any existing match line has text for all lines up to the last
+ # line of its context.
+ update_match_line_text(match_line, head_lines.last)
+
+ # Insert a new match line after the created gap.
+ match_line = create_match_line(tail_lines.first)
+
+ section = [
+ { conflict: false, lines: head_lines },
+ { conflict: false, lines: tail_lines.unshift(match_line) }
+ ]
+ end
+ elsif conflict_after
+ tail_lines = lines.last(CONTEXT_LINES)
+
+ # Create a gap and insert a match line at the start.
+ if lines.length > tail_lines.length
+ match_line = create_match_line(tail_lines.first)
+
+ tail_lines.unshift(match_line)
+ end
+
+ lines = tail_lines
+ elsif conflict_before
+ # We're at the end of the file (no conflicts after), so just remove extra
+ # trailing lines.
+ lines = lines.first(CONTEXT_LINES)
+ end
+ end
+
+ # We want to update the match line's text every time unless we've already
+ # created a gap and its corresponding match line.
+ update_match_line_text(match_line, lines.last) unless section
+
+ section ||= { conflict: !no_conflict, lines: lines }
+ section[:id] = line_code(lines.first) unless no_conflict
+ section
+ end
+ end
+
+ def line_code(line)
+ Gitlab::Diff::LineCode.generate(our_path, line.new_pos, line.old_pos)
+ end
+
+ def create_match_line(line)
+ Gitlab::Diff::Line.new('', 'match', line.index, line.old_pos, line.new_pos)
+ end
+
+ # Any line beginning with a letter, an underscore, or a dollar can be used in a
+ # match line header. Only context sections can contain match lines, as match lines
+ # have to exist in both versions of the file.
+ def find_match_line_header(index)
+ return @match_line_headers[index] if @match_line_headers.key?(index)
+
+ @match_line_headers[index] = begin
+ if index >= 0
+ line = lines[index]
+
+ if line.type.nil? && line.text.match(/\A[A-Za-z$_]/)
+ " #{line.text}"
+ else
+ find_match_line_header(index - 1)
+ end
+ end
+ end
+ end
+
+ # Set the match line's text for the current line. A match line takes its start
+ # position and context header (where present) from itself, and its end position from
+ # the line passed in.
+ def update_match_line_text(match_line, line)
+ return unless match_line
+
+ header = find_match_line_header(match_line.index - 1)
+
+ match_line.text = "@@ -#{match_line.old_pos},#{line.old_pos} +#{match_line.new_pos},#{line.new_pos} @@#{header}"
+ end
+
+ def as_json(opts = nil)
+ {
+ old_path: their_path,
+ new_path: our_path,
+ blob_icon: file_type_icon_class('file', our_mode, our_path),
+ blob_path: namespace_project_blob_path(merge_request.project.namespace,
+ merge_request.project,
+ ::File.join(merge_request.diff_refs.head_sha, our_path)),
+ sections: sections
+ }
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/conflict/file_collection.rb b/lib/gitlab/conflict/file_collection.rb
new file mode 100644
index 00000000000..bbd0427a2c8
--- /dev/null
+++ b/lib/gitlab/conflict/file_collection.rb
@@ -0,0 +1,57 @@
+module Gitlab
+ module Conflict
+ class FileCollection
+ class ConflictSideMissing < StandardError
+ end
+
+ attr_reader :merge_request, :our_commit, :their_commit
+
+ def initialize(merge_request)
+ @merge_request = merge_request
+ @our_commit = merge_request.source_branch_head.raw.raw_commit
+ @their_commit = merge_request.target_branch_head.raw.raw_commit
+ end
+
+ def repository
+ merge_request.project.repository
+ end
+
+ def merge_index
+ @merge_index ||= repository.rugged.merge_commits(our_commit, their_commit)
+ end
+
+ def files
+ @files ||= merge_index.conflicts.map do |conflict|
+ raise ConflictSideMissing unless conflict[:theirs] && conflict[:ours]
+
+ Gitlab::Conflict::File.new(merge_index.merge_file(conflict[:ours][:path]),
+ conflict,
+ merge_request: merge_request)
+ end
+ end
+
+ def as_json(opts = nil)
+ {
+ target_branch: merge_request.target_branch,
+ source_branch: merge_request.source_branch,
+ commit_sha: merge_request.diff_head_sha,
+ commit_message: default_commit_message,
+ files: files
+ }
+ end
+
+ def default_commit_message
+ conflict_filenames = merge_index.conflicts.map do |conflict|
+ "# #{conflict[:ours][:path]}"
+ end
+
+ <<EOM.chomp
+Merge branch '#{merge_request.target_branch}' into '#{merge_request.source_branch}'
+
+# Conflicts:
+#{conflict_filenames.join("\n")}
+EOM
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/conflict/parser.rb b/lib/gitlab/conflict/parser.rb
new file mode 100644
index 00000000000..6eccded7872
--- /dev/null
+++ b/lib/gitlab/conflict/parser.rb
@@ -0,0 +1,62 @@
+module Gitlab
+ module Conflict
+ class Parser
+ class ParserError < StandardError
+ end
+
+ class UnexpectedDelimiter < ParserError
+ end
+
+ class MissingEndDelimiter < ParserError
+ end
+
+ class UnmergeableFile < ParserError
+ end
+
+ def parse(text, our_path:, their_path:, parent_file: nil)
+ raise UnmergeableFile if text.blank? # Typically a binary file
+ raise UnmergeableFile if text.length > 102400
+
+ line_obj_index = 0
+ line_old = 1
+ line_new = 1
+ type = nil
+ lines = []
+ conflict_start = "<<<<<<< #{our_path}"
+ conflict_middle = '======='
+ conflict_end = ">>>>>>> #{their_path}"
+
+ text.each_line.map do |line|
+ full_line = line.delete("\n")
+
+ if full_line == conflict_start
+ raise UnexpectedDelimiter unless type.nil?
+
+ type = 'new'
+ elsif full_line == conflict_middle
+ raise UnexpectedDelimiter unless type == 'new'
+
+ type = 'old'
+ elsif full_line == conflict_end
+ raise UnexpectedDelimiter unless type == 'old'
+
+ type = nil
+ elsif line[0] == '\\'
+ type = 'nonewline'
+ lines << Gitlab::Diff::Line.new(full_line, type, line_obj_index, line_old, line_new, parent_file: parent_file)
+ else
+ lines << Gitlab::Diff::Line.new(full_line, type, line_obj_index, line_old, line_new, parent_file: parent_file)
+ line_old += 1 if type != 'new'
+ line_new += 1 if type != 'old'
+
+ line_obj_index += 1
+ end
+ end
+
+ raise MissingEndDelimiter unless type.nil?
+
+ lines
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/diff/line.rb b/lib/gitlab/diff/line.rb
index cf097e0d0de..80a146b4a5a 100644
--- a/lib/gitlab/diff/line.rb
+++ b/lib/gitlab/diff/line.rb
@@ -2,11 +2,13 @@ module Gitlab
module Diff
class Line
attr_reader :type, :index, :old_pos, :new_pos
+ attr_writer :rich_text
attr_accessor :text
- def initialize(text, type, index, old_pos, new_pos)
+ def initialize(text, type, index, old_pos, new_pos, parent_file: nil)
@text, @type, @index = text, type, index
@old_pos, @new_pos = old_pos, new_pos
+ @parent_file = parent_file
end
def self.init_from_hash(hash)
@@ -43,9 +45,25 @@ module Gitlab
type == 'old'
end
+ def rich_text
+ @parent_file.highlight_lines! if @parent_file && !@rich_text
+
+ @rich_text
+ end
+
def meta?
type == 'match' || type == 'nonewline'
end
+
+ def as_json(opts = nil)
+ {
+ type: type,
+ old_line: old_line,
+ new_line: new_line,
+ text: text,
+ rich_text: rich_text || text
+ }
+ end
end
end
end
diff --git a/lib/gitlab/downtime_check/message.rb b/lib/gitlab/downtime_check/message.rb
index 4446e921e0d..40a4815a9a0 100644
--- a/lib/gitlab/downtime_check/message.rb
+++ b/lib/gitlab/downtime_check/message.rb
@@ -1,10 +1,10 @@
module Gitlab
class DowntimeCheck
class Message
- attr_reader :path, :offline, :reason
+ attr_reader :path, :offline
- OFFLINE = "\e[32moffline\e[0m"
- ONLINE = "\e[31monline\e[0m"
+ OFFLINE = "\e[31moffline\e[0m"
+ ONLINE = "\e[32monline\e[0m"
# path - The file path of the migration.
# offline - When set to `true` the migration will require downtime.
@@ -19,10 +19,21 @@ module Gitlab
label = offline ? OFFLINE : ONLINE
message = "[#{label}]: #{path}"
- message += ": #{reason}" if reason
+
+ if reason?
+ message += ":\n\n#{reason}\n\n"
+ end
message
end
+
+ def reason?
+ @reason.present?
+ end
+
+ def reason
+ @reason.strip.lines.map(&:strip).join("\n")
+ end
end
end
end
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 69758494543..c64c2b075c5 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -4,6 +4,11 @@ describe Projects::MergeRequestsController do
let(:project) { create(:project) }
let(:user) { create(:user) }
let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
+ let(:merge_request_with_conflicts) do
+ create(:merge_request, source_branch: 'conflict-resolvable', target_branch: 'conflict-start', source_project: project) do |mr|
+ mr.mark_as_unmergeable
+ end
+ end
before do
sign_in(user)
@@ -523,4 +528,135 @@ describe Projects::MergeRequestsController do
end
end
end
+
+ describe 'GET conflicts' do
+ let(:json_response) { JSON.parse(response.body) }
+
+ context 'when the conflicts cannot be resolved in the UI' do
+ before do
+ allow_any_instance_of(Gitlab::Conflict::Parser).
+ to receive(:parse).and_raise(Gitlab::Conflict::Parser::UnexpectedDelimiter)
+
+ get :conflicts,
+ namespace_id: merge_request_with_conflicts.project.namespace.to_param,
+ project_id: merge_request_with_conflicts.project.to_param,
+ id: merge_request_with_conflicts.iid,
+ format: 'json'
+ end
+
+ it 'returns a 200 status code' do
+ expect(response).to have_http_status(:ok)
+ end
+
+ it 'returns JSON with a message' do
+ expect(json_response.keys).to contain_exactly('message', 'type')
+ end
+ end
+
+ context 'with valid conflicts' do
+ before do
+ get :conflicts,
+ namespace_id: merge_request_with_conflicts.project.namespace.to_param,
+ project_id: merge_request_with_conflicts.project.to_param,
+ id: merge_request_with_conflicts.iid,
+ format: 'json'
+ end
+
+ it 'includes meta info about the MR' do
+ expect(json_response['commit_message']).to include('Merge branch')
+ expect(json_response['commit_sha']).to match(/\h{40}/)
+ expect(json_response['source_branch']).to eq(merge_request_with_conflicts.source_branch)
+ expect(json_response['target_branch']).to eq(merge_request_with_conflicts.target_branch)
+ end
+
+ it 'includes each file that has conflicts' do
+ filenames = json_response['files'].map { |file| file['new_path'] }
+
+ expect(filenames).to contain_exactly('files/ruby/popen.rb', 'files/ruby/regex.rb')
+ end
+
+ it 'splits files into sections with lines' do
+ json_response['files'].each do |file|
+ file['sections'].each do |section|
+ expect(section).to include('conflict', 'lines')
+
+ section['lines'].each do |line|
+ if section['conflict']
+ expect(line['type']).to be_in(['old', 'new'])
+ expect(line.values_at('old_line', 'new_line')).to contain_exactly(nil, a_kind_of(Integer))
+ else
+ if line['type'].nil?
+ expect(line['old_line']).not_to eq(nil)
+ expect(line['new_line']).not_to eq(nil)
+ else
+ expect(line['type']).to eq('match')
+ expect(line['old_line']).to eq(nil)
+ expect(line['new_line']).to eq(nil)
+ end
+ end
+ end
+ end
+ end
+ end
+
+ it 'has unique section IDs across files' do
+ section_ids = json_response['files'].flat_map do |file|
+ file['sections'].map { |section| section['id'] }.compact
+ end
+
+ expect(section_ids.uniq).to eq(section_ids)
+ end
+ end
+ end
+
+ context 'POST resolve_conflicts' do
+ let(:json_response) { JSON.parse(response.body) }
+ let!(:original_head_sha) { merge_request_with_conflicts.diff_head_sha }
+
+ def resolve_conflicts(sections)
+ post :resolve_conflicts,
+ namespace_id: merge_request_with_conflicts.project.namespace.to_param,
+ project_id: merge_request_with_conflicts.project.to_param,
+ id: merge_request_with_conflicts.iid,
+ format: 'json',
+ sections: sections,
+ commit_message: 'Commit message'
+ end
+
+ context 'with valid params' do
+ before do
+ resolve_conflicts('2f6fcd96b88b36ce98c38da085c795a27d92a3dd_14_14' => 'head',
+ '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_9_9' => 'head',
+ '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_21_21' => 'origin',
+ '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_49_49' => 'origin')
+ end
+
+ it 'creates a new commit on the branch' do
+ expect(original_head_sha).not_to eq(merge_request_with_conflicts.source_branch_head.sha)
+ expect(merge_request_with_conflicts.source_branch_head.message).to include('Commit message')
+ end
+
+ it 'returns an OK response' do
+ expect(response).to have_http_status(:ok)
+ end
+ end
+
+ context 'when sections are missing' do
+ before do
+ resolve_conflicts('2f6fcd96b88b36ce98c38da085c795a27d92a3dd_14_14' => 'head')
+ end
+
+ it 'returns a 400 error' do
+ expect(response).to have_http_status(:bad_request)
+ end
+
+ it 'has a message with the name of the first missing section' do
+ expect(json_response['message']).to include('6eb14e00385d2fb284765eb1cd8d420d33d63fc9_9_9')
+ end
+
+ it 'does not create a new commit' do
+ expect(original_head_sha).to eq(merge_request_with_conflicts.source_branch_head.sha)
+ end
+ end
+ end
end
diff --git a/spec/features/merge_requests/conflicts_spec.rb b/spec/features/merge_requests/conflicts_spec.rb
new file mode 100644
index 00000000000..930c36ade2b
--- /dev/null
+++ b/spec/features/merge_requests/conflicts_spec.rb
@@ -0,0 +1,72 @@
+require 'spec_helper'
+
+feature 'Merge request conflict resolution', js: true, feature: true do
+ include WaitForAjax
+
+ let(:user) { create(:user) }
+ let(:project) { create(:project) }
+
+ def create_merge_request(source_branch)
+ create(:merge_request, source_branch: source_branch, target_branch: 'conflict-start', source_project: project) do |mr|
+ mr.mark_as_unmergeable
+ end
+ end
+
+ context 'when a merge request can be resolved in the UI' do
+ let(:merge_request) { create_merge_request('conflict-resolvable') }
+
+ before do
+ project.team << [user, :developer]
+ login_as(user)
+
+ visit namespace_project_merge_request_path(project.namespace, project, merge_request)
+ end
+
+ it 'shows a link to the conflict resolution page' do
+ expect(page).to have_link('conflicts', href: /\/conflicts\Z/)
+ end
+
+ context 'visiting the conflicts resolution page' do
+ before { click_link('conflicts', href: /\/conflicts\Z/) }
+
+ it 'shows the conflicts' do
+ begin
+ expect(find('#conflicts')).to have_content('popen.rb')
+ rescue Capybara::Poltergeist::JavascriptError
+ retry
+ end
+ end
+ end
+ end
+
+ UNRESOLVABLE_CONFLICTS = {
+ 'conflict-too-large' => 'when the conflicts contain a large file',
+ 'conflict-binary-file' => 'when the conflicts contain a binary file',
+ 'conflict-contains-conflict-markers' => 'when the conflicts contain a file with ambiguous conflict markers',
+ 'conflict-missing-side' => 'when the conflicts contain a file edited in one branch and deleted in another'
+ }
+
+ UNRESOLVABLE_CONFLICTS.each do |source_branch, description|
+ context description do
+ let(:merge_request) { create_merge_request(source_branch) }
+
+ before do
+ project.team << [user, :developer]
+ login_as(user)
+
+ visit namespace_project_merge_request_path(project.namespace, project, merge_request)
+ end
+
+ it 'does not show a link to the conflict resolution page' do
+ expect(page).not_to have_link('conflicts', href: /\/conflicts\Z/)
+ end
+
+ it 'shows an error if the conflicts page is visited directly' do
+ visit current_url + '/conflicts'
+ wait_for_ajax
+
+ expect(find('#conflicts')).to have_content('Please try to resolve them locally.')
+ end
+ end
+ end
+end
diff --git a/spec/features/merge_requests/pipelines_spec.rb b/spec/features/merge_requests/pipelines_spec.rb
new file mode 100644
index 00000000000..9c4c0525267
--- /dev/null
+++ b/spec/features/merge_requests/pipelines_spec.rb
@@ -0,0 +1,48 @@
+require 'spec_helper'
+
+feature 'Pipelines for Merge Requests', feature: true, js: true do
+ include WaitForAjax
+
+ given(:user) { create(:user) }
+ given(:merge_request) { create(:merge_request) }
+ given(:project) { merge_request.target_project }
+
+ before do
+ project.team << [user, :master]
+ login_as user
+ end
+
+ context 'with pipelines' do
+ let!(:pipeline) do
+ create(:ci_empty_pipeline,
+ project: merge_request.source_project,
+ ref: merge_request.source_branch,
+ sha: merge_request.diff_head_sha)
+ end
+
+ before do
+ visit namespace_project_merge_request_path(project.namespace, project, merge_request)
+ end
+
+ scenario 'user visits merge request pipelines tab' do
+ page.within('.merge-request-tabs') do
+ click_link('Pipelines')
+ end
+ wait_for_ajax
+
+ expect(page).to have_selector('.pipeline-actions')
+ end
+ end
+
+ context 'without pipelines' do
+ before do
+ visit namespace_project_merge_request_path(project.namespace, project, merge_request)
+ end
+
+ scenario 'user visits merge request page' do
+ page.within('.merge-request-tabs') do
+ expect(page).to have_no_link('Pipelines')
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/conflict/file_collection_spec.rb b/spec/lib/gitlab/conflict/file_collection_spec.rb
new file mode 100644
index 00000000000..39d892c18c0
--- /dev/null
+++ b/spec/lib/gitlab/conflict/file_collection_spec.rb
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+describe Gitlab::Conflict::FileCollection, lib: true do
+ let(:merge_request) { create(:merge_request, source_branch: 'conflict-resolvable', target_branch: 'conflict-start') }
+ let(:file_collection) { Gitlab::Conflict::FileCollection.new(merge_request) }
+
+ describe '#files' do
+ it 'returns an array of Conflict::Files' do
+ expect(file_collection.files).to all(be_an_instance_of(Gitlab::Conflict::File))
+ end
+ end
+
+ describe '#default_commit_message' do
+ it 'matches the format of the git CLI commit message' do
+ expect(file_collection.default_commit_message).to eq(<<EOM.chomp)
+Merge branch 'conflict-start' into 'conflict-resolvable'
+
+# Conflicts:
+# files/ruby/popen.rb
+# files/ruby/regex.rb
+EOM
+ end
+ end
+end
diff --git a/spec/lib/gitlab/conflict/file_spec.rb b/spec/lib/gitlab/conflict/file_spec.rb
new file mode 100644
index 00000000000..60020487061
--- /dev/null
+++ b/spec/lib/gitlab/conflict/file_spec.rb
@@ -0,0 +1,261 @@
+require 'spec_helper'
+
+describe Gitlab::Conflict::File, lib: true do
+ let(:project) { create(:project) }
+ let(:repository) { project.repository }
+ let(:rugged) { repository.rugged }
+ let(:their_commit) { rugged.branches['conflict-start'].target }
+ let(:our_commit) { rugged.branches['conflict-resolvable'].target }
+ let(:merge_request) { create(:merge_request, source_branch: 'conflict-resolvable', target_branch: 'conflict-start', source_project: project) }
+ let(:index) { rugged.merge_commits(our_commit, their_commit) }
+ let(:conflict) { index.conflicts.last }
+ let(:merge_file_result) { index.merge_file('files/ruby/regex.rb') }
+ let(:conflict_file) { Gitlab::Conflict::File.new(merge_file_result, conflict, merge_request: merge_request) }
+
+ describe '#resolve_lines' do
+ let(:section_keys) { conflict_file.sections.map { |section| section[:id] }.compact }
+
+ context 'when resolving everything to the same side' do
+ let(:resolution_hash) { section_keys.map { |key| [key, 'head'] }.to_h }
+ let(:resolved_lines) { conflict_file.resolve_lines(resolution_hash) }
+ let(:expected_lines) { conflict_file.lines.reject { |line| line.type == 'old' } }
+
+ it 'has the correct number of lines' do
+ expect(resolved_lines.length).to eq(expected_lines.length)
+ end
+
+ it 'has content matching the chosen lines' do
+ expect(resolved_lines.map(&:text)).to eq(expected_lines.map(&:text))
+ end
+ end
+
+ context 'with mixed resolutions' do
+ let(:resolution_hash) do
+ section_keys.map.with_index { |key, i| [key, i.even? ? 'head' : 'origin'] }.to_h
+ end
+
+ let(:resolved_lines) { conflict_file.resolve_lines(resolution_hash) }
+
+ it 'has the correct number of lines' do
+ file_lines = conflict_file.lines.reject { |line| line.type == 'new' }
+
+ expect(resolved_lines.length).to eq(file_lines.length)
+ end
+
+ it 'returns a file containing only the chosen parts of the resolved sections' do
+ expect(resolved_lines.chunk { |line| line.type || 'both' }.map(&:first)).
+ to eq(['both', 'new', 'both', 'old', 'both', 'new', 'both'])
+ end
+ end
+
+ it 'raises MissingResolution when passed a hash without resolutions for all sections' do
+ empty_hash = section_keys.map { |key| [key, nil] }.to_h
+ invalid_hash = section_keys.map { |key| [key, 'invalid'] }.to_h
+
+ expect { conflict_file.resolve_lines({}) }.
+ to raise_error(Gitlab::Conflict::File::MissingResolution)
+
+ expect { conflict_file.resolve_lines(empty_hash) }.
+ to raise_error(Gitlab::Conflict::File::MissingResolution)
+
+ expect { conflict_file.resolve_lines(invalid_hash) }.
+ to raise_error(Gitlab::Conflict::File::MissingResolution)
+ end
+ end
+
+ describe '#highlight_lines!' do
+ def html_to_text(html)
+ CGI.unescapeHTML(ActionView::Base.full_sanitizer.sanitize(html)).delete("\n")
+ end
+
+ it 'modifies the existing lines' do
+ expect { conflict_file.highlight_lines! }.to change { conflict_file.lines.map(&:instance_variables) }
+ end
+
+ it 'is called implicitly when rich_text is accessed on a line' do
+ expect(conflict_file).to receive(:highlight_lines!).once.and_call_original
+
+ conflict_file.lines.each(&:rich_text)
+ end
+
+ it 'sets the rich_text of the lines matching the text content' do
+ conflict_file.lines.each do |line|
+ expect(line.text).to eq(html_to_text(line.rich_text))
+ end
+ end
+ end
+
+ describe '#sections' do
+ it 'only inserts match lines when there is a gap between sections' do
+ conflict_file.sections.each_with_index do |section, i|
+ previous_line_number = 0
+ current_line_number = section[:lines].map(&:old_line).compact.min
+
+ if i > 0
+ previous_line_number = conflict_file.sections[i - 1][:lines].map(&:old_line).compact.last
+ end
+
+ if current_line_number == previous_line_number + 1
+ expect(section[:lines].first.type).not_to eq('match')
+ else
+ expect(section[:lines].first.type).to eq('match')
+ expect(section[:lines].first.text).to match(/\A@@ -#{current_line_number},\d+ \+\d+,\d+ @@ module Gitlab\Z/)
+ end
+ end
+ end
+
+ it 'sets conflict to false for sections with only unchanged lines' do
+ conflict_file.sections.reject { |section| section[:conflict] }.each do |section|
+ without_match = section[:lines].reject { |line| line.type == 'match' }
+
+ expect(without_match).to all(have_attributes(type: nil))
+ end
+ end
+
+ it 'only includes a maximum of CONTEXT_LINES (plus an optional match line) in context sections' do
+ conflict_file.sections.reject { |section| section[:conflict] }.each do |section|
+ without_match = section[:lines].reject { |line| line.type == 'match' }
+
+ expect(without_match.length).to be <= Gitlab::Conflict::File::CONTEXT_LINES * 2
+ end
+ end
+
+ it 'sets conflict to true for sections with only changed lines' do
+ conflict_file.sections.select { |section| section[:conflict] }.each do |section|
+ section[:lines].each do |line|
+ expect(line.type).to be_in(['new', 'old'])
+ end
+ end
+ end
+
+ it 'adds unique IDs to conflict sections, and not to other sections' do
+ section_ids = []
+
+ conflict_file.sections.each do |section|
+ if section[:conflict]
+ expect(section).to have_key(:id)
+ section_ids << section[:id]
+ else
+ expect(section).not_to have_key(:id)
+ end
+ end
+
+ expect(section_ids.uniq).to eq(section_ids)
+ end
+
+ context 'with an example file' do
+ let(:file) do
+ <<FILE
+ # Ensure there is no match line header here
+ def username_regexp
+ default_regexp
+ end
+
+<<<<<<< files/ruby/regex.rb
+def project_name_regexp
+ /\A[a-zA-Z0-9][a-zA-Z0-9_\-\. ]*\z/
+end
+
+def name_regexp
+ /\A[a-zA-Z0-9_\-\. ]*\z/
+=======
+def project_name_regex
+ %r{\A[a-zA-Z0-9][a-zA-Z0-9_\-\. ]*\z}
+end
+
+def name_regex
+ %r{\A[a-zA-Z0-9_\-\. ]*\z}
+>>>>>>> files/ruby/regex.rb
+end
+
+# Some extra lines
+# To force a match line
+# To be created
+
+def path_regexp
+ default_regexp
+end
+
+<<<<<<< files/ruby/regex.rb
+def archive_formats_regexp
+ /(zip|tar|7z|tar\.gz|tgz|gz|tar\.bz2|tbz|tbz2|tb2|bz2)/
+=======
+def archive_formats_regex
+ %r{(zip|tar|7z|tar\.gz|tgz|gz|tar\.bz2|tbz|tbz2|tb2|bz2)}
+>>>>>>> files/ruby/regex.rb
+end
+
+def git_reference_regexp
+ # Valid git ref regexp, see:
+ # https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html
+ %r{
+ (?!
+ (?# doesn't begins with)
+ \/| (?# rule #6)
+ (?# doesn't contain)
+ .*(?:
+ [\/.]\.| (?# rule #1,3)
+ \/\/| (?# rule #6)
+ @\{| (?# rule #8)
+ \\ (?# rule #9)
+ )
+ )
+ [^\000-\040\177~^:?*\[]+ (?# rule #4-5)
+ (?# doesn't end with)
+ (?<!\.lock) (?# rule #1)
+ (?<![\/.]) (?# rule #6-7)
+ }x
+end
+
+protected
+
+<<<<<<< files/ruby/regex.rb
+def default_regexp
+ /\A[.?]?[a-zA-Z0-9][a-zA-Z0-9_\-\.]*(?<!\.git)\z/
+=======
+def default_regex
+ %r{\A[.?]?[a-zA-Z0-9][a-zA-Z0-9_\-\.]*(?<!\.git)\z}
+>>>>>>> files/ruby/regex.rb
+end
+FILE
+ end
+
+ let(:conflict_file) { Gitlab::Conflict::File.new({ data: file }, conflict, merge_request: merge_request) }
+ let(:sections) { conflict_file.sections }
+
+ it 'sets the correct match line headers' do
+ expect(sections[0][:lines].first).to have_attributes(type: 'match', text: '@@ -3,14 +3,14 @@')
+ expect(sections[3][:lines].first).to have_attributes(type: 'match', text: '@@ -19,26 +19,26 @@ def path_regexp')
+ expect(sections[6][:lines].first).to have_attributes(type: 'match', text: '@@ -47,52 +47,52 @@ end')
+ end
+
+ it 'does not add match lines where they are not needed' do
+ expect(sections[1][:lines].first.type).not_to eq('match')
+ expect(sections[2][:lines].first.type).not_to eq('match')
+ expect(sections[4][:lines].first.type).not_to eq('match')
+ expect(sections[5][:lines].first.type).not_to eq('match')
+ expect(sections[7][:lines].first.type).not_to eq('match')
+ end
+
+ it 'creates context sections of the correct length' do
+ expect(sections[0][:lines].reject(&:type).length).to eq(3)
+ expect(sections[2][:lines].reject(&:type).length).to eq(3)
+ expect(sections[3][:lines].reject(&:type).length).to eq(3)
+ expect(sections[5][:lines].reject(&:type).length).to eq(3)
+ expect(sections[6][:lines].reject(&:type).length).to eq(3)
+ expect(sections[8][:lines].reject(&:type).length).to eq(1)
+ end
+ end
+ end
+
+ describe '#as_json' do
+ it 'includes the blob path for the file' do
+ expect(conflict_file.as_json[:blob_path]).
+ to eq("/#{project.namespace.to_param}/#{merge_request.project.to_param}/blob/#{our_commit.oid}/files/ruby/regex.rb")
+ end
+
+ it 'includes the blob icon for the file' do
+ expect(conflict_file.as_json[:blob_icon]).to eq('file-text-o')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/conflict/parser_spec.rb b/spec/lib/gitlab/conflict/parser_spec.rb
new file mode 100644
index 00000000000..65a828accde
--- /dev/null
+++ b/spec/lib/gitlab/conflict/parser_spec.rb
@@ -0,0 +1,188 @@
+require 'spec_helper'
+
+describe Gitlab::Conflict::Parser, lib: true do
+ let(:parser) { Gitlab::Conflict::Parser.new }
+
+ describe '#parse' do
+ def parse_text(text)
+ parser.parse(text, our_path: 'README.md', their_path: 'README.md')
+ end
+
+ context 'when the file has valid conflicts' do
+ let(:text) do
+ <<CONFLICT
+module Gitlab
+ module Regexp
+ extend self
+
+ def username_regexp
+ default_regexp
+ end
+
+<<<<<<< files/ruby/regex.rb
+ def project_name_regexp
+ /\A[a-zA-Z0-9][a-zA-Z0-9_\-\. ]*\z/
+ end
+
+ def name_regexp
+ /\A[a-zA-Z0-9_\-\. ]*\z/
+=======
+ def project_name_regex
+ %r{\A[a-zA-Z0-9][a-zA-Z0-9_\-\. ]*\z}
+ end
+
+ def name_regex
+ %r{\A[a-zA-Z0-9_\-\. ]*\z}
+>>>>>>> files/ruby/regex.rb
+ end
+
+ def path_regexp
+ default_regexp
+ end
+
+<<<<<<< files/ruby/regex.rb
+ def archive_formats_regexp
+ /(zip|tar|7z|tar\.gz|tgz|gz|tar\.bz2|tbz|tbz2|tb2|bz2)/
+=======
+ def archive_formats_regex
+ %r{(zip|tar|7z|tar\.gz|tgz|gz|tar\.bz2|tbz|tbz2|tb2|bz2)}
+>>>>>>> files/ruby/regex.rb
+ end
+
+ def git_reference_regexp
+ # Valid git ref regexp, see:
+ # https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html
+ %r{
+ (?!
+ (?# doesn't begins with)
+ \/| (?# rule #6)
+ (?# doesn't contain)
+ .*(?:
+ [\/.]\.| (?# rule #1,3)
+ \/\/| (?# rule #6)
+ @\{| (?# rule #8)
+ \\ (?# rule #9)
+ )
+ )
+ [^\000-\040\177~^:?*\[]+ (?# rule #4-5)
+ (?# doesn't end with)
+ (?<!\.lock) (?# rule #1)
+ (?<![\/.]) (?# rule #6-7)
+ }x
+ end
+
+ protected
+
+<<<<<<< files/ruby/regex.rb
+ def default_regexp
+ /\A[.?]?[a-zA-Z0-9][a-zA-Z0-9_\-\.]*(?<!\.git)\z/
+=======
+ def default_regex
+ %r{\A[.?]?[a-zA-Z0-9][a-zA-Z0-9_\-\.]*(?<!\.git)\z}
+>>>>>>> files/ruby/regex.rb
+ end
+ end
+end
+CONFLICT
+ end
+
+ let(:lines) do
+ parser.parse(text, our_path: 'files/ruby/regex.rb', their_path: 'files/ruby/regex.rb')
+ end
+
+ it 'sets our lines as new lines' do
+ expect(lines[8..13]).to all(have_attributes(type: 'new'))
+ expect(lines[26..27]).to all(have_attributes(type: 'new'))
+ expect(lines[56..57]).to all(have_attributes(type: 'new'))
+ end
+
+ it 'sets their lines as old lines' do
+ expect(lines[14..19]).to all(have_attributes(type: 'old'))
+ expect(lines[28..29]).to all(have_attributes(type: 'old'))
+ expect(lines[58..59]).to all(have_attributes(type: 'old'))
+ end
+
+ it 'sets non-conflicted lines as both' do
+ expect(lines[0..7]).to all(have_attributes(type: nil))
+ expect(lines[20..25]).to all(have_attributes(type: nil))
+ expect(lines[30..55]).to all(have_attributes(type: nil))
+ expect(lines[60..62]).to all(have_attributes(type: nil))
+ end
+
+ it 'sets consecutive line numbers for index, old_pos, and new_pos' do
+ old_line_numbers = lines.select { |line| line.type != 'new' }.map(&:old_pos)
+ new_line_numbers = lines.select { |line| line.type != 'old' }.map(&:new_pos)
+
+ expect(lines.map(&:index)).to eq(0.upto(62).to_a)
+ expect(old_line_numbers).to eq(1.upto(53).to_a)
+ expect(new_line_numbers).to eq(1.upto(53).to_a)
+ end
+ end
+
+ context 'when the file contents include conflict delimiters' do
+ it 'raises UnexpectedDelimiter when there is a non-start delimiter first' do
+ expect { parse_text('=======') }.
+ to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter)
+
+ expect { parse_text('>>>>>>> README.md') }.
+ to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter)
+
+ expect { parse_text('>>>>>>> some-other-path.md') }.
+ not_to raise_error
+ end
+
+ it 'raises UnexpectedDelimiter when a start delimiter is followed by a non-middle delimiter' do
+ start_text = "<<<<<<< README.md\n"
+ end_text = "\n=======\n>>>>>>> README.md"
+
+ expect { parse_text(start_text + '>>>>>>> README.md' + end_text) }.
+ to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter)
+
+ expect { parse_text(start_text + start_text + end_text) }.
+ to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter)
+
+ expect { parse_text(start_text + '>>>>>>> some-other-path.md' + end_text) }.
+ not_to raise_error
+ end
+
+ it 'raises UnexpectedDelimiter when a middle delimiter is followed by a non-end delimiter' do
+ start_text = "<<<<<<< README.md\n=======\n"
+ end_text = "\n>>>>>>> README.md"
+
+ expect { parse_text(start_text + '=======' + end_text) }.
+ to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter)
+
+ expect { parse_text(start_text + start_text + end_text) }.
+ to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter)
+
+ expect { parse_text(start_text + '>>>>>>> some-other-path.md' + end_text) }.
+ not_to raise_error
+ end
+
+ it 'raises MissingEndDelimiter when there is no end delimiter at the end' do
+ start_text = "<<<<<<< README.md\n=======\n"
+
+ expect { parse_text(start_text) }.
+ to raise_error(Gitlab::Conflict::Parser::MissingEndDelimiter)
+
+ expect { parse_text(start_text + '>>>>>>> some-other-path.md') }.
+ to raise_error(Gitlab::Conflict::Parser::MissingEndDelimiter)
+ end
+ end
+
+ context 'other file types' do
+ it 'raises UnmergeableFile when lines is blank, indicating a binary file' do
+ expect { parse_text('') }.
+ to raise_error(Gitlab::Conflict::Parser::UnmergeableFile)
+
+ expect { parse_text(nil) }.
+ to raise_error(Gitlab::Conflict::Parser::UnmergeableFile)
+ end
+
+ it 'raises UnmergeableFile when the file is over 100 KB' do
+ expect { parse_text('a' * 102401) }.
+ to raise_error(Gitlab::Conflict::Parser::UnmergeableFile)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/downtime_check/message_spec.rb b/spec/lib/gitlab/downtime_check/message_spec.rb
index 93094cda776..a5a398abf78 100644
--- a/spec/lib/gitlab/downtime_check/message_spec.rb
+++ b/spec/lib/gitlab/downtime_check/message_spec.rb
@@ -5,13 +5,35 @@ describe Gitlab::DowntimeCheck::Message do
it 'returns an ANSI formatted String for an offline migration' do
message = described_class.new('foo.rb', true, 'hello')
- expect(message.to_s).to eq("[\e[32moffline\e[0m]: foo.rb: hello")
+ expect(message.to_s).to eq("[\e[31moffline\e[0m]: foo.rb:\n\nhello\n\n")
end
it 'returns an ANSI formatted String for an online migration' do
message = described_class.new('foo.rb')
- expect(message.to_s).to eq("[\e[31monline\e[0m]: foo.rb")
+ expect(message.to_s).to eq("[\e[32monline\e[0m]: foo.rb")
+ end
+ end
+
+ describe '#reason?' do
+ it 'returns false when no reason is specified' do
+ message = described_class.new('foo.rb')
+
+ expect(message.reason?).to eq(false)
+ end
+
+ it 'returns true when a reason is specified' do
+ message = described_class.new('foo.rb', true, 'hello')
+
+ expect(message.reason?).to eq(true)
+ end
+ end
+
+ describe '#reason' do
+ it 'strips excessive whitespace from the returned String' do
+ message = described_class.new('foo.rb', true, " hello\n world\n\n foo")
+
+ expect(message.reason).to eq("hello\nworld\n\nfoo")
end
end
end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 35a4418ebb3..f83dbefedc0 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -456,6 +456,20 @@ describe MergeRequest, models: true do
subject { create :merge_request, :simple }
end
+ describe '#commits_sha' do
+ let(:commit0) { double('commit0', sha: 'sha1') }
+ let(:commit1) { double('commit1', sha: 'sha2') }
+ let(:commit2) { double('commit2', sha: 'sha3') }
+
+ before do
+ allow(subject.merge_request_diff).to receive(:commits).and_return([commit0, commit1, commit2])
+ end
+
+ it 'returns sha of commits' do
+ expect(subject.commits_sha).to contain_exactly('sha1', 'sha2', 'sha3')
+ end
+ end
+
describe '#pipeline' do
describe 'when the source project exists' do
it 'returns the latest pipeline' do
@@ -480,6 +494,19 @@ describe MergeRequest, models: true do
end
end
+ describe '#all_pipelines' do
+ let!(:pipelines) do
+ subject.merge_request_diff.commits.map do |commit|
+ create(:ci_empty_pipeline, project: subject.source_project, sha: commit.id, ref: subject.source_branch)
+ end
+ end
+
+ it 'returns a pipelines from source projects with proper ordering' do
+ expect(subject.all_pipelines).not_to be_empty
+ expect(subject.all_pipelines).to eq(pipelines.reverse)
+ end
+ end
+
describe '#participants' do
let(:project) { create(:project, :public) }
@@ -756,4 +783,56 @@ describe MergeRequest, models: true do
end
end
end
+
+ describe '#conflicts_can_be_resolved_in_ui?' do
+ def create_merge_request(source_branch)
+ create(:merge_request, source_branch: source_branch, target_branch: 'conflict-start') do |mr|
+ mr.mark_as_unmergeable
+ end
+ end
+
+ it 'returns a falsey value when the MR can be merged without conflicts' do
+ merge_request = create_merge_request('master')
+ merge_request.mark_as_mergeable
+
+ expect(merge_request.conflicts_can_be_resolved_in_ui?).to be_falsey
+ end
+
+ it 'returns a falsey value when the MR does not support new diff notes' do
+ merge_request = create_merge_request('conflict-resolvable')
+ merge_request.merge_request_diff.update_attributes(start_commit_sha: nil)
+
+ expect(merge_request.conflicts_can_be_resolved_in_ui?).to be_falsey
+ end
+
+ it 'returns a falsey value when the conflicts contain a large file' do
+ merge_request = create_merge_request('conflict-too-large')
+
+ expect(merge_request.conflicts_can_be_resolved_in_ui?).to be_falsey
+ end
+
+ it 'returns a falsey value when the conflicts contain a binary file' do
+ merge_request = create_merge_request('conflict-binary-file')
+
+ expect(merge_request.conflicts_can_be_resolved_in_ui?).to be_falsey
+ end
+
+ it 'returns a falsey value when the conflicts contain a file with ambiguous conflict markers' do
+ merge_request = create_merge_request('conflict-contains-conflict-markers')
+
+ expect(merge_request.conflicts_can_be_resolved_in_ui?).to be_falsey
+ end
+
+ it 'returns a falsey value when the conflicts contain a file edited in one branch and deleted in another' do
+ merge_request = create_merge_request('conflict-missing-side')
+
+ expect(merge_request.conflicts_can_be_resolved_in_ui?).to be_falsey
+ end
+
+ it 'returns a truthy value when the conflicts are resolvable in the UI' do
+ merge_request = create_merge_request('conflict-resolvable')
+
+ expect(merge_request.conflicts_can_be_resolved_in_ui?).to be_truthy
+ end
+ end
end
diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb
index 1c0c66969e3..edbbfc3c9e5 100644
--- a/spec/support/test_env.rb
+++ b/spec/support/test_env.rb
@@ -5,25 +5,31 @@ module TestEnv
# When developing the seed repository, comment out the branch you will modify.
BRANCH_SHA = {
- 'empty-branch' => '7efb185',
- 'ends-with.json' => '98b0d8b3',
- 'flatten-dir' => 'e56497b',
- 'feature' => '0b4bc9a',
- 'feature_conflict' => 'bb5206f',
- 'fix' => '48f0be4',
- 'improve/awesome' => '5937ac0',
- 'markdown' => '0ed8c6c',
- 'lfs' => 'be93687',
- 'master' => '5937ac0',
- "'test'" => 'e56497b',
- 'orphaned-branch' => '45127a9',
- 'binary-encoding' => '7b1cf43',
- 'gitattributes' => '5a62481',
- 'expand-collapse-diffs' => '4842455',
- 'expand-collapse-files' => '025db92',
- 'expand-collapse-lines' => '238e82d',
- 'video' => '8879059',
- 'crlf-diff' => '5938907'
+ 'empty-branch' => '7efb185',
+ 'ends-with.json' => '98b0d8b3',
+ 'flatten-dir' => 'e56497b',
+ 'feature' => '0b4bc9a',
+ 'feature_conflict' => 'bb5206f',
+ 'fix' => '48f0be4',
+ 'improve/awesome' => '5937ac0',
+ 'markdown' => '0ed8c6c',
+ 'lfs' => 'be93687',
+ 'master' => '5937ac0',
+ "'test'" => 'e56497b',
+ 'orphaned-branch' => '45127a9',
+ 'binary-encoding' => '7b1cf43',
+ 'gitattributes' => '5a62481',
+ 'expand-collapse-diffs' => '4842455',
+ 'expand-collapse-files' => '025db92',
+ 'expand-collapse-lines' => '238e82d',
+ 'video' => '8879059',
+ 'crlf-diff' => '5938907',
+ 'conflict-start' => '14fa46b',
+ 'conflict-resolvable' => '1450cd6',
+ 'conflict-binary-file' => '259a6fb',
+ 'conflict-contains-conflict-markers' => '5e0964c',
+ 'conflict-missing-side' => 'eb227b3',
+ 'conflict-too-large' => '39fa04f',
}
# gitlab-test-fork is a fork of gitlab-fork, but we don't necessarily
diff --git a/vendor/assets/javascripts/vue-resource.full.js b/vendor/assets/javascripts/vue-resource.full.js
new file mode 100644
index 00000000000..d7981dbec7e
--- /dev/null
+++ b/vendor/assets/javascripts/vue-resource.full.js
@@ -0,0 +1,1318 @@
+/*!
+ * vue-resource v0.9.3
+ * https://github.com/vuejs/vue-resource
+ * Released under the MIT License.
+ */
+
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (global.VueResource = factory());
+}(this, function () { 'use strict';
+
+ /**
+ * Promises/A+ polyfill v1.1.4 (https://github.com/bramstein/promis)
+ */
+
+ var RESOLVED = 0;
+ var REJECTED = 1;
+ var PENDING = 2;
+
+ function Promise$2(executor) {
+
+ this.state = PENDING;
+ this.value = undefined;
+ this.deferred = [];
+
+ var promise = this;
+
+ try {
+ executor(function (x) {
+ promise.resolve(x);
+ }, function (r) {
+ promise.reject(r);
+ });
+ } catch (e) {
+ promise.reject(e);
+ }
+ }
+
+ Promise$2.reject = function (r) {
+ return new Promise$2(function (resolve, reject) {
+ reject(r);
+ });
+ };
+
+ Promise$2.resolve = function (x) {
+ return new Promise$2(function (resolve, reject) {
+ resolve(x);
+ });
+ };
+
+ Promise$2.all = function all(iterable) {
+ return new Promise$2(function (resolve, reject) {
+ var count = 0,
+ result = [];
+
+ if (iterable.length === 0) {
+ resolve(result);
+ }
+
+ function resolver(i) {
+ return function (x) {
+ result[i] = x;
+ count += 1;
+
+ if (count === iterable.length) {
+ resolve(result);
+ }
+ };
+ }
+
+ for (var i = 0; i < iterable.length; i += 1) {
+ Promise$2.resolve(iterable[i]).then(resolver(i), reject);
+ }
+ });
+ };
+
+ Promise$2.race = function race(iterable) {
+ return new Promise$2(function (resolve, reject) {
+ for (var i = 0; i < iterable.length; i += 1) {
+ Promise$2.resolve(iterable[i]).then(resolve, reject);
+ }
+ });
+ };
+
+ var p$1 = Promise$2.prototype;
+
+ p$1.resolve = function resolve(x) {
+ var promise = this;
+
+ if (promise.state === PENDING) {
+ if (x === promise) {
+ throw new TypeError('Promise settled with itself.');
+ }
+
+ var called = false;
+
+ try {
+ var then = x && x['then'];
+
+ if (x !== null && typeof x === 'object' && typeof then === 'function') {
+ then.call(x, function (x) {
+ if (!called) {
+ promise.resolve(x);
+ }
+ called = true;
+ }, function (r) {
+ if (!called) {
+ promise.reject(r);
+ }
+ called = true;
+ });
+ return;
+ }
+ } catch (e) {
+ if (!called) {
+ promise.reject(e);
+ }
+ return;
+ }
+
+ promise.state = RESOLVED;
+ promise.value = x;
+ promise.notify();
+ }
+ };
+
+ p$1.reject = function reject(reason) {
+ var promise = this;
+
+ if (promise.state === PENDING) {
+ if (reason === promise) {
+ throw new TypeError('Promise settled with itself.');
+ }
+
+ promise.state = REJECTED;
+ promise.value = reason;
+ promise.notify();
+ }
+ };
+
+ p$1.notify = function notify() {
+ var promise = this;
+
+ nextTick(function () {
+ if (promise.state !== PENDING) {
+ while (promise.deferred.length) {
+ var deferred = promise.deferred.shift(),
+ onResolved = deferred[0],
+ onRejected = deferred[1],
+ resolve = deferred[2],
+ reject = deferred[3];
+
+ try {
+ if (promise.state === RESOLVED) {
+ if (typeof onResolved === 'function') {
+ resolve(onResolved.call(undefined, promise.value));
+ } else {
+ resolve(promise.value);
+ }
+ } else if (promise.state === REJECTED) {
+ if (typeof onRejected === 'function') {
+ resolve(onRejected.call(undefined, promise.value));
+ } else {
+ reject(promise.value);
+ }
+ }
+ } catch (e) {
+ reject(e);
+ }
+ }
+ }
+ });
+ };
+
+ p$1.then = function then(onResolved, onRejected) {
+ var promise = this;
+
+ return new Promise$2(function (resolve, reject) {
+ promise.deferred.push([onResolved, onRejected, resolve, reject]);
+ promise.notify();
+ });
+ };
+
+ p$1.catch = function (onRejected) {
+ return this.then(undefined, onRejected);
+ };
+
+ var PromiseObj = window.Promise || Promise$2;
+
+ function Promise$1(executor, context) {
+
+ if (executor instanceof PromiseObj) {
+ this.promise = executor;
+ } else {
+ this.promise = new PromiseObj(executor.bind(context));
+ }
+
+ this.context = context;
+ }
+
+ Promise$1.all = function (iterable, context) {
+ return new Promise$1(PromiseObj.all(iterable), context);
+ };
+
+ Promise$1.resolve = function (value, context) {
+ return new Promise$1(PromiseObj.resolve(value), context);
+ };
+
+ Promise$1.reject = function (reason, context) {
+ return new Promise$1(PromiseObj.reject(reason), context);
+ };
+
+ Promise$1.race = function (iterable, context) {
+ return new Promise$1(PromiseObj.race(iterable), context);
+ };
+
+ var p = Promise$1.prototype;
+
+ p.bind = function (context) {
+ this.context = context;
+ return this;
+ };
+
+ p.then = function (fulfilled, rejected) {
+
+ if (fulfilled && fulfilled.bind && this.context) {
+ fulfilled = fulfilled.bind(this.context);
+ }
+
+ if (rejected && rejected.bind && this.context) {
+ rejected = rejected.bind(this.context);
+ }
+
+ return new Promise$1(this.promise.then(fulfilled, rejected), this.context);
+ };
+
+ p.catch = function (rejected) {
+
+ if (rejected && rejected.bind && this.context) {
+ rejected = rejected.bind(this.context);
+ }
+
+ return new Promise$1(this.promise.catch(rejected), this.context);
+ };
+
+ p.finally = function (callback) {
+
+ return this.then(function (value) {
+ callback.call(this);
+ return value;
+ }, function (reason) {
+ callback.call(this);
+ return PromiseObj.reject(reason);
+ });
+ };
+
+ var debug = false;
+ var util = {};
+ var array = [];
+ function Util (Vue) {
+ util = Vue.util;
+ debug = Vue.config.debug || !Vue.config.silent;
+ }
+
+ function warn(msg) {
+ if (typeof console !== 'undefined' && debug) {
+ console.warn('[VueResource warn]: ' + msg);
+ }
+ }
+
+ function error(msg) {
+ if (typeof console !== 'undefined') {
+ console.error(msg);
+ }
+ }
+
+ function nextTick(cb, ctx) {
+ return util.nextTick(cb, ctx);
+ }
+
+ function trim(str) {
+ return str.replace(/^\s*|\s*$/g, '');
+ }
+
+ var isArray = Array.isArray;
+
+ function isString(val) {
+ return typeof val === 'string';
+ }
+
+ function isBoolean(val) {
+ return val === true || val === false;
+ }
+
+ function isFunction(val) {
+ return typeof val === 'function';
+ }
+
+ function isObject(obj) {
+ return obj !== null && typeof obj === 'object';
+ }
+
+ function isPlainObject(obj) {
+ return isObject(obj) && Object.getPrototypeOf(obj) == Object.prototype;
+ }
+
+ function isFormData(obj) {
+ return typeof FormData !== 'undefined' && obj instanceof FormData;
+ }
+
+ function when(value, fulfilled, rejected) {
+
+ var promise = Promise$1.resolve(value);
+
+ if (arguments.length < 2) {
+ return promise;
+ }
+
+ return promise.then(fulfilled, rejected);
+ }
+
+ function options(fn, obj, opts) {
+
+ opts = opts || {};
+
+ if (isFunction(opts)) {
+ opts = opts.call(obj);
+ }
+
+ return merge(fn.bind({ $vm: obj, $options: opts }), fn, { $options: opts });
+ }
+
+ function each(obj, iterator) {
+
+ var i, key;
+
+ if (typeof obj.length == 'number') {
+ for (i = 0; i < obj.length; i++) {
+ iterator.call(obj[i], obj[i], i);
+ }
+ } else if (isObject(obj)) {
+ for (key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ iterator.call(obj[key], obj[key], key);
+ }
+ }
+ }
+
+ return obj;
+ }
+
+ var assign = Object.assign || _assign;
+
+ function merge(target) {
+
+ var args = array.slice.call(arguments, 1);
+
+ args.forEach(function (source) {
+ _merge(target, source, true);
+ });
+
+ return target;
+ }
+
+ function defaults(target) {
+
+ var args = array.slice.call(arguments, 1);
+
+ args.forEach(function (source) {
+
+ for (var key in source) {
+ if (target[key] === undefined) {
+ target[key] = source[key];
+ }
+ }
+ });
+
+ return target;
+ }
+
+ function _assign(target) {
+
+ var args = array.slice.call(arguments, 1);
+
+ args.forEach(function (source) {
+ _merge(target, source);
+ });
+
+ return target;
+ }
+
+ function _merge(target, source, deep) {
+ for (var key in source) {
+ if (deep && (isPlainObject(source[key]) || isArray(source[key]))) {
+ if (isPlainObject(source[key]) && !isPlainObject(target[key])) {
+ target[key] = {};
+ }
+ if (isArray(source[key]) && !isArray(target[key])) {
+ target[key] = [];
+ }
+ _merge(target[key], source[key], deep);
+ } else if (source[key] !== undefined) {
+ target[key] = source[key];
+ }
+ }
+ }
+
+ function root (options, next) {
+
+ var url = next(options);
+
+ if (isString(options.root) && !url.match(/^(https?:)?\//)) {
+ url = options.root + '/' + url;
+ }
+
+ return url;
+ }
+
+ function query (options, next) {
+
+ var urlParams = Object.keys(Url.options.params),
+ query = {},
+ url = next(options);
+
+ each(options.params, function (value, key) {
+ if (urlParams.indexOf(key) === -1) {
+ query[key] = value;
+ }
+ });
+
+ query = Url.params(query);
+
+ if (query) {
+ url += (url.indexOf('?') == -1 ? '?' : '&') + query;
+ }
+
+ return url;
+ }
+
+ /**
+ * URL Template v2.0.6 (https://github.com/bramstein/url-template)
+ */
+
+ function expand(url, params, variables) {
+
+ var tmpl = parse(url),
+ expanded = tmpl.expand(params);
+
+ if (variables) {
+ variables.push.apply(variables, tmpl.vars);
+ }
+
+ return expanded;
+ }
+
+ function parse(template) {
+
+ var operators = ['+', '#', '.', '/', ';', '?', '&'],
+ variables = [];
+
+ return {
+ vars: variables,
+ expand: function (context) {
+ return template.replace(/\{([^\{\}]+)\}|([^\{\}]+)/g, function (_, expression, literal) {
+ if (expression) {
+
+ var operator = null,
+ values = [];
+
+ if (operators.indexOf(expression.charAt(0)) !== -1) {
+ operator = expression.charAt(0);
+ expression = expression.substr(1);
+ }
+
+ expression.split(/,/g).forEach(function (variable) {
+ var tmp = /([^:\*]*)(?::(\d+)|(\*))?/.exec(variable);
+ values.push.apply(values, getValues(context, operator, tmp[1], tmp[2] || tmp[3]));
+ variables.push(tmp[1]);
+ });
+
+ if (operator && operator !== '+') {
+
+ var separator = ',';
+
+ if (operator === '?') {
+ separator = '&';
+ } else if (operator !== '#') {
+ separator = operator;
+ }
+
+ return (values.length !== 0 ? operator : '') + values.join(separator);
+ } else {
+ return values.join(',');
+ }
+ } else {
+ return encodeReserved(literal);
+ }
+ });
+ }
+ };
+ }
+
+ function getValues(context, operator, key, modifier) {
+
+ var value = context[key],
+ result = [];
+
+ if (isDefined(value) && value !== '') {
+ if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
+ value = value.toString();
+
+ if (modifier && modifier !== '*') {
+ value = value.substring(0, parseInt(modifier, 10));
+ }
+
+ result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : null));
+ } else {
+ if (modifier === '*') {
+ if (Array.isArray(value)) {
+ value.filter(isDefined).forEach(function (value) {
+ result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : null));
+ });
+ } else {
+ Object.keys(value).forEach(function (k) {
+ if (isDefined(value[k])) {
+ result.push(encodeValue(operator, value[k], k));
+ }
+ });
+ }
+ } else {
+ var tmp = [];
+
+ if (Array.isArray(value)) {
+ value.filter(isDefined).forEach(function (value) {
+ tmp.push(encodeValue(operator, value));
+ });
+ } else {
+ Object.keys(value).forEach(function (k) {
+ if (isDefined(value[k])) {
+ tmp.push(encodeURIComponent(k));
+ tmp.push(encodeValue(operator, value[k].toString()));
+ }
+ });
+ }
+
+ if (isKeyOperator(operator)) {
+ result.push(encodeURIComponent(key) + '=' + tmp.join(','));
+ } else if (tmp.length !== 0) {
+ result.push(tmp.join(','));
+ }
+ }
+ }
+ } else {
+ if (operator === ';') {
+ result.push(encodeURIComponent(key));
+ } else if (value === '' && (operator === '&' || operator === '?')) {
+ result.push(encodeURIComponent(key) + '=');
+ } else if (value === '') {
+ result.push('');
+ }
+ }
+
+ return result;
+ }
+
+ function isDefined(value) {
+ return value !== undefined && value !== null;
+ }
+
+ function isKeyOperator(operator) {
+ return operator === ';' || operator === '&' || operator === '?';
+ }
+
+ function encodeValue(operator, value, key) {
+
+ value = operator === '+' || operator === '#' ? encodeReserved(value) : encodeURIComponent(value);
+
+ if (key) {
+ return encodeURIComponent(key) + '=' + value;
+ } else {
+ return value;
+ }
+ }
+
+ function encodeReserved(str) {
+ return str.split(/(%[0-9A-Fa-f]{2})/g).map(function (part) {
+ if (!/%[0-9A-Fa-f]/.test(part)) {
+ part = encodeURI(part);
+ }
+ return part;
+ }).join('');
+ }
+
+ function template (options) {
+
+ var variables = [],
+ url = expand(options.url, options.params, variables);
+
+ variables.forEach(function (key) {
+ delete options.params[key];
+ });
+
+ return url;
+ }
+
+ /**
+ * Service for URL templating.
+ */
+
+ var ie = document.documentMode;
+ var el = document.createElement('a');
+
+ function Url(url, params) {
+
+ var self = this || {},
+ options = url,
+ transform;
+
+ if (isString(url)) {
+ options = { url: url, params: params };
+ }
+
+ options = merge({}, Url.options, self.$options, options);
+
+ Url.transforms.forEach(function (handler) {
+ transform = factory(handler, transform, self.$vm);
+ });
+
+ return transform(options);
+ }
+
+ /**
+ * Url options.
+ */
+
+ Url.options = {
+ url: '',
+ root: null,
+ params: {}
+ };
+
+ /**
+ * Url transforms.
+ */
+
+ Url.transforms = [template, query, root];
+
+ /**
+ * Encodes a Url parameter string.
+ *
+ * @param {Object} obj
+ */
+
+ Url.params = function (obj) {
+
+ var params = [],
+ escape = encodeURIComponent;
+
+ params.add = function (key, value) {
+
+ if (isFunction(value)) {
+ value = value();
+ }
+
+ if (value === null) {
+ value = '';
+ }
+
+ this.push(escape(key) + '=' + escape(value));
+ };
+
+ serialize(params, obj);
+
+ return params.join('&').replace(/%20/g, '+');
+ };
+
+ /**
+ * Parse a URL and return its components.
+ *
+ * @param {String} url
+ */
+
+ Url.parse = function (url) {
+
+ if (ie) {
+ el.href = url;
+ url = el.href;
+ }
+
+ el.href = url;
+
+ return {
+ href: el.href,
+ protocol: el.protocol ? el.protocol.replace(/:$/, '') : '',
+ port: el.port,
+ host: el.host,
+ hostname: el.hostname,
+ pathname: el.pathname.charAt(0) === '/' ? el.pathname : '/' + el.pathname,
+ search: el.search ? el.search.replace(/^\?/, '') : '',
+ hash: el.hash ? el.hash.replace(/^#/, '') : ''
+ };
+ };
+
+ function factory(handler, next, vm) {
+ return function (options) {
+ return handler.call(vm, options, next);
+ };
+ }
+
+ function serialize(params, obj, scope) {
+
+ var array = isArray(obj),
+ plain = isPlainObject(obj),
+ hash;
+
+ each(obj, function (value, key) {
+
+ hash = isObject(value) || isArray(value);
+
+ if (scope) {
+ key = scope + '[' + (plain || hash ? key : '') + ']';
+ }
+
+ if (!scope && array) {
+ params.add(value.name, value.value);
+ } else if (hash) {
+ serialize(params, value, key);
+ } else {
+ params.add(key, value);
+ }
+ });
+ }
+
+ function xdrClient (request) {
+ return new Promise$1(function (resolve) {
+
+ var xdr = new XDomainRequest(),
+ handler = function (event) {
+
+ var response = request.respondWith(xdr.responseText, {
+ status: xdr.status,
+ statusText: xdr.statusText
+ });
+
+ resolve(response);
+ };
+
+ request.abort = function () {
+ return xdr.abort();
+ };
+
+ xdr.open(request.method, request.getUrl(), true);
+ xdr.timeout = 0;
+ xdr.onload = handler;
+ xdr.onerror = handler;
+ xdr.ontimeout = function () {};
+ xdr.onprogress = function () {};
+ xdr.send(request.getBody());
+ });
+ }
+
+ var ORIGIN_URL = Url.parse(location.href);
+ var SUPPORTS_CORS = 'withCredentials' in new XMLHttpRequest();
+
+ function cors (request, next) {
+
+ if (!isBoolean(request.crossOrigin) && crossOrigin(request)) {
+ request.crossOrigin = true;
+ }
+
+ if (request.crossOrigin) {
+
+ if (!SUPPORTS_CORS) {
+ request.client = xdrClient;
+ }
+
+ delete request.emulateHTTP;
+ }
+
+ next();
+ }
+
+ function crossOrigin(request) {
+
+ var requestUrl = Url.parse(Url(request));
+
+ return requestUrl.protocol !== ORIGIN_URL.protocol || requestUrl.host !== ORIGIN_URL.host;
+ }
+
+ function body (request, next) {
+
+ if (request.emulateJSON && isPlainObject(request.body)) {
+ request.body = Url.params(request.body);
+ request.headers['Content-Type'] = 'application/x-www-form-urlencoded';
+ }
+
+ if (isFormData(request.body)) {
+ delete request.headers['Content-Type'];
+ }
+
+ if (isPlainObject(request.body)) {
+ request.body = JSON.stringify(request.body);
+ }
+
+ next(function (response) {
+
+ var contentType = response.headers['Content-Type'];
+
+ if (isString(contentType) && contentType.indexOf('application/json') === 0) {
+
+ try {
+ response.data = response.json();
+ } catch (e) {
+ response.data = null;
+ }
+ } else {
+ response.data = response.text();
+ }
+ });
+ }
+
+ function jsonpClient (request) {
+ return new Promise$1(function (resolve) {
+
+ var name = request.jsonp || 'callback',
+ callback = '_jsonp' + Math.random().toString(36).substr(2),
+ body = null,
+ handler,
+ script;
+
+ handler = function (event) {
+
+ var status = 0;
+
+ if (event.type === 'load' && body !== null) {
+ status = 200;
+ } else if (event.type === 'error') {
+ status = 404;
+ }
+
+ resolve(request.respondWith(body, { status: status }));
+
+ delete window[callback];
+ document.body.removeChild(script);
+ };
+
+ request.params[name] = callback;
+
+ window[callback] = function (result) {
+ body = JSON.stringify(result);
+ };
+
+ script = document.createElement('script');
+ script.src = request.getUrl();
+ script.type = 'text/javascript';
+ script.async = true;
+ script.onload = handler;
+ script.onerror = handler;
+
+ document.body.appendChild(script);
+ });
+ }
+
+ function jsonp (request, next) {
+
+ if (request.method == 'JSONP') {
+ request.client = jsonpClient;
+ }
+
+ next(function (response) {
+
+ if (request.method == 'JSONP') {
+ response.data = response.json();
+ }
+ });
+ }
+
+ function before (request, next) {
+
+ if (isFunction(request.before)) {
+ request.before.call(this, request);
+ }
+
+ next();
+ }
+
+ /**
+ * HTTP method override Interceptor.
+ */
+
+ function method (request, next) {
+
+ if (request.emulateHTTP && /^(PUT|PATCH|DELETE)$/i.test(request.method)) {
+ request.headers['X-HTTP-Method-Override'] = request.method;
+ request.method = 'POST';
+ }
+
+ next();
+ }
+
+ function header (request, next) {
+
+ request.method = request.method.toUpperCase();
+ request.headers = assign({}, Http.headers.common, !request.crossOrigin ? Http.headers.custom : {}, Http.headers[request.method.toLowerCase()], request.headers);
+
+ next();
+ }
+
+ /**
+ * Timeout Interceptor.
+ */
+
+ function timeout (request, next) {
+
+ var timeout;
+
+ if (request.timeout) {
+ timeout = setTimeout(function () {
+ request.abort();
+ }, request.timeout);
+ }
+
+ next(function (response) {
+
+ clearTimeout(timeout);
+ });
+ }
+
+ function xhrClient (request) {
+ return new Promise$1(function (resolve) {
+
+ var xhr = new XMLHttpRequest(),
+ handler = function (event) {
+
+ var response = request.respondWith('response' in xhr ? xhr.response : xhr.responseText, {
+ status: xhr.status === 1223 ? 204 : xhr.status, // IE9 status bug
+ statusText: xhr.status === 1223 ? 'No Content' : trim(xhr.statusText),
+ headers: parseHeaders(xhr.getAllResponseHeaders())
+ });
+
+ resolve(response);
+ };
+
+ request.abort = function () {
+ return xhr.abort();
+ };
+
+ xhr.open(request.method, request.getUrl(), true);
+ xhr.timeout = 0;
+ xhr.onload = handler;
+ xhr.onerror = handler;
+
+ if (request.progress) {
+ if (request.method === 'GET') {
+ xhr.addEventListener('progress', request.progress);
+ } else if (/^(POST|PUT)$/i.test(request.method)) {
+ xhr.upload.addEventListener('progress', request.progress);
+ }
+ }
+
+ if (request.credentials === true) {
+ xhr.withCredentials = true;
+ }
+
+ each(request.headers || {}, function (value, header) {
+ xhr.setRequestHeader(header, value);
+ });
+
+ xhr.send(request.getBody());
+ });
+ }
+
+ function parseHeaders(str) {
+
+ var headers = {},
+ value,
+ name,
+ i;
+
+ each(trim(str).split('\n'), function (row) {
+
+ i = row.indexOf(':');
+ name = trim(row.slice(0, i));
+ value = trim(row.slice(i + 1));
+
+ if (headers[name]) {
+
+ if (isArray(headers[name])) {
+ headers[name].push(value);
+ } else {
+ headers[name] = [headers[name], value];
+ }
+ } else {
+
+ headers[name] = value;
+ }
+ });
+
+ return headers;
+ }
+
+ function Client (context) {
+
+ var reqHandlers = [sendRequest],
+ resHandlers = [],
+ handler;
+
+ if (!isObject(context)) {
+ context = null;
+ }
+
+ function Client(request) {
+ return new Promise$1(function (resolve) {
+
+ function exec() {
+
+ handler = reqHandlers.pop();
+
+ if (isFunction(handler)) {
+ handler.call(context, request, next);
+ } else {
+ warn('Invalid interceptor of type ' + typeof handler + ', must be a function');
+ next();
+ }
+ }
+
+ function next(response) {
+
+ if (isFunction(response)) {
+
+ resHandlers.unshift(response);
+ } else if (isObject(response)) {
+
+ resHandlers.forEach(function (handler) {
+ response = when(response, function (response) {
+ return handler.call(context, response) || response;
+ });
+ });
+
+ when(response, resolve);
+
+ return;
+ }
+
+ exec();
+ }
+
+ exec();
+ }, context);
+ }
+
+ Client.use = function (handler) {
+ reqHandlers.push(handler);
+ };
+
+ return Client;
+ }
+
+ function sendRequest(request, resolve) {
+
+ var client = request.client || xhrClient;
+
+ resolve(client(request));
+ }
+
+ var classCallCheck = function (instance, Constructor) {
+ if (!(instance instanceof Constructor)) {
+ throw new TypeError("Cannot call a class as a function");
+ }
+ };
+
+ /**
+ * HTTP Response.
+ */
+
+ var Response = function () {
+ function Response(body, _ref) {
+ var url = _ref.url;
+ var headers = _ref.headers;
+ var status = _ref.status;
+ var statusText = _ref.statusText;
+ classCallCheck(this, Response);
+
+
+ this.url = url;
+ this.body = body;
+ this.headers = headers || {};
+ this.status = status || 0;
+ this.statusText = statusText || '';
+ this.ok = status >= 200 && status < 300;
+ }
+
+ Response.prototype.text = function text() {
+ return this.body;
+ };
+
+ Response.prototype.blob = function blob() {
+ return new Blob([this.body]);
+ };
+
+ Response.prototype.json = function json() {
+ return JSON.parse(this.body);
+ };
+
+ return Response;
+ }();
+
+ var Request = function () {
+ function Request(options) {
+ classCallCheck(this, Request);
+
+
+ this.method = 'GET';
+ this.body = null;
+ this.params = {};
+ this.headers = {};
+
+ assign(this, options);
+ }
+
+ Request.prototype.getUrl = function getUrl() {
+ return Url(this);
+ };
+
+ Request.prototype.getBody = function getBody() {
+ return this.body;
+ };
+
+ Request.prototype.respondWith = function respondWith(body, options) {
+ return new Response(body, assign(options || {}, { url: this.getUrl() }));
+ };
+
+ return Request;
+ }();
+
+ /**
+ * Service for sending network requests.
+ */
+
+ var CUSTOM_HEADERS = { 'X-Requested-With': 'XMLHttpRequest' };
+ var COMMON_HEADERS = { 'Accept': 'application/json, text/plain, */*' };
+ var JSON_CONTENT_TYPE = { 'Content-Type': 'application/json;charset=utf-8' };
+
+ function Http(options) {
+
+ var self = this || {},
+ client = Client(self.$vm);
+
+ defaults(options || {}, self.$options, Http.options);
+
+ Http.interceptors.forEach(function (handler) {
+ client.use(handler);
+ });
+
+ return client(new Request(options)).then(function (response) {
+
+ return response.ok ? response : Promise$1.reject(response);
+ }, function (response) {
+
+ if (response instanceof Error) {
+ error(response);
+ }
+
+ return Promise$1.reject(response);
+ });
+ }
+
+ Http.options = {};
+
+ Http.headers = {
+ put: JSON_CONTENT_TYPE,
+ post: JSON_CONTENT_TYPE,
+ patch: JSON_CONTENT_TYPE,
+ delete: JSON_CONTENT_TYPE,
+ custom: CUSTOM_HEADERS,
+ common: COMMON_HEADERS
+ };
+
+ Http.interceptors = [before, timeout, method, body, jsonp, header, cors];
+
+ ['get', 'delete', 'head', 'jsonp'].forEach(function (method) {
+
+ Http[method] = function (url, options) {
+ return this(assign(options || {}, { url: url, method: method }));
+ };
+ });
+
+ ['post', 'put', 'patch'].forEach(function (method) {
+
+ Http[method] = function (url, body, options) {
+ return this(assign(options || {}, { url: url, method: method, body: body }));
+ };
+ });
+
+ function Resource(url, params, actions, options) {
+
+ var self = this || {},
+ resource = {};
+
+ actions = assign({}, Resource.actions, actions);
+
+ each(actions, function (action, name) {
+
+ action = merge({ url: url, params: params || {} }, options, action);
+
+ resource[name] = function () {
+ return (self.$http || Http)(opts(action, arguments));
+ };
+ });
+
+ return resource;
+ }
+
+ function opts(action, args) {
+
+ var options = assign({}, action),
+ params = {},
+ body;
+
+ switch (args.length) {
+
+ case 2:
+
+ params = args[0];
+ body = args[1];
+
+ break;
+
+ case 1:
+
+ if (/^(POST|PUT|PATCH)$/i.test(options.method)) {
+ body = args[0];
+ } else {
+ params = args[0];
+ }
+
+ break;
+
+ case 0:
+
+ break;
+
+ default:
+
+ throw 'Expected up to 4 arguments [params, body], got ' + args.length + ' arguments';
+ }
+
+ options.body = body;
+ options.params = assign({}, options.params, params);
+
+ return options;
+ }
+
+ Resource.actions = {
+
+ get: { method: 'GET' },
+ save: { method: 'POST' },
+ query: { method: 'GET' },
+ update: { method: 'PUT' },
+ remove: { method: 'DELETE' },
+ delete: { method: 'DELETE' }
+
+ };
+
+ function plugin(Vue) {
+
+ if (plugin.installed) {
+ return;
+ }
+
+ Util(Vue);
+
+ Vue.url = Url;
+ Vue.http = Http;
+ Vue.resource = Resource;
+ Vue.Promise = Promise$1;
+
+ Object.defineProperties(Vue.prototype, {
+
+ $url: {
+ get: function () {
+ return options(Vue.url, this, this.$options.url);
+ }
+ },
+
+ $http: {
+ get: function () {
+ return options(Vue.http, this, this.$options.http);
+ }
+ },
+
+ $resource: {
+ get: function () {
+ return Vue.resource.bind(this);
+ }
+ },
+
+ $promise: {
+ get: function () {
+ var _this = this;
+
+ return function (executor) {
+ return new Vue.Promise(executor, _this);
+ };
+ }
+ }
+
+ });
+ }
+
+ if (typeof window !== 'undefined' && window.Vue) {
+ window.Vue.use(plugin);
+ }
+
+ return plugin;
+
+})); \ No newline at end of file
diff --git a/vendor/assets/javascripts/vue-resource.js.erb b/vendor/assets/javascripts/vue-resource.js.erb
new file mode 100644
index 00000000000..8001775ce98
--- /dev/null
+++ b/vendor/assets/javascripts/vue-resource.js.erb
@@ -0,0 +1,2 @@
+<% type = Rails.env.development? ? 'full' : 'min' %>
+<%= File.read(Rails.root.join("vendor/assets/javascripts/vue-resource.#{type}.js")) %>
diff --git a/vendor/assets/javascripts/vue-resource.min.js b/vendor/assets/javascripts/vue-resource.min.js
new file mode 100644
index 00000000000..6bff73a2a67
--- /dev/null
+++ b/vendor/assets/javascripts/vue-resource.min.js
@@ -0,0 +1,7 @@
+/*!
+ * vue-resource v0.9.3
+ * https://github.com/vuejs/vue-resource
+ * Released under the MIT License.
+ */
+
+!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):t.VueResource=n()}(this,function(){"use strict";function t(t){this.state=Z,this.value=void 0,this.deferred=[];var n=this;try{t(function(t){n.resolve(t)},function(t){n.reject(t)})}catch(e){n.reject(e)}}function n(t,n){t instanceof nt?this.promise=t:this.promise=new nt(t.bind(n)),this.context=n}function e(t){rt=t.util,ot=t.config.debug||!t.config.silent}function o(t){"undefined"!=typeof console&&ot&&console.warn("[VueResource warn]: "+t)}function r(t){"undefined"!=typeof console&&console.error(t)}function i(t,n){return rt.nextTick(t,n)}function u(t){return t.replace(/^\s*|\s*$/g,"")}function s(t){return"string"==typeof t}function c(t){return t===!0||t===!1}function a(t){return"function"==typeof t}function f(t){return null!==t&&"object"==typeof t}function h(t){return f(t)&&Object.getPrototypeOf(t)==Object.prototype}function p(t){return"undefined"!=typeof FormData&&t instanceof FormData}function l(t,e,o){var r=n.resolve(t);return arguments.length<2?r:r.then(e,o)}function d(t,n,e){return e=e||{},a(e)&&(e=e.call(n)),v(t.bind({$vm:n,$options:e}),t,{$options:e})}function m(t,n){var e,o;if("number"==typeof t.length)for(e=0;e<t.length;e++)n.call(t[e],t[e],e);else if(f(t))for(o in t)t.hasOwnProperty(o)&&n.call(t[o],t[o],o);return t}function v(t){var n=it.slice.call(arguments,1);return n.forEach(function(n){g(t,n,!0)}),t}function y(t){var n=it.slice.call(arguments,1);return n.forEach(function(n){for(var e in n)void 0===t[e]&&(t[e]=n[e])}),t}function b(t){var n=it.slice.call(arguments,1);return n.forEach(function(n){g(t,n)}),t}function g(t,n,e){for(var o in n)e&&(h(n[o])||ut(n[o]))?(h(n[o])&&!h(t[o])&&(t[o]={}),ut(n[o])&&!ut(t[o])&&(t[o]=[]),g(t[o],n[o],e)):void 0!==n[o]&&(t[o]=n[o])}function w(t,n){var e=n(t);return s(t.root)&&!e.match(/^(https?:)?\//)&&(e=t.root+"/"+e),e}function T(t,n){var e=Object.keys(R.options.params),o={},r=n(t);return m(t.params,function(t,n){e.indexOf(n)===-1&&(o[n]=t)}),o=R.params(o),o&&(r+=(r.indexOf("?")==-1?"?":"&")+o),r}function j(t,n,e){var o=E(t),r=o.expand(n);return e&&e.push.apply(e,o.vars),r}function E(t){var n=["+","#",".","/",";","?","&"],e=[];return{vars:e,expand:function(o){return t.replace(/\{([^\{\}]+)\}|([^\{\}]+)/g,function(t,r,i){if(r){var u=null,s=[];if(n.indexOf(r.charAt(0))!==-1&&(u=r.charAt(0),r=r.substr(1)),r.split(/,/g).forEach(function(t){var n=/([^:\*]*)(?::(\d+)|(\*))?/.exec(t);s.push.apply(s,x(o,u,n[1],n[2]||n[3])),e.push(n[1])}),u&&"+"!==u){var c=",";return"?"===u?c="&":"#"!==u&&(c=u),(0!==s.length?u:"")+s.join(c)}return s.join(",")}return $(i)})}}}function x(t,n,e,o){var r=t[e],i=[];if(O(r)&&""!==r)if("string"==typeof r||"number"==typeof r||"boolean"==typeof r)r=r.toString(),o&&"*"!==o&&(r=r.substring(0,parseInt(o,10))),i.push(C(n,r,P(n)?e:null));else if("*"===o)Array.isArray(r)?r.filter(O).forEach(function(t){i.push(C(n,t,P(n)?e:null))}):Object.keys(r).forEach(function(t){O(r[t])&&i.push(C(n,r[t],t))});else{var u=[];Array.isArray(r)?r.filter(O).forEach(function(t){u.push(C(n,t))}):Object.keys(r).forEach(function(t){O(r[t])&&(u.push(encodeURIComponent(t)),u.push(C(n,r[t].toString())))}),P(n)?i.push(encodeURIComponent(e)+"="+u.join(",")):0!==u.length&&i.push(u.join(","))}else";"===n?i.push(encodeURIComponent(e)):""!==r||"&"!==n&&"?"!==n?""===r&&i.push(""):i.push(encodeURIComponent(e)+"=");return i}function O(t){return void 0!==t&&null!==t}function P(t){return";"===t||"&"===t||"?"===t}function C(t,n,e){return n="+"===t||"#"===t?$(n):encodeURIComponent(n),e?encodeURIComponent(e)+"="+n:n}function $(t){return t.split(/(%[0-9A-Fa-f]{2})/g).map(function(t){return/%[0-9A-Fa-f]/.test(t)||(t=encodeURI(t)),t}).join("")}function U(t){var n=[],e=j(t.url,t.params,n);return n.forEach(function(n){delete t.params[n]}),e}function R(t,n){var e,o=this||{},r=t;return s(t)&&(r={url:t,params:n}),r=v({},R.options,o.$options,r),R.transforms.forEach(function(t){e=A(t,e,o.$vm)}),e(r)}function A(t,n,e){return function(o){return t.call(e,o,n)}}function S(t,n,e){var o,r=ut(n),i=h(n);m(n,function(n,u){o=f(n)||ut(n),e&&(u=e+"["+(i||o?u:"")+"]"),!e&&r?t.add(n.name,n.value):o?S(t,n,u):t.add(u,n)})}function k(t){return new n(function(n){var e=new XDomainRequest,o=function(o){var r=t.respondWith(e.responseText,{status:e.status,statusText:e.statusText});n(r)};t.abort=function(){return e.abort()},e.open(t.method,t.getUrl(),!0),e.timeout=0,e.onload=o,e.onerror=o,e.ontimeout=function(){},e.onprogress=function(){},e.send(t.getBody())})}function H(t,n){!c(t.crossOrigin)&&I(t)&&(t.crossOrigin=!0),t.crossOrigin&&(ht||(t.client=k),delete t.emulateHTTP),n()}function I(t){var n=R.parse(R(t));return n.protocol!==ft.protocol||n.host!==ft.host}function L(t,n){t.emulateJSON&&h(t.body)&&(t.body=R.params(t.body),t.headers["Content-Type"]="application/x-www-form-urlencoded"),p(t.body)&&delete t.headers["Content-Type"],h(t.body)&&(t.body=JSON.stringify(t.body)),n(function(t){var n=t.headers["Content-Type"];if(s(n)&&0===n.indexOf("application/json"))try{t.data=t.json()}catch(e){t.data=null}else t.data=t.text()})}function q(t){return new n(function(n){var e,o,r=t.jsonp||"callback",i="_jsonp"+Math.random().toString(36).substr(2),u=null;e=function(e){var r=0;"load"===e.type&&null!==u?r=200:"error"===e.type&&(r=404),n(t.respondWith(u,{status:r})),delete window[i],document.body.removeChild(o)},t.params[r]=i,window[i]=function(t){u=JSON.stringify(t)},o=document.createElement("script"),o.src=t.getUrl(),o.type="text/javascript",o.async=!0,o.onload=e,o.onerror=e,document.body.appendChild(o)})}function N(t,n){"JSONP"==t.method&&(t.client=q),n(function(n){"JSONP"==t.method&&(n.data=n.json())})}function D(t,n){a(t.before)&&t.before.call(this,t),n()}function J(t,n){t.emulateHTTP&&/^(PUT|PATCH|DELETE)$/i.test(t.method)&&(t.headers["X-HTTP-Method-Override"]=t.method,t.method="POST"),n()}function M(t,n){t.method=t.method.toUpperCase(),t.headers=st({},V.headers.common,t.crossOrigin?{}:V.headers.custom,V.headers[t.method.toLowerCase()],t.headers),n()}function X(t,n){var e;t.timeout&&(e=setTimeout(function(){t.abort()},t.timeout)),n(function(t){clearTimeout(e)})}function W(t){return new n(function(n){var e=new XMLHttpRequest,o=function(o){var r=t.respondWith("response"in e?e.response:e.responseText,{status:1223===e.status?204:e.status,statusText:1223===e.status?"No Content":u(e.statusText),headers:B(e.getAllResponseHeaders())});n(r)};t.abort=function(){return e.abort()},e.open(t.method,t.getUrl(),!0),e.timeout=0,e.onload=o,e.onerror=o,t.progress&&("GET"===t.method?e.addEventListener("progress",t.progress):/^(POST|PUT)$/i.test(t.method)&&e.upload.addEventListener("progress",t.progress)),t.credentials===!0&&(e.withCredentials=!0),m(t.headers||{},function(t,n){e.setRequestHeader(n,t)}),e.send(t.getBody())})}function B(t){var n,e,o,r={};return m(u(t).split("\n"),function(t){o=t.indexOf(":"),e=u(t.slice(0,o)),n=u(t.slice(o+1)),r[e]?ut(r[e])?r[e].push(n):r[e]=[r[e],n]:r[e]=n}),r}function F(t){function e(e){return new n(function(n){function s(){r=i.pop(),a(r)?r.call(t,e,c):(o("Invalid interceptor of type "+typeof r+", must be a function"),c())}function c(e){if(a(e))u.unshift(e);else if(f(e))return u.forEach(function(n){e=l(e,function(e){return n.call(t,e)||e})}),void l(e,n);s()}s()},t)}var r,i=[G],u=[];return f(t)||(t=null),e.use=function(t){i.push(t)},e}function G(t,n){var e=t.client||W;n(e(t))}function V(t){var e=this||{},o=F(e.$vm);return y(t||{},e.$options,V.options),V.interceptors.forEach(function(t){o.use(t)}),o(new dt(t)).then(function(t){return t.ok?t:n.reject(t)},function(t){return t instanceof Error&&r(t),n.reject(t)})}function _(t,n,e,o){var r=this||{},i={};return e=st({},_.actions,e),m(e,function(e,u){e=v({url:t,params:n||{}},o,e),i[u]=function(){return(r.$http||V)(z(e,arguments))}}),i}function z(t,n){var e,o=st({},t),r={};switch(n.length){case 2:r=n[0],e=n[1];break;case 1:/^(POST|PUT|PATCH)$/i.test(o.method)?e=n[0]:r=n[0];break;case 0:break;default:throw"Expected up to 4 arguments [params, body], got "+n.length+" arguments"}return o.body=e,o.params=st({},o.params,r),o}function K(t){K.installed||(e(t),t.url=R,t.http=V,t.resource=_,t.Promise=n,Object.defineProperties(t.prototype,{$url:{get:function(){return d(t.url,this,this.$options.url)}},$http:{get:function(){return d(t.http,this,this.$options.http)}},$resource:{get:function(){return t.resource.bind(this)}},$promise:{get:function(){var n=this;return function(e){return new t.Promise(e,n)}}}}))}var Q=0,Y=1,Z=2;t.reject=function(n){return new t(function(t,e){e(n)})},t.resolve=function(n){return new t(function(t,e){t(n)})},t.all=function(n){return new t(function(e,o){function r(t){return function(o){u[t]=o,i+=1,i===n.length&&e(u)}}var i=0,u=[];0===n.length&&e(u);for(var s=0;s<n.length;s+=1)t.resolve(n[s]).then(r(s),o)})},t.race=function(n){return new t(function(e,o){for(var r=0;r<n.length;r+=1)t.resolve(n[r]).then(e,o)})};var tt=t.prototype;tt.resolve=function(t){var n=this;if(n.state===Z){if(t===n)throw new TypeError("Promise settled with itself.");var e=!1;try{var o=t&&t.then;if(null!==t&&"object"==typeof t&&"function"==typeof o)return void o.call(t,function(t){e||n.resolve(t),e=!0},function(t){e||n.reject(t),e=!0})}catch(r){return void(e||n.reject(r))}n.state=Q,n.value=t,n.notify()}},tt.reject=function(t){var n=this;if(n.state===Z){if(t===n)throw new TypeError("Promise settled with itself.");n.state=Y,n.value=t,n.notify()}},tt.notify=function(){var t=this;i(function(){if(t.state!==Z)for(;t.deferred.length;){var n=t.deferred.shift(),e=n[0],o=n[1],r=n[2],i=n[3];try{t.state===Q?r("function"==typeof e?e.call(void 0,t.value):t.value):t.state===Y&&("function"==typeof o?r(o.call(void 0,t.value)):i(t.value))}catch(u){i(u)}}})},tt.then=function(n,e){var o=this;return new t(function(t,r){o.deferred.push([n,e,t,r]),o.notify()})},tt["catch"]=function(t){return this.then(void 0,t)};var nt=window.Promise||t;n.all=function(t,e){return new n(nt.all(t),e)},n.resolve=function(t,e){return new n(nt.resolve(t),e)},n.reject=function(t,e){return new n(nt.reject(t),e)},n.race=function(t,e){return new n(nt.race(t),e)};var et=n.prototype;et.bind=function(t){return this.context=t,this},et.then=function(t,e){return t&&t.bind&&this.context&&(t=t.bind(this.context)),e&&e.bind&&this.context&&(e=e.bind(this.context)),new n(this.promise.then(t,e),this.context)},et["catch"]=function(t){return t&&t.bind&&this.context&&(t=t.bind(this.context)),new n(this.promise["catch"](t),this.context)},et["finally"]=function(t){return this.then(function(n){return t.call(this),n},function(n){return t.call(this),nt.reject(n)})};var ot=!1,rt={},it=[],ut=Array.isArray,st=Object.assign||b,ct=document.documentMode,at=document.createElement("a");R.options={url:"",root:null,params:{}},R.transforms=[U,T,w],R.params=function(t){var n=[],e=encodeURIComponent;return n.add=function(t,n){a(n)&&(n=n()),null===n&&(n=""),this.push(e(t)+"="+e(n))},S(n,t),n.join("&").replace(/%20/g,"+")},R.parse=function(t){return ct&&(at.href=t,t=at.href),at.href=t,{href:at.href,protocol:at.protocol?at.protocol.replace(/:$/,""):"",port:at.port,host:at.host,hostname:at.hostname,pathname:"/"===at.pathname.charAt(0)?at.pathname:"/"+at.pathname,search:at.search?at.search.replace(/^\?/,""):"",hash:at.hash?at.hash.replace(/^#/,""):""}};var ft=R.parse(location.href),ht="withCredentials"in new XMLHttpRequest,pt=function(t,n){if(!(t instanceof n))throw new TypeError("Cannot call a class as a function")},lt=function(){function t(n,e){var o=e.url,r=e.headers,i=e.status,u=e.statusText;pt(this,t),this.url=o,this.body=n,this.headers=r||{},this.status=i||0,this.statusText=u||"",this.ok=i>=200&&i<300}return t.prototype.text=function(){return this.body},t.prototype.blob=function(){return new Blob([this.body])},t.prototype.json=function(){return JSON.parse(this.body)},t}(),dt=function(){function t(n){pt(this,t),this.method="GET",this.body=null,this.params={},this.headers={},st(this,n)}return t.prototype.getUrl=function(){return R(this)},t.prototype.getBody=function(){return this.body},t.prototype.respondWith=function(t,n){return new lt(t,st(n||{},{url:this.getUrl()}))},t}(),mt={"X-Requested-With":"XMLHttpRequest"},vt={Accept:"application/json, text/plain, */*"},yt={"Content-Type":"application/json;charset=utf-8"};return V.options={},V.headers={put:yt,post:yt,patch:yt,"delete":yt,custom:mt,common:vt},V.interceptors=[D,X,J,L,N,M,H],["get","delete","head","jsonp"].forEach(function(t){V[t]=function(n,e){return this(st(e||{},{url:n,method:t}))}}),["post","put","patch"].forEach(function(t){V[t]=function(n,e,o){return this(st(o||{},{url:n,method:t,body:e}))}}),_.actions={get:{method:"GET"},save:{method:"POST"},query:{method:"GET"},update:{method:"PUT"},remove:{method:"DELETE"},"delete":{method:"DELETE"}},"undefined"!=typeof window&&window.Vue&&window.Vue.use(K),K}); \ No newline at end of file
diff --git a/vendor/assets/javascripts/vue.full.js b/vendor/assets/javascripts/vue.full.js
new file mode 100644
index 00000000000..7ae95897a01
--- /dev/null
+++ b/vendor/assets/javascripts/vue.full.js
@@ -0,0 +1,10073 @@
+/*!
+ * Vue.js v1.0.26
+ * (c) 2016 Evan You
+ * Released under the MIT License.
+ */
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (global.Vue = factory());
+}(this, function () { 'use strict';
+
+ function set(obj, key, val) {
+ if (hasOwn(obj, key)) {
+ obj[key] = val;
+ return;
+ }
+ if (obj._isVue) {
+ set(obj._data, key, val);
+ return;
+ }
+ var ob = obj.__ob__;
+ if (!ob) {
+ obj[key] = val;
+ return;
+ }
+ ob.convert(key, val);
+ ob.dep.notify();
+ if (ob.vms) {
+ var i = ob.vms.length;
+ while (i--) {
+ var vm = ob.vms[i];
+ vm._proxy(key);
+ vm._digest();
+ }
+ }
+ return val;
+ }
+
+ /**
+ * Delete a property and trigger change if necessary.
+ *
+ * @param {Object} obj
+ * @param {String} key
+ */
+
+ function del(obj, key) {
+ if (!hasOwn(obj, key)) {
+ return;
+ }
+ delete obj[key];
+ var ob = obj.__ob__;
+ if (!ob) {
+ if (obj._isVue) {
+ delete obj._data[key];
+ obj._digest();
+ }
+ return;
+ }
+ ob.dep.notify();
+ if (ob.vms) {
+ var i = ob.vms.length;
+ while (i--) {
+ var vm = ob.vms[i];
+ vm._unproxy(key);
+ vm._digest();
+ }
+ }
+ }
+
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
+ /**
+ * Check whether the object has the property.
+ *
+ * @param {Object} obj
+ * @param {String} key
+ * @return {Boolean}
+ */
+
+ function hasOwn(obj, key) {
+ return hasOwnProperty.call(obj, key);
+ }
+
+ /**
+ * Check if an expression is a literal value.
+ *
+ * @param {String} exp
+ * @return {Boolean}
+ */
+
+ var literalValueRE = /^\s?(true|false|-?[\d\.]+|'[^']*'|"[^"]*")\s?$/;
+
+ function isLiteral(exp) {
+ return literalValueRE.test(exp);
+ }
+
+ /**
+ * Check if a string starts with $ or _
+ *
+ * @param {String} str
+ * @return {Boolean}
+ */
+
+ function isReserved(str) {
+ var c = (str + '').charCodeAt(0);
+ return c === 0x24 || c === 0x5F;
+ }
+
+ /**
+ * Guard text output, make sure undefined outputs
+ * empty string
+ *
+ * @param {*} value
+ * @return {String}
+ */
+
+ function _toString(value) {
+ return value == null ? '' : value.toString();
+ }
+
+ /**
+ * Check and convert possible numeric strings to numbers
+ * before setting back to data
+ *
+ * @param {*} value
+ * @return {*|Number}
+ */
+
+ function toNumber(value) {
+ if (typeof value !== 'string') {
+ return value;
+ } else {
+ var parsed = Number(value);
+ return isNaN(parsed) ? value : parsed;
+ }
+ }
+
+ /**
+ * Convert string boolean literals into real booleans.
+ *
+ * @param {*} value
+ * @return {*|Boolean}
+ */
+
+ function toBoolean(value) {
+ return value === 'true' ? true : value === 'false' ? false : value;
+ }
+
+ /**
+ * Strip quotes from a string
+ *
+ * @param {String} str
+ * @return {String | false}
+ */
+
+ function stripQuotes(str) {
+ var a = str.charCodeAt(0);
+ var b = str.charCodeAt(str.length - 1);
+ return a === b && (a === 0x22 || a === 0x27) ? str.slice(1, -1) : str;
+ }
+
+ /**
+ * Camelize a hyphen-delmited string.
+ *
+ * @param {String} str
+ * @return {String}
+ */
+
+ var camelizeRE = /-(\w)/g;
+
+ function camelize(str) {
+ return str.replace(camelizeRE, toUpper);
+ }
+
+ function toUpper(_, c) {
+ return c ? c.toUpperCase() : '';
+ }
+
+ /**
+ * Hyphenate a camelCase string.
+ *
+ * @param {String} str
+ * @return {String}
+ */
+
+ var hyphenateRE = /([a-z\d])([A-Z])/g;
+
+ function hyphenate(str) {
+ return str.replace(hyphenateRE, '$1-$2').toLowerCase();
+ }
+
+ /**
+ * Converts hyphen/underscore/slash delimitered names into
+ * camelized classNames.
+ *
+ * e.g. my-component => MyComponent
+ * some_else => SomeElse
+ * some/comp => SomeComp
+ *
+ * @param {String} str
+ * @return {String}
+ */
+
+ var classifyRE = /(?:^|[-_\/])(\w)/g;
+
+ function classify(str) {
+ return str.replace(classifyRE, toUpper);
+ }
+
+ /**
+ * Simple bind, faster than native
+ *
+ * @param {Function} fn
+ * @param {Object} ctx
+ * @return {Function}
+ */
+
+ function bind(fn, ctx) {
+ return function (a) {
+ var l = arguments.length;
+ return l ? l > 1 ? fn.apply(ctx, arguments) : fn.call(ctx, a) : fn.call(ctx);
+ };
+ }
+
+ /**
+ * Convert an Array-like object to a real Array.
+ *
+ * @param {Array-like} list
+ * @param {Number} [start] - start index
+ * @return {Array}
+ */
+
+ function toArray(list, start) {
+ start = start || 0;
+ var i = list.length - start;
+ var ret = new Array(i);
+ while (i--) {
+ ret[i] = list[i + start];
+ }
+ return ret;
+ }
+
+ /**
+ * Mix properties into target object.
+ *
+ * @param {Object} to
+ * @param {Object} from
+ */
+
+ function extend(to, from) {
+ var keys = Object.keys(from);
+ var i = keys.length;
+ while (i--) {
+ to[keys[i]] = from[keys[i]];
+ }
+ return to;
+ }
+
+ /**
+ * Quick object check - this is primarily used to tell
+ * Objects from primitive values when we know the value
+ * is a JSON-compliant type.
+ *
+ * @param {*} obj
+ * @return {Boolean}
+ */
+
+ function isObject(obj) {
+ return obj !== null && typeof obj === 'object';
+ }
+
+ /**
+ * Strict object type check. Only returns true
+ * for plain JavaScript objects.
+ *
+ * @param {*} obj
+ * @return {Boolean}
+ */
+
+ var toString = Object.prototype.toString;
+ var OBJECT_STRING = '[object Object]';
+
+ function isPlainObject(obj) {
+ return toString.call(obj) === OBJECT_STRING;
+ }
+
+ /**
+ * Array type check.
+ *
+ * @param {*} obj
+ * @return {Boolean}
+ */
+
+ var isArray = Array.isArray;
+
+ /**
+ * Define a property.
+ *
+ * @param {Object} obj
+ * @param {String} key
+ * @param {*} val
+ * @param {Boolean} [enumerable]
+ */
+
+ function def(obj, key, val, enumerable) {
+ Object.defineProperty(obj, key, {
+ value: val,
+ enumerable: !!enumerable,
+ writable: true,
+ configurable: true
+ });
+ }
+
+ /**
+ * Debounce a function so it only gets called after the
+ * input stops arriving after the given wait period.
+ *
+ * @param {Function} func
+ * @param {Number} wait
+ * @return {Function} - the debounced function
+ */
+
+ function _debounce(func, wait) {
+ var timeout, args, context, timestamp, result;
+ var later = function later() {
+ var last = Date.now() - timestamp;
+ if (last < wait && last >= 0) {
+ timeout = setTimeout(later, wait - last);
+ } else {
+ timeout = null;
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ }
+ };
+ return function () {
+ context = this;
+ args = arguments;
+ timestamp = Date.now();
+ if (!timeout) {
+ timeout = setTimeout(later, wait);
+ }
+ return result;
+ };
+ }
+
+ /**
+ * Manual indexOf because it's slightly faster than
+ * native.
+ *
+ * @param {Array} arr
+ * @param {*} obj
+ */
+
+ function indexOf(arr, obj) {
+ var i = arr.length;
+ while (i--) {
+ if (arr[i] === obj) return i;
+ }
+ return -1;
+ }
+
+ /**
+ * Make a cancellable version of an async callback.
+ *
+ * @param {Function} fn
+ * @return {Function}
+ */
+
+ function cancellable(fn) {
+ var cb = function cb() {
+ if (!cb.cancelled) {
+ return fn.apply(this, arguments);
+ }
+ };
+ cb.cancel = function () {
+ cb.cancelled = true;
+ };
+ return cb;
+ }
+
+ /**
+ * Check if two values are loosely equal - that is,
+ * if they are plain objects, do they have the same shape?
+ *
+ * @param {*} a
+ * @param {*} b
+ * @return {Boolean}
+ */
+
+ function looseEqual(a, b) {
+ /* eslint-disable eqeqeq */
+ return a == b || (isObject(a) && isObject(b) ? JSON.stringify(a) === JSON.stringify(b) : false);
+ /* eslint-enable eqeqeq */
+ }
+
+ var hasProto = ('__proto__' in {});
+
+ // Browser environment sniffing
+ var inBrowser = typeof window !== 'undefined' && Object.prototype.toString.call(window) !== '[object Object]';
+
+ // detect devtools
+ var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__;
+
+ // UA sniffing for working around browser-specific quirks
+ var UA = inBrowser && window.navigator.userAgent.toLowerCase();
+ var isIE = UA && UA.indexOf('trident') > 0;
+ var isIE9 = UA && UA.indexOf('msie 9.0') > 0;
+ var isAndroid = UA && UA.indexOf('android') > 0;
+ var isIos = UA && /(iphone|ipad|ipod|ios)/i.test(UA);
+ var iosVersionMatch = isIos && UA.match(/os ([\d_]+)/);
+ var iosVersion = iosVersionMatch && iosVersionMatch[1].split('_');
+
+ // detecting iOS UIWebView by indexedDB
+ var hasMutationObserverBug = iosVersion && Number(iosVersion[0]) >= 9 && Number(iosVersion[1]) >= 3 && !window.indexedDB;
+
+ var transitionProp = undefined;
+ var transitionEndEvent = undefined;
+ var animationProp = undefined;
+ var animationEndEvent = undefined;
+
+ // Transition property/event sniffing
+ if (inBrowser && !isIE9) {
+ var isWebkitTrans = window.ontransitionend === undefined && window.onwebkittransitionend !== undefined;
+ var isWebkitAnim = window.onanimationend === undefined && window.onwebkitanimationend !== undefined;
+ transitionProp = isWebkitTrans ? 'WebkitTransition' : 'transition';
+ transitionEndEvent = isWebkitTrans ? 'webkitTransitionEnd' : 'transitionend';
+ animationProp = isWebkitAnim ? 'WebkitAnimation' : 'animation';
+ animationEndEvent = isWebkitAnim ? 'webkitAnimationEnd' : 'animationend';
+ }
+
+ /**
+ * Defer a task to execute it asynchronously. Ideally this
+ * should be executed as a microtask, so we leverage
+ * MutationObserver if it's available, and fallback to
+ * setTimeout(0).
+ *
+ * @param {Function} cb
+ * @param {Object} ctx
+ */
+
+ var nextTick = (function () {
+ var callbacks = [];
+ var pending = false;
+ var timerFunc;
+ function nextTickHandler() {
+ pending = false;
+ var copies = callbacks.slice(0);
+ callbacks = [];
+ for (var i = 0; i < copies.length; i++) {
+ copies[i]();
+ }
+ }
+
+ /* istanbul ignore if */
+ if (typeof MutationObserver !== 'undefined' && !hasMutationObserverBug) {
+ var counter = 1;
+ var observer = new MutationObserver(nextTickHandler);
+ var textNode = document.createTextNode(counter);
+ observer.observe(textNode, {
+ characterData: true
+ });
+ timerFunc = function () {
+ counter = (counter + 1) % 2;
+ textNode.data = counter;
+ };
+ } else {
+ // webpack attempts to inject a shim for setImmediate
+ // if it is used as a global, so we have to work around that to
+ // avoid bundling unnecessary code.
+ var context = inBrowser ? window : typeof global !== 'undefined' ? global : {};
+ timerFunc = context.setImmediate || setTimeout;
+ }
+ return function (cb, ctx) {
+ var func = ctx ? function () {
+ cb.call(ctx);
+ } : cb;
+ callbacks.push(func);
+ if (pending) return;
+ pending = true;
+ timerFunc(nextTickHandler, 0);
+ };
+ })();
+
+ var _Set = undefined;
+ /* istanbul ignore if */
+ if (typeof Set !== 'undefined' && Set.toString().match(/native code/)) {
+ // use native Set when available.
+ _Set = Set;
+ } else {
+ // a non-standard Set polyfill that only works with primitive keys.
+ _Set = function () {
+ this.set = Object.create(null);
+ };
+ _Set.prototype.has = function (key) {
+ return this.set[key] !== undefined;
+ };
+ _Set.prototype.add = function (key) {
+ this.set[key] = 1;
+ };
+ _Set.prototype.clear = function () {
+ this.set = Object.create(null);
+ };
+ }
+
+ function Cache(limit) {
+ this.size = 0;
+ this.limit = limit;
+ this.head = this.tail = undefined;
+ this._keymap = Object.create(null);
+ }
+
+ var p = Cache.prototype;
+
+ /**
+ * Put <value> into the cache associated with <key>.
+ * Returns the entry which was removed to make room for
+ * the new entry. Otherwise undefined is returned.
+ * (i.e. if there was enough room already).
+ *
+ * @param {String} key
+ * @param {*} value
+ * @return {Entry|undefined}
+ */
+
+ p.put = function (key, value) {
+ var removed;
+
+ var entry = this.get(key, true);
+ if (!entry) {
+ if (this.size === this.limit) {
+ removed = this.shift();
+ }
+ entry = {
+ key: key
+ };
+ this._keymap[key] = entry;
+ if (this.tail) {
+ this.tail.newer = entry;
+ entry.older = this.tail;
+ } else {
+ this.head = entry;
+ }
+ this.tail = entry;
+ this.size++;
+ }
+ entry.value = value;
+
+ return removed;
+ };
+
+ /**
+ * Purge the least recently used (oldest) entry from the
+ * cache. Returns the removed entry or undefined if the
+ * cache was empty.
+ */
+
+ p.shift = function () {
+ var entry = this.head;
+ if (entry) {
+ this.head = this.head.newer;
+ this.head.older = undefined;
+ entry.newer = entry.older = undefined;
+ this._keymap[entry.key] = undefined;
+ this.size--;
+ }
+ return entry;
+ };
+
+ /**
+ * Get and register recent use of <key>. Returns the value
+ * associated with <key> or undefined if not in cache.
+ *
+ * @param {String} key
+ * @param {Boolean} returnEntry
+ * @return {Entry|*}
+ */
+
+ p.get = function (key, returnEntry) {
+ var entry = this._keymap[key];
+ if (entry === undefined) return;
+ if (entry === this.tail) {
+ return returnEntry ? entry : entry.value;
+ }
+ // HEAD--------------TAIL
+ // <.older .newer>
+ // <--- add direction --
+ // A B C <D> E
+ if (entry.newer) {
+ if (entry === this.head) {
+ this.head = entry.newer;
+ }
+ entry.newer.older = entry.older; // C <-- E.
+ }
+ if (entry.older) {
+ entry.older.newer = entry.newer; // C. --> E
+ }
+ entry.newer = undefined; // D --x
+ entry.older = this.tail; // D. --> E
+ if (this.tail) {
+ this.tail.newer = entry; // E. <-- D
+ }
+ this.tail = entry;
+ return returnEntry ? entry : entry.value;
+ };
+
+ var cache$1 = new Cache(1000);
+ var filterTokenRE = /[^\s'"]+|'[^']*'|"[^"]*"/g;
+ var reservedArgRE = /^in$|^-?\d+/;
+
+ /**
+ * Parser state
+ */
+
+ var str;
+ var dir;
+ var c;
+ var prev;
+ var i;
+ var l;
+ var lastFilterIndex;
+ var inSingle;
+ var inDouble;
+ var curly;
+ var square;
+ var paren;
+ /**
+ * Push a filter to the current directive object
+ */
+
+ function pushFilter() {
+ var exp = str.slice(lastFilterIndex, i).trim();
+ var filter;
+ if (exp) {
+ filter = {};
+ var tokens = exp.match(filterTokenRE);
+ filter.name = tokens[0];
+ if (tokens.length > 1) {
+ filter.args = tokens.slice(1).map(processFilterArg);
+ }
+ }
+ if (filter) {
+ (dir.filters = dir.filters || []).push(filter);
+ }
+ lastFilterIndex = i + 1;
+ }
+
+ /**
+ * Check if an argument is dynamic and strip quotes.
+ *
+ * @param {String} arg
+ * @return {Object}
+ */
+
+ function processFilterArg(arg) {
+ if (reservedArgRE.test(arg)) {
+ return {
+ value: toNumber(arg),
+ dynamic: false
+ };
+ } else {
+ var stripped = stripQuotes(arg);
+ var dynamic = stripped === arg;
+ return {
+ value: dynamic ? arg : stripped,
+ dynamic: dynamic
+ };
+ }
+ }
+
+ /**
+ * Parse a directive value and extract the expression
+ * and its filters into a descriptor.
+ *
+ * Example:
+ *
+ * "a + 1 | uppercase" will yield:
+ * {
+ * expression: 'a + 1',
+ * filters: [
+ * { name: 'uppercase', args: null }
+ * ]
+ * }
+ *
+ * @param {String} s
+ * @return {Object}
+ */
+
+ function parseDirective(s) {
+ var hit = cache$1.get(s);
+ if (hit) {
+ return hit;
+ }
+
+ // reset parser state
+ str = s;
+ inSingle = inDouble = false;
+ curly = square = paren = 0;
+ lastFilterIndex = 0;
+ dir = {};
+
+ for (i = 0, l = str.length; i < l; i++) {
+ prev = c;
+ c = str.charCodeAt(i);
+ if (inSingle) {
+ // check single quote
+ if (c === 0x27 && prev !== 0x5C) inSingle = !inSingle;
+ } else if (inDouble) {
+ // check double quote
+ if (c === 0x22 && prev !== 0x5C) inDouble = !inDouble;
+ } else if (c === 0x7C && // pipe
+ str.charCodeAt(i + 1) !== 0x7C && str.charCodeAt(i - 1) !== 0x7C) {
+ if (dir.expression == null) {
+ // first filter, end of expression
+ lastFilterIndex = i + 1;
+ dir.expression = str.slice(0, i).trim();
+ } else {
+ // already has filter
+ pushFilter();
+ }
+ } else {
+ switch (c) {
+ case 0x22:
+ inDouble = true;break; // "
+ case 0x27:
+ inSingle = true;break; // '
+ case 0x28:
+ paren++;break; // (
+ case 0x29:
+ paren--;break; // )
+ case 0x5B:
+ square++;break; // [
+ case 0x5D:
+ square--;break; // ]
+ case 0x7B:
+ curly++;break; // {
+ case 0x7D:
+ curly--;break; // }
+ }
+ }
+ }
+
+ if (dir.expression == null) {
+ dir.expression = str.slice(0, i).trim();
+ } else if (lastFilterIndex !== 0) {
+ pushFilter();
+ }
+
+ cache$1.put(s, dir);
+ return dir;
+ }
+
+var directive = Object.freeze({
+ parseDirective: parseDirective
+ });
+
+ var regexEscapeRE = /[-.*+?^${}()|[\]\/\\]/g;
+ var cache = undefined;
+ var tagRE = undefined;
+ var htmlRE = undefined;
+ /**
+ * Escape a string so it can be used in a RegExp
+ * constructor.
+ *
+ * @param {String} str
+ */
+
+ function escapeRegex(str) {
+ return str.replace(regexEscapeRE, '\\$&');
+ }
+
+ function compileRegex() {
+ var open = escapeRegex(config.delimiters[0]);
+ var close = escapeRegex(config.delimiters[1]);
+ var unsafeOpen = escapeRegex(config.unsafeDelimiters[0]);
+ var unsafeClose = escapeRegex(config.unsafeDelimiters[1]);
+ tagRE = new RegExp(unsafeOpen + '((?:.|\\n)+?)' + unsafeClose + '|' + open + '((?:.|\\n)+?)' + close, 'g');
+ htmlRE = new RegExp('^' + unsafeOpen + '((?:.|\\n)+?)' + unsafeClose + '$');
+ // reset cache
+ cache = new Cache(1000);
+ }
+
+ /**
+ * Parse a template text string into an array of tokens.
+ *
+ * @param {String} text
+ * @return {Array<Object> | null}
+ * - {String} type
+ * - {String} value
+ * - {Boolean} [html]
+ * - {Boolean} [oneTime]
+ */
+
+ function parseText(text) {
+ if (!cache) {
+ compileRegex();
+ }
+ var hit = cache.get(text);
+ if (hit) {
+ return hit;
+ }
+ if (!tagRE.test(text)) {
+ return null;
+ }
+ var tokens = [];
+ var lastIndex = tagRE.lastIndex = 0;
+ var match, index, html, value, first, oneTime;
+ /* eslint-disable no-cond-assign */
+ while (match = tagRE.exec(text)) {
+ /* eslint-enable no-cond-assign */
+ index = match.index;
+ // push text token
+ if (index > lastIndex) {
+ tokens.push({
+ value: text.slice(lastIndex, index)
+ });
+ }
+ // tag token
+ html = htmlRE.test(match[0]);
+ value = html ? match[1] : match[2];
+ first = value.charCodeAt(0);
+ oneTime = first === 42; // *
+ value = oneTime ? value.slice(1) : value;
+ tokens.push({
+ tag: true,
+ value: value.trim(),
+ html: html,
+ oneTime: oneTime
+ });
+ lastIndex = index + match[0].length;
+ }
+ if (lastIndex < text.length) {
+ tokens.push({
+ value: text.slice(lastIndex)
+ });
+ }
+ cache.put(text, tokens);
+ return tokens;
+ }
+
+ /**
+ * Format a list of tokens into an expression.
+ * e.g. tokens parsed from 'a {{b}} c' can be serialized
+ * into one single expression as '"a " + b + " c"'.
+ *
+ * @param {Array} tokens
+ * @param {Vue} [vm]
+ * @return {String}
+ */
+
+ function tokensToExp(tokens, vm) {
+ if (tokens.length > 1) {
+ return tokens.map(function (token) {
+ return formatToken(token, vm);
+ }).join('+');
+ } else {
+ return formatToken(tokens[0], vm, true);
+ }
+ }
+
+ /**
+ * Format a single token.
+ *
+ * @param {Object} token
+ * @param {Vue} [vm]
+ * @param {Boolean} [single]
+ * @return {String}
+ */
+
+ function formatToken(token, vm, single) {
+ return token.tag ? token.oneTime && vm ? '"' + vm.$eval(token.value) + '"' : inlineFilters(token.value, single) : '"' + token.value + '"';
+ }
+
+ /**
+ * For an attribute with multiple interpolation tags,
+ * e.g. attr="some-{{thing | filter}}", in order to combine
+ * the whole thing into a single watchable expression, we
+ * have to inline those filters. This function does exactly
+ * that. This is a bit hacky but it avoids heavy changes
+ * to directive parser and watcher mechanism.
+ *
+ * @param {String} exp
+ * @param {Boolean} single
+ * @return {String}
+ */
+
+ var filterRE = /[^|]\|[^|]/;
+ function inlineFilters(exp, single) {
+ if (!filterRE.test(exp)) {
+ return single ? exp : '(' + exp + ')';
+ } else {
+ var dir = parseDirective(exp);
+ if (!dir.filters) {
+ return '(' + exp + ')';
+ } else {
+ return 'this._applyFilters(' + dir.expression + // value
+ ',null,' + // oldValue (null for read)
+ JSON.stringify(dir.filters) + // filter descriptors
+ ',false)'; // write?
+ }
+ }
+ }
+
+var text = Object.freeze({
+ compileRegex: compileRegex,
+ parseText: parseText,
+ tokensToExp: tokensToExp
+ });
+
+ var delimiters = ['{{', '}}'];
+ var unsafeDelimiters = ['{{{', '}}}'];
+
+ var config = Object.defineProperties({
+
+ /**
+ * Whether to print debug messages.
+ * Also enables stack trace for warnings.
+ *
+ * @type {Boolean}
+ */
+
+ debug: false,
+
+ /**
+ * Whether to suppress warnings.
+ *
+ * @type {Boolean}
+ */
+
+ silent: false,
+
+ /**
+ * Whether to use async rendering.
+ */
+
+ async: true,
+
+ /**
+ * Whether to warn against errors caught when evaluating
+ * expressions.
+ */
+
+ warnExpressionErrors: true,
+
+ /**
+ * Whether to allow devtools inspection.
+ * Disabled by default in production builds.
+ */
+
+ devtools: 'development' !== 'production',
+
+ /**
+ * Internal flag to indicate the delimiters have been
+ * changed.
+ *
+ * @type {Boolean}
+ */
+
+ _delimitersChanged: true,
+
+ /**
+ * List of asset types that a component can own.
+ *
+ * @type {Array}
+ */
+
+ _assetTypes: ['component', 'directive', 'elementDirective', 'filter', 'transition', 'partial'],
+
+ /**
+ * prop binding modes
+ */
+
+ _propBindingModes: {
+ ONE_WAY: 0,
+ TWO_WAY: 1,
+ ONE_TIME: 2
+ },
+
+ /**
+ * Max circular updates allowed in a batcher flush cycle.
+ */
+
+ _maxUpdateCount: 100
+
+ }, {
+ delimiters: { /**
+ * Interpolation delimiters. Changing these would trigger
+ * the text parser to re-compile the regular expressions.
+ *
+ * @type {Array<String>}
+ */
+
+ get: function get() {
+ return delimiters;
+ },
+ set: function set(val) {
+ delimiters = val;
+ compileRegex();
+ },
+ configurable: true,
+ enumerable: true
+ },
+ unsafeDelimiters: {
+ get: function get() {
+ return unsafeDelimiters;
+ },
+ set: function set(val) {
+ unsafeDelimiters = val;
+ compileRegex();
+ },
+ configurable: true,
+ enumerable: true
+ }
+ });
+
+ var warn = undefined;
+ var formatComponentName = undefined;
+
+ if ('development' !== 'production') {
+ (function () {
+ var hasConsole = typeof console !== 'undefined';
+
+ warn = function (msg, vm) {
+ if (hasConsole && !config.silent) {
+ console.error('[Vue warn]: ' + msg + (vm ? formatComponentName(vm) : ''));
+ }
+ };
+
+ formatComponentName = function (vm) {
+ var name = vm._isVue ? vm.$options.name : vm.name;
+ return name ? ' (found in component: <' + hyphenate(name) + '>)' : '';
+ };
+ })();
+ }
+
+ /**
+ * Append with transition.
+ *
+ * @param {Element} el
+ * @param {Element} target
+ * @param {Vue} vm
+ * @param {Function} [cb]
+ */
+
+ function appendWithTransition(el, target, vm, cb) {
+ applyTransition(el, 1, function () {
+ target.appendChild(el);
+ }, vm, cb);
+ }
+
+ /**
+ * InsertBefore with transition.
+ *
+ * @param {Element} el
+ * @param {Element} target
+ * @param {Vue} vm
+ * @param {Function} [cb]
+ */
+
+ function beforeWithTransition(el, target, vm, cb) {
+ applyTransition(el, 1, function () {
+ before(el, target);
+ }, vm, cb);
+ }
+
+ /**
+ * Remove with transition.
+ *
+ * @param {Element} el
+ * @param {Vue} vm
+ * @param {Function} [cb]
+ */
+
+ function removeWithTransition(el, vm, cb) {
+ applyTransition(el, -1, function () {
+ remove(el);
+ }, vm, cb);
+ }
+
+ /**
+ * Apply transitions with an operation callback.
+ *
+ * @param {Element} el
+ * @param {Number} direction
+ * 1: enter
+ * -1: leave
+ * @param {Function} op - the actual DOM operation
+ * @param {Vue} vm
+ * @param {Function} [cb]
+ */
+
+ function applyTransition(el, direction, op, vm, cb) {
+ var transition = el.__v_trans;
+ if (!transition ||
+ // skip if there are no js hooks and CSS transition is
+ // not supported
+ !transition.hooks && !transitionEndEvent ||
+ // skip transitions for initial compile
+ !vm._isCompiled ||
+ // if the vm is being manipulated by a parent directive
+ // during the parent's compilation phase, skip the
+ // animation.
+ vm.$parent && !vm.$parent._isCompiled) {
+ op();
+ if (cb) cb();
+ return;
+ }
+ var action = direction > 0 ? 'enter' : 'leave';
+ transition[action](op, cb);
+ }
+
+var transition = Object.freeze({
+ appendWithTransition: appendWithTransition,
+ beforeWithTransition: beforeWithTransition,
+ removeWithTransition: removeWithTransition,
+ applyTransition: applyTransition
+ });
+
+ /**
+ * Query an element selector if it's not an element already.
+ *
+ * @param {String|Element} el
+ * @return {Element}
+ */
+
+ function query(el) {
+ if (typeof el === 'string') {
+ var selector = el;
+ el = document.querySelector(el);
+ if (!el) {
+ 'development' !== 'production' && warn('Cannot find element: ' + selector);
+ }
+ }
+ return el;
+ }
+
+ /**
+ * Check if a node is in the document.
+ * Note: document.documentElement.contains should work here
+ * but always returns false for comment nodes in phantomjs,
+ * making unit tests difficult. This is fixed by doing the
+ * contains() check on the node's parentNode instead of
+ * the node itself.
+ *
+ * @param {Node} node
+ * @return {Boolean}
+ */
+
+ function inDoc(node) {
+ if (!node) return false;
+ var doc = node.ownerDocument.documentElement;
+ var parent = node.parentNode;
+ return doc === node || doc === parent || !!(parent && parent.nodeType === 1 && doc.contains(parent));
+ }
+
+ /**
+ * Get and remove an attribute from a node.
+ *
+ * @param {Node} node
+ * @param {String} _attr
+ */
+
+ function getAttr(node, _attr) {
+ var val = node.getAttribute(_attr);
+ if (val !== null) {
+ node.removeAttribute(_attr);
+ }
+ return val;
+ }
+
+ /**
+ * Get an attribute with colon or v-bind: prefix.
+ *
+ * @param {Node} node
+ * @param {String} name
+ * @return {String|null}
+ */
+
+ function getBindAttr(node, name) {
+ var val = getAttr(node, ':' + name);
+ if (val === null) {
+ val = getAttr(node, 'v-bind:' + name);
+ }
+ return val;
+ }
+
+ /**
+ * Check the presence of a bind attribute.
+ *
+ * @param {Node} node
+ * @param {String} name
+ * @return {Boolean}
+ */
+
+ function hasBindAttr(node, name) {
+ return node.hasAttribute(name) || node.hasAttribute(':' + name) || node.hasAttribute('v-bind:' + name);
+ }
+
+ /**
+ * Insert el before target
+ *
+ * @param {Element} el
+ * @param {Element} target
+ */
+
+ function before(el, target) {
+ target.parentNode.insertBefore(el, target);
+ }
+
+ /**
+ * Insert el after target
+ *
+ * @param {Element} el
+ * @param {Element} target
+ */
+
+ function after(el, target) {
+ if (target.nextSibling) {
+ before(el, target.nextSibling);
+ } else {
+ target.parentNode.appendChild(el);
+ }
+ }
+
+ /**
+ * Remove el from DOM
+ *
+ * @param {Element} el
+ */
+
+ function remove(el) {
+ el.parentNode.removeChild(el);
+ }
+
+ /**
+ * Prepend el to target
+ *
+ * @param {Element} el
+ * @param {Element} target
+ */
+
+ function prepend(el, target) {
+ if (target.firstChild) {
+ before(el, target.firstChild);
+ } else {
+ target.appendChild(el);
+ }
+ }
+
+ /**
+ * Replace target with el
+ *
+ * @param {Element} target
+ * @param {Element} el
+ */
+
+ function replace(target, el) {
+ var parent = target.parentNode;
+ if (parent) {
+ parent.replaceChild(el, target);
+ }
+ }
+
+ /**
+ * Add event listener shorthand.
+ *
+ * @param {Element} el
+ * @param {String} event
+ * @param {Function} cb
+ * @param {Boolean} [useCapture]
+ */
+
+ function on(el, event, cb, useCapture) {
+ el.addEventListener(event, cb, useCapture);
+ }
+
+ /**
+ * Remove event listener shorthand.
+ *
+ * @param {Element} el
+ * @param {String} event
+ * @param {Function} cb
+ */
+
+ function off(el, event, cb) {
+ el.removeEventListener(event, cb);
+ }
+
+ /**
+ * For IE9 compat: when both class and :class are present
+ * getAttribute('class') returns wrong value...
+ *
+ * @param {Element} el
+ * @return {String}
+ */
+
+ function getClass(el) {
+ var classname = el.className;
+ if (typeof classname === 'object') {
+ classname = classname.baseVal || '';
+ }
+ return classname;
+ }
+
+ /**
+ * In IE9, setAttribute('class') will result in empty class
+ * if the element also has the :class attribute; However in
+ * PhantomJS, setting `className` does not work on SVG elements...
+ * So we have to do a conditional check here.
+ *
+ * @param {Element} el
+ * @param {String} cls
+ */
+
+ function setClass(el, cls) {
+ /* istanbul ignore if */
+ if (isIE9 && !/svg$/.test(el.namespaceURI)) {
+ el.className = cls;
+ } else {
+ el.setAttribute('class', cls);
+ }
+ }
+
+ /**
+ * Add class with compatibility for IE & SVG
+ *
+ * @param {Element} el
+ * @param {String} cls
+ */
+
+ function addClass(el, cls) {
+ if (el.classList) {
+ el.classList.add(cls);
+ } else {
+ var cur = ' ' + getClass(el) + ' ';
+ if (cur.indexOf(' ' + cls + ' ') < 0) {
+ setClass(el, (cur + cls).trim());
+ }
+ }
+ }
+
+ /**
+ * Remove class with compatibility for IE & SVG
+ *
+ * @param {Element} el
+ * @param {String} cls
+ */
+
+ function removeClass(el, cls) {
+ if (el.classList) {
+ el.classList.remove(cls);
+ } else {
+ var cur = ' ' + getClass(el) + ' ';
+ var tar = ' ' + cls + ' ';
+ while (cur.indexOf(tar) >= 0) {
+ cur = cur.replace(tar, ' ');
+ }
+ setClass(el, cur.trim());
+ }
+ if (!el.className) {
+ el.removeAttribute('class');
+ }
+ }
+
+ /**
+ * Extract raw content inside an element into a temporary
+ * container div
+ *
+ * @param {Element} el
+ * @param {Boolean} asFragment
+ * @return {Element|DocumentFragment}
+ */
+
+ function extractContent(el, asFragment) {
+ var child;
+ var rawContent;
+ /* istanbul ignore if */
+ if (isTemplate(el) && isFragment(el.content)) {
+ el = el.content;
+ }
+ if (el.hasChildNodes()) {
+ trimNode(el);
+ rawContent = asFragment ? document.createDocumentFragment() : document.createElement('div');
+ /* eslint-disable no-cond-assign */
+ while (child = el.firstChild) {
+ /* eslint-enable no-cond-assign */
+ rawContent.appendChild(child);
+ }
+ }
+ return rawContent;
+ }
+
+ /**
+ * Trim possible empty head/tail text and comment
+ * nodes inside a parent.
+ *
+ * @param {Node} node
+ */
+
+ function trimNode(node) {
+ var child;
+ /* eslint-disable no-sequences */
+ while ((child = node.firstChild, isTrimmable(child))) {
+ node.removeChild(child);
+ }
+ while ((child = node.lastChild, isTrimmable(child))) {
+ node.removeChild(child);
+ }
+ /* eslint-enable no-sequences */
+ }
+
+ function isTrimmable(node) {
+ return node && (node.nodeType === 3 && !node.data.trim() || node.nodeType === 8);
+ }
+
+ /**
+ * Check if an element is a template tag.
+ * Note if the template appears inside an SVG its tagName
+ * will be in lowercase.
+ *
+ * @param {Element} el
+ */
+
+ function isTemplate(el) {
+ return el.tagName && el.tagName.toLowerCase() === 'template';
+ }
+
+ /**
+ * Create an "anchor" for performing dom insertion/removals.
+ * This is used in a number of scenarios:
+ * - fragment instance
+ * - v-html
+ * - v-if
+ * - v-for
+ * - component
+ *
+ * @param {String} content
+ * @param {Boolean} persist - IE trashes empty textNodes on
+ * cloneNode(true), so in certain
+ * cases the anchor needs to be
+ * non-empty to be persisted in
+ * templates.
+ * @return {Comment|Text}
+ */
+
+ function createAnchor(content, persist) {
+ var anchor = config.debug ? document.createComment(content) : document.createTextNode(persist ? ' ' : '');
+ anchor.__v_anchor = true;
+ return anchor;
+ }
+
+ /**
+ * Find a component ref attribute that starts with $.
+ *
+ * @param {Element} node
+ * @return {String|undefined}
+ */
+
+ var refRE = /^v-ref:/;
+
+ function findRef(node) {
+ if (node.hasAttributes()) {
+ var attrs = node.attributes;
+ for (var i = 0, l = attrs.length; i < l; i++) {
+ var name = attrs[i].name;
+ if (refRE.test(name)) {
+ return camelize(name.replace(refRE, ''));
+ }
+ }
+ }
+ }
+
+ /**
+ * Map a function to a range of nodes .
+ *
+ * @param {Node} node
+ * @param {Node} end
+ * @param {Function} op
+ */
+
+ function mapNodeRange(node, end, op) {
+ var next;
+ while (node !== end) {
+ next = node.nextSibling;
+ op(node);
+ node = next;
+ }
+ op(end);
+ }
+
+ /**
+ * Remove a range of nodes with transition, store
+ * the nodes in a fragment with correct ordering,
+ * and call callback when done.
+ *
+ * @param {Node} start
+ * @param {Node} end
+ * @param {Vue} vm
+ * @param {DocumentFragment} frag
+ * @param {Function} cb
+ */
+
+ function removeNodeRange(start, end, vm, frag, cb) {
+ var done = false;
+ var removed = 0;
+ var nodes = [];
+ mapNodeRange(start, end, function (node) {
+ if (node === end) done = true;
+ nodes.push(node);
+ removeWithTransition(node, vm, onRemoved);
+ });
+ function onRemoved() {
+ removed++;
+ if (done && removed >= nodes.length) {
+ for (var i = 0; i < nodes.length; i++) {
+ frag.appendChild(nodes[i]);
+ }
+ cb && cb();
+ }
+ }
+ }
+
+ /**
+ * Check if a node is a DocumentFragment.
+ *
+ * @param {Node} node
+ * @return {Boolean}
+ */
+
+ function isFragment(node) {
+ return node && node.nodeType === 11;
+ }
+
+ /**
+ * Get outerHTML of elements, taking care
+ * of SVG elements in IE as well.
+ *
+ * @param {Element} el
+ * @return {String}
+ */
+
+ function getOuterHTML(el) {
+ if (el.outerHTML) {
+ return el.outerHTML;
+ } else {
+ var container = document.createElement('div');
+ container.appendChild(el.cloneNode(true));
+ return container.innerHTML;
+ }
+ }
+
+ var commonTagRE = /^(div|p|span|img|a|b|i|br|ul|ol|li|h1|h2|h3|h4|h5|h6|code|pre|table|th|td|tr|form|label|input|select|option|nav|article|section|header|footer)$/i;
+ var reservedTagRE = /^(slot|partial|component)$/i;
+
+ var isUnknownElement = undefined;
+ if ('development' !== 'production') {
+ isUnknownElement = function (el, tag) {
+ if (tag.indexOf('-') > -1) {
+ // http://stackoverflow.com/a/28210364/1070244
+ return el.constructor === window.HTMLUnknownElement || el.constructor === window.HTMLElement;
+ } else {
+ return (/HTMLUnknownElement/.test(el.toString()) &&
+ // Chrome returns unknown for several HTML5 elements.
+ // https://code.google.com/p/chromium/issues/detail?id=540526
+ // Firefox returns unknown for some "Interactive elements."
+ !/^(data|time|rtc|rb|details|dialog|summary)$/.test(tag)
+ );
+ }
+ };
+ }
+
+ /**
+ * Check if an element is a component, if yes return its
+ * component id.
+ *
+ * @param {Element} el
+ * @param {Object} options
+ * @return {Object|undefined}
+ */
+
+ function checkComponentAttr(el, options) {
+ var tag = el.tagName.toLowerCase();
+ var hasAttrs = el.hasAttributes();
+ if (!commonTagRE.test(tag) && !reservedTagRE.test(tag)) {
+ if (resolveAsset(options, 'components', tag)) {
+ return { id: tag };
+ } else {
+ var is = hasAttrs && getIsBinding(el, options);
+ if (is) {
+ return is;
+ } else if ('development' !== 'production') {
+ var expectedTag = options._componentNameMap && options._componentNameMap[tag];
+ if (expectedTag) {
+ warn('Unknown custom element: <' + tag + '> - ' + 'did you mean <' + expectedTag + '>? ' + 'HTML is case-insensitive, remember to use kebab-case in templates.');
+ } else if (isUnknownElement(el, tag)) {
+ warn('Unknown custom element: <' + tag + '> - did you ' + 'register the component correctly? For recursive components, ' + 'make sure to provide the "name" option.');
+ }
+ }
+ }
+ } else if (hasAttrs) {
+ return getIsBinding(el, options);
+ }
+ }
+
+ /**
+ * Get "is" binding from an element.
+ *
+ * @param {Element} el
+ * @param {Object} options
+ * @return {Object|undefined}
+ */
+
+ function getIsBinding(el, options) {
+ // dynamic syntax
+ var exp = el.getAttribute('is');
+ if (exp != null) {
+ if (resolveAsset(options, 'components', exp)) {
+ el.removeAttribute('is');
+ return { id: exp };
+ }
+ } else {
+ exp = getBindAttr(el, 'is');
+ if (exp != null) {
+ return { id: exp, dynamic: true };
+ }
+ }
+ }
+
+ /**
+ * Option overwriting strategies are functions that handle
+ * how to merge a parent option value and a child option
+ * value into the final value.
+ *
+ * All strategy functions follow the same signature:
+ *
+ * @param {*} parentVal
+ * @param {*} childVal
+ * @param {Vue} [vm]
+ */
+
+ var strats = config.optionMergeStrategies = Object.create(null);
+
+ /**
+ * Helper that recursively merges two data objects together.
+ */
+
+ function mergeData(to, from) {
+ var key, toVal, fromVal;
+ for (key in from) {
+ toVal = to[key];
+ fromVal = from[key];
+ if (!hasOwn(to, key)) {
+ set(to, key, fromVal);
+ } else if (isObject(toVal) && isObject(fromVal)) {
+ mergeData(toVal, fromVal);
+ }
+ }
+ return to;
+ }
+
+ /**
+ * Data
+ */
+
+ strats.data = function (parentVal, childVal, vm) {
+ if (!vm) {
+ // in a Vue.extend merge, both should be functions
+ if (!childVal) {
+ return parentVal;
+ }
+ if (typeof childVal !== 'function') {
+ 'development' !== 'production' && warn('The "data" option should be a function ' + 'that returns a per-instance value in component ' + 'definitions.', vm);
+ return parentVal;
+ }
+ if (!parentVal) {
+ return childVal;
+ }
+ // when parentVal & childVal are both present,
+ // we need to return a function that returns the
+ // merged result of both functions... no need to
+ // check if parentVal is a function here because
+ // it has to be a function to pass previous merges.
+ return function mergedDataFn() {
+ return mergeData(childVal.call(this), parentVal.call(this));
+ };
+ } else if (parentVal || childVal) {
+ return function mergedInstanceDataFn() {
+ // instance merge
+ var instanceData = typeof childVal === 'function' ? childVal.call(vm) : childVal;
+ var defaultData = typeof parentVal === 'function' ? parentVal.call(vm) : undefined;
+ if (instanceData) {
+ return mergeData(instanceData, defaultData);
+ } else {
+ return defaultData;
+ }
+ };
+ }
+ };
+
+ /**
+ * El
+ */
+
+ strats.el = function (parentVal, childVal, vm) {
+ if (!vm && childVal && typeof childVal !== 'function') {
+ 'development' !== 'production' && warn('The "el" option should be a function ' + 'that returns a per-instance value in component ' + 'definitions.', vm);
+ return;
+ }
+ var ret = childVal || parentVal;
+ // invoke the element factory if this is instance merge
+ return vm && typeof ret === 'function' ? ret.call(vm) : ret;
+ };
+
+ /**
+ * Hooks and param attributes are merged as arrays.
+ */
+
+ strats.init = strats.created = strats.ready = strats.attached = strats.detached = strats.beforeCompile = strats.compiled = strats.beforeDestroy = strats.destroyed = strats.activate = function (parentVal, childVal) {
+ return childVal ? parentVal ? parentVal.concat(childVal) : isArray(childVal) ? childVal : [childVal] : parentVal;
+ };
+
+ /**
+ * Assets
+ *
+ * When a vm is present (instance creation), we need to do
+ * a three-way merge between constructor options, instance
+ * options and parent options.
+ */
+
+ function mergeAssets(parentVal, childVal) {
+ var res = Object.create(parentVal || null);
+ return childVal ? extend(res, guardArrayAssets(childVal)) : res;
+ }
+
+ config._assetTypes.forEach(function (type) {
+ strats[type + 's'] = mergeAssets;
+ });
+
+ /**
+ * Events & Watchers.
+ *
+ * Events & watchers hashes should not overwrite one
+ * another, so we merge them as arrays.
+ */
+
+ strats.watch = strats.events = function (parentVal, childVal) {
+ if (!childVal) return parentVal;
+ if (!parentVal) return childVal;
+ var ret = {};
+ extend(ret, parentVal);
+ for (var key in childVal) {
+ var parent = ret[key];
+ var child = childVal[key];
+ if (parent && !isArray(parent)) {
+ parent = [parent];
+ }
+ ret[key] = parent ? parent.concat(child) : [child];
+ }
+ return ret;
+ };
+
+ /**
+ * Other object hashes.
+ */
+
+ strats.props = strats.methods = strats.computed = function (parentVal, childVal) {
+ if (!childVal) return parentVal;
+ if (!parentVal) return childVal;
+ var ret = Object.create(null);
+ extend(ret, parentVal);
+ extend(ret, childVal);
+ return ret;
+ };
+
+ /**
+ * Default strategy.
+ */
+
+ var defaultStrat = function defaultStrat(parentVal, childVal) {
+ return childVal === undefined ? parentVal : childVal;
+ };
+
+ /**
+ * Make sure component options get converted to actual
+ * constructors.
+ *
+ * @param {Object} options
+ */
+
+ function guardComponents(options) {
+ if (options.components) {
+ var components = options.components = guardArrayAssets(options.components);
+ var ids = Object.keys(components);
+ var def;
+ if ('development' !== 'production') {
+ var map = options._componentNameMap = {};
+ }
+ for (var i = 0, l = ids.length; i < l; i++) {
+ var key = ids[i];
+ if (commonTagRE.test(key) || reservedTagRE.test(key)) {
+ 'development' !== 'production' && warn('Do not use built-in or reserved HTML elements as component ' + 'id: ' + key);
+ continue;
+ }
+ // record a all lowercase <-> kebab-case mapping for
+ // possible custom element case error warning
+ if ('development' !== 'production') {
+ map[key.replace(/-/g, '').toLowerCase()] = hyphenate(key);
+ }
+ def = components[key];
+ if (isPlainObject(def)) {
+ components[key] = Vue.extend(def);
+ }
+ }
+ }
+ }
+
+ /**
+ * Ensure all props option syntax are normalized into the
+ * Object-based format.
+ *
+ * @param {Object} options
+ */
+
+ function guardProps(options) {
+ var props = options.props;
+ var i, val;
+ if (isArray(props)) {
+ options.props = {};
+ i = props.length;
+ while (i--) {
+ val = props[i];
+ if (typeof val === 'string') {
+ options.props[val] = null;
+ } else if (val.name) {
+ options.props[val.name] = val;
+ }
+ }
+ } else if (isPlainObject(props)) {
+ var keys = Object.keys(props);
+ i = keys.length;
+ while (i--) {
+ val = props[keys[i]];
+ if (typeof val === 'function') {
+ props[keys[i]] = { type: val };
+ }
+ }
+ }
+ }
+
+ /**
+ * Guard an Array-format assets option and converted it
+ * into the key-value Object format.
+ *
+ * @param {Object|Array} assets
+ * @return {Object}
+ */
+
+ function guardArrayAssets(assets) {
+ if (isArray(assets)) {
+ var res = {};
+ var i = assets.length;
+ var asset;
+ while (i--) {
+ asset = assets[i];
+ var id = typeof asset === 'function' ? asset.options && asset.options.name || asset.id : asset.name || asset.id;
+ if (!id) {
+ 'development' !== 'production' && warn('Array-syntax assets must provide a "name" or "id" field.');
+ } else {
+ res[id] = asset;
+ }
+ }
+ return res;
+ }
+ return assets;
+ }
+
+ /**
+ * Merge two option objects into a new one.
+ * Core utility used in both instantiation and inheritance.
+ *
+ * @param {Object} parent
+ * @param {Object} child
+ * @param {Vue} [vm] - if vm is present, indicates this is
+ * an instantiation merge.
+ */
+
+ function mergeOptions(parent, child, vm) {
+ guardComponents(child);
+ guardProps(child);
+ if ('development' !== 'production') {
+ if (child.propsData && !vm) {
+ warn('propsData can only be used as an instantiation option.');
+ }
+ }
+ var options = {};
+ var key;
+ if (child['extends']) {
+ parent = typeof child['extends'] === 'function' ? mergeOptions(parent, child['extends'].options, vm) : mergeOptions(parent, child['extends'], vm);
+ }
+ if (child.mixins) {
+ for (var i = 0, l = child.mixins.length; i < l; i++) {
+ var mixin = child.mixins[i];
+ var mixinOptions = mixin.prototype instanceof Vue ? mixin.options : mixin;
+ parent = mergeOptions(parent, mixinOptions, vm);
+ }
+ }
+ for (key in parent) {
+ mergeField(key);
+ }
+ for (key in child) {
+ if (!hasOwn(parent, key)) {
+ mergeField(key);
+ }
+ }
+ function mergeField(key) {
+ var strat = strats[key] || defaultStrat;
+ options[key] = strat(parent[key], child[key], vm, key);
+ }
+ return options;
+ }
+
+ /**
+ * Resolve an asset.
+ * This function is used because child instances need access
+ * to assets defined in its ancestor chain.
+ *
+ * @param {Object} options
+ * @param {String} type
+ * @param {String} id
+ * @param {Boolean} warnMissing
+ * @return {Object|Function}
+ */
+
+ function resolveAsset(options, type, id, warnMissing) {
+ /* istanbul ignore if */
+ if (typeof id !== 'string') {
+ return;
+ }
+ var assets = options[type];
+ var camelizedId;
+ var res = assets[id] ||
+ // camelCase ID
+ assets[camelizedId = camelize(id)] ||
+ // Pascal Case ID
+ assets[camelizedId.charAt(0).toUpperCase() + camelizedId.slice(1)];
+ if ('development' !== 'production' && warnMissing && !res) {
+ warn('Failed to resolve ' + type.slice(0, -1) + ': ' + id, options);
+ }
+ return res;
+ }
+
+ var uid$1 = 0;
+
+ /**
+ * A dep is an observable that can have multiple
+ * directives subscribing to it.
+ *
+ * @constructor
+ */
+ function Dep() {
+ this.id = uid$1++;
+ this.subs = [];
+ }
+
+ // the current target watcher being evaluated.
+ // this is globally unique because there could be only one
+ // watcher being evaluated at any time.
+ Dep.target = null;
+
+ /**
+ * Add a directive subscriber.
+ *
+ * @param {Directive} sub
+ */
+
+ Dep.prototype.addSub = function (sub) {
+ this.subs.push(sub);
+ };
+
+ /**
+ * Remove a directive subscriber.
+ *
+ * @param {Directive} sub
+ */
+
+ Dep.prototype.removeSub = function (sub) {
+ this.subs.$remove(sub);
+ };
+
+ /**
+ * Add self as a dependency to the target watcher.
+ */
+
+ Dep.prototype.depend = function () {
+ Dep.target.addDep(this);
+ };
+
+ /**
+ * Notify all subscribers of a new value.
+ */
+
+ Dep.prototype.notify = function () {
+ // stablize the subscriber list first
+ var subs = toArray(this.subs);
+ for (var i = 0, l = subs.length; i < l; i++) {
+ subs[i].update();
+ }
+ };
+
+ var arrayProto = Array.prototype;
+ var arrayMethods = Object.create(arrayProto)
+
+ /**
+ * Intercept mutating methods and emit events
+ */
+
+ ;['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(function (method) {
+ // cache original method
+ var original = arrayProto[method];
+ def(arrayMethods, method, function mutator() {
+ // avoid leaking arguments:
+ // http://jsperf.com/closure-with-arguments
+ var i = arguments.length;
+ var args = new Array(i);
+ while (i--) {
+ args[i] = arguments[i];
+ }
+ var result = original.apply(this, args);
+ var ob = this.__ob__;
+ var inserted;
+ switch (method) {
+ case 'push':
+ inserted = args;
+ break;
+ case 'unshift':
+ inserted = args;
+ break;
+ case 'splice':
+ inserted = args.slice(2);
+ break;
+ }
+ if (inserted) ob.observeArray(inserted);
+ // notify change
+ ob.dep.notify();
+ return result;
+ });
+ });
+
+ /**
+ * Swap the element at the given index with a new value
+ * and emits corresponding event.
+ *
+ * @param {Number} index
+ * @param {*} val
+ * @return {*} - replaced element
+ */
+
+ def(arrayProto, '$set', function $set(index, val) {
+ if (index >= this.length) {
+ this.length = Number(index) + 1;
+ }
+ return this.splice(index, 1, val)[0];
+ });
+
+ /**
+ * Convenience method to remove the element at given index or target element reference.
+ *
+ * @param {*} item
+ */
+
+ def(arrayProto, '$remove', function $remove(item) {
+ /* istanbul ignore if */
+ if (!this.length) return;
+ var index = indexOf(this, item);
+ if (index > -1) {
+ return this.splice(index, 1);
+ }
+ });
+
+ var arrayKeys = Object.getOwnPropertyNames(arrayMethods);
+
+ /**
+ * By default, when a reactive property is set, the new value is
+ * also converted to become reactive. However in certain cases, e.g.
+ * v-for scope alias and props, we don't want to force conversion
+ * because the value may be a nested value under a frozen data structure.
+ *
+ * So whenever we want to set a reactive property without forcing
+ * conversion on the new value, we wrap that call inside this function.
+ */
+
+ var shouldConvert = true;
+
+ function withoutConversion(fn) {
+ shouldConvert = false;
+ fn();
+ shouldConvert = true;
+ }
+
+ /**
+ * Observer class that are attached to each observed
+ * object. Once attached, the observer converts target
+ * object's property keys into getter/setters that
+ * collect dependencies and dispatches updates.
+ *
+ * @param {Array|Object} value
+ * @constructor
+ */
+
+ function Observer(value) {
+ this.value = value;
+ this.dep = new Dep();
+ def(value, '__ob__', this);
+ if (isArray(value)) {
+ var augment = hasProto ? protoAugment : copyAugment;
+ augment(value, arrayMethods, arrayKeys);
+ this.observeArray(value);
+ } else {
+ this.walk(value);
+ }
+ }
+
+ // Instance methods
+
+ /**
+ * Walk through each property and convert them into
+ * getter/setters. This method should only be called when
+ * value type is Object.
+ *
+ * @param {Object} obj
+ */
+
+ Observer.prototype.walk = function (obj) {
+ var keys = Object.keys(obj);
+ for (var i = 0, l = keys.length; i < l; i++) {
+ this.convert(keys[i], obj[keys[i]]);
+ }
+ };
+
+ /**
+ * Observe a list of Array items.
+ *
+ * @param {Array} items
+ */
+
+ Observer.prototype.observeArray = function (items) {
+ for (var i = 0, l = items.length; i < l; i++) {
+ observe(items[i]);
+ }
+ };
+
+ /**
+ * Convert a property into getter/setter so we can emit
+ * the events when the property is accessed/changed.
+ *
+ * @param {String} key
+ * @param {*} val
+ */
+
+ Observer.prototype.convert = function (key, val) {
+ defineReactive(this.value, key, val);
+ };
+
+ /**
+ * Add an owner vm, so that when $set/$delete mutations
+ * happen we can notify owner vms to proxy the keys and
+ * digest the watchers. This is only called when the object
+ * is observed as an instance's root $data.
+ *
+ * @param {Vue} vm
+ */
+
+ Observer.prototype.addVm = function (vm) {
+ (this.vms || (this.vms = [])).push(vm);
+ };
+
+ /**
+ * Remove an owner vm. This is called when the object is
+ * swapped out as an instance's $data object.
+ *
+ * @param {Vue} vm
+ */
+
+ Observer.prototype.removeVm = function (vm) {
+ this.vms.$remove(vm);
+ };
+
+ // helpers
+
+ /**
+ * Augment an target Object or Array by intercepting
+ * the prototype chain using __proto__
+ *
+ * @param {Object|Array} target
+ * @param {Object} src
+ */
+
+ function protoAugment(target, src) {
+ /* eslint-disable no-proto */
+ target.__proto__ = src;
+ /* eslint-enable no-proto */
+ }
+
+ /**
+ * Augment an target Object or Array by defining
+ * hidden properties.
+ *
+ * @param {Object|Array} target
+ * @param {Object} proto
+ */
+
+ function copyAugment(target, src, keys) {
+ for (var i = 0, l = keys.length; i < l; i++) {
+ var key = keys[i];
+ def(target, key, src[key]);
+ }
+ }
+
+ /**
+ * Attempt to create an observer instance for a value,
+ * returns the new observer if successfully observed,
+ * or the existing observer if the value already has one.
+ *
+ * @param {*} value
+ * @param {Vue} [vm]
+ * @return {Observer|undefined}
+ * @static
+ */
+
+ function observe(value, vm) {
+ if (!value || typeof value !== 'object') {
+ return;
+ }
+ var ob;
+ if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
+ ob = value.__ob__;
+ } else if (shouldConvert && (isArray(value) || isPlainObject(value)) && Object.isExtensible(value) && !value._isVue) {
+ ob = new Observer(value);
+ }
+ if (ob && vm) {
+ ob.addVm(vm);
+ }
+ return ob;
+ }
+
+ /**
+ * Define a reactive property on an Object.
+ *
+ * @param {Object} obj
+ * @param {String} key
+ * @param {*} val
+ */
+
+ function defineReactive(obj, key, val) {
+ var dep = new Dep();
+
+ var property = Object.getOwnPropertyDescriptor(obj, key);
+ if (property && property.configurable === false) {
+ return;
+ }
+
+ // cater for pre-defined getter/setters
+ var getter = property && property.get;
+ var setter = property && property.set;
+
+ var childOb = observe(val);
+ Object.defineProperty(obj, key, {
+ enumerable: true,
+ configurable: true,
+ get: function reactiveGetter() {
+ var value = getter ? getter.call(obj) : val;
+ if (Dep.target) {
+ dep.depend();
+ if (childOb) {
+ childOb.dep.depend();
+ }
+ if (isArray(value)) {
+ for (var e, i = 0, l = value.length; i < l; i++) {
+ e = value[i];
+ e && e.__ob__ && e.__ob__.dep.depend();
+ }
+ }
+ }
+ return value;
+ },
+ set: function reactiveSetter(newVal) {
+ var value = getter ? getter.call(obj) : val;
+ if (newVal === value) {
+ return;
+ }
+ if (setter) {
+ setter.call(obj, newVal);
+ } else {
+ val = newVal;
+ }
+ childOb = observe(newVal);
+ dep.notify();
+ }
+ });
+ }
+
+
+
+ var util = Object.freeze({
+ defineReactive: defineReactive,
+ set: set,
+ del: del,
+ hasOwn: hasOwn,
+ isLiteral: isLiteral,
+ isReserved: isReserved,
+ _toString: _toString,
+ toNumber: toNumber,
+ toBoolean: toBoolean,
+ stripQuotes: stripQuotes,
+ camelize: camelize,
+ hyphenate: hyphenate,
+ classify: classify,
+ bind: bind,
+ toArray: toArray,
+ extend: extend,
+ isObject: isObject,
+ isPlainObject: isPlainObject,
+ def: def,
+ debounce: _debounce,
+ indexOf: indexOf,
+ cancellable: cancellable,
+ looseEqual: looseEqual,
+ isArray: isArray,
+ hasProto: hasProto,
+ inBrowser: inBrowser,
+ devtools: devtools,
+ isIE: isIE,
+ isIE9: isIE9,
+ isAndroid: isAndroid,
+ isIos: isIos,
+ iosVersionMatch: iosVersionMatch,
+ iosVersion: iosVersion,
+ hasMutationObserverBug: hasMutationObserverBug,
+ get transitionProp () { return transitionProp; },
+ get transitionEndEvent () { return transitionEndEvent; },
+ get animationProp () { return animationProp; },
+ get animationEndEvent () { return animationEndEvent; },
+ nextTick: nextTick,
+ get _Set () { return _Set; },
+ query: query,
+ inDoc: inDoc,
+ getAttr: getAttr,
+ getBindAttr: getBindAttr,
+ hasBindAttr: hasBindAttr,
+ before: before,
+ after: after,
+ remove: remove,
+ prepend: prepend,
+ replace: replace,
+ on: on,
+ off: off,
+ setClass: setClass,
+ addClass: addClass,
+ removeClass: removeClass,
+ extractContent: extractContent,
+ trimNode: trimNode,
+ isTemplate: isTemplate,
+ createAnchor: createAnchor,
+ findRef: findRef,
+ mapNodeRange: mapNodeRange,
+ removeNodeRange: removeNodeRange,
+ isFragment: isFragment,
+ getOuterHTML: getOuterHTML,
+ mergeOptions: mergeOptions,
+ resolveAsset: resolveAsset,
+ checkComponentAttr: checkComponentAttr,
+ commonTagRE: commonTagRE,
+ reservedTagRE: reservedTagRE,
+ get warn () { return warn; }
+ });
+
+ var uid = 0;
+
+ function initMixin (Vue) {
+ /**
+ * The main init sequence. This is called for every
+ * instance, including ones that are created from extended
+ * constructors.
+ *
+ * @param {Object} options - this options object should be
+ * the result of merging class
+ * options and the options passed
+ * in to the constructor.
+ */
+
+ Vue.prototype._init = function (options) {
+ options = options || {};
+
+ this.$el = null;
+ this.$parent = options.parent;
+ this.$root = this.$parent ? this.$parent.$root : this;
+ this.$children = [];
+ this.$refs = {}; // child vm references
+ this.$els = {}; // element references
+ this._watchers = []; // all watchers as an array
+ this._directives = []; // all directives
+
+ // a uid
+ this._uid = uid++;
+
+ // a flag to avoid this being observed
+ this._isVue = true;
+
+ // events bookkeeping
+ this._events = {}; // registered callbacks
+ this._eventsCount = {}; // for $broadcast optimization
+
+ // fragment instance properties
+ this._isFragment = false;
+ this._fragment = // @type {DocumentFragment}
+ this._fragmentStart = // @type {Text|Comment}
+ this._fragmentEnd = null; // @type {Text|Comment}
+
+ // lifecycle state
+ this._isCompiled = this._isDestroyed = this._isReady = this._isAttached = this._isBeingDestroyed = this._vForRemoving = false;
+ this._unlinkFn = null;
+
+ // context:
+ // if this is a transcluded component, context
+ // will be the common parent vm of this instance
+ // and its host.
+ this._context = options._context || this.$parent;
+
+ // scope:
+ // if this is inside an inline v-for, the scope
+ // will be the intermediate scope created for this
+ // repeat fragment. this is used for linking props
+ // and container directives.
+ this._scope = options._scope;
+
+ // fragment:
+ // if this instance is compiled inside a Fragment, it
+ // needs to reigster itself as a child of that fragment
+ // for attach/detach to work properly.
+ this._frag = options._frag;
+ if (this._frag) {
+ this._frag.children.push(this);
+ }
+
+ // push self into parent / transclusion host
+ if (this.$parent) {
+ this.$parent.$children.push(this);
+ }
+
+ // merge options.
+ options = this.$options = mergeOptions(this.constructor.options, options, this);
+
+ // set ref
+ this._updateRef();
+
+ // initialize data as empty object.
+ // it will be filled up in _initData().
+ this._data = {};
+
+ // call init hook
+ this._callHook('init');
+
+ // initialize data observation and scope inheritance.
+ this._initState();
+
+ // setup event system and option events.
+ this._initEvents();
+
+ // call created hook
+ this._callHook('created');
+
+ // if `el` option is passed, start compilation.
+ if (options.el) {
+ this.$mount(options.el);
+ }
+ };
+ }
+
+ var pathCache = new Cache(1000);
+
+ // actions
+ var APPEND = 0;
+ var PUSH = 1;
+ var INC_SUB_PATH_DEPTH = 2;
+ var PUSH_SUB_PATH = 3;
+
+ // states
+ var BEFORE_PATH = 0;
+ var IN_PATH = 1;
+ var BEFORE_IDENT = 2;
+ var IN_IDENT = 3;
+ var IN_SUB_PATH = 4;
+ var IN_SINGLE_QUOTE = 5;
+ var IN_DOUBLE_QUOTE = 6;
+ var AFTER_PATH = 7;
+ var ERROR = 8;
+
+ var pathStateMachine = [];
+
+ pathStateMachine[BEFORE_PATH] = {
+ 'ws': [BEFORE_PATH],
+ 'ident': [IN_IDENT, APPEND],
+ '[': [IN_SUB_PATH],
+ 'eof': [AFTER_PATH]
+ };
+
+ pathStateMachine[IN_PATH] = {
+ 'ws': [IN_PATH],
+ '.': [BEFORE_IDENT],
+ '[': [IN_SUB_PATH],
+ 'eof': [AFTER_PATH]
+ };
+
+ pathStateMachine[BEFORE_IDENT] = {
+ 'ws': [BEFORE_IDENT],
+ 'ident': [IN_IDENT, APPEND]
+ };
+
+ pathStateMachine[IN_IDENT] = {
+ 'ident': [IN_IDENT, APPEND],
+ '0': [IN_IDENT, APPEND],
+ 'number': [IN_IDENT, APPEND],
+ 'ws': [IN_PATH, PUSH],
+ '.': [BEFORE_IDENT, PUSH],
+ '[': [IN_SUB_PATH, PUSH],
+ 'eof': [AFTER_PATH, PUSH]
+ };
+
+ pathStateMachine[IN_SUB_PATH] = {
+ "'": [IN_SINGLE_QUOTE, APPEND],
+ '"': [IN_DOUBLE_QUOTE, APPEND],
+ '[': [IN_SUB_PATH, INC_SUB_PATH_DEPTH],
+ ']': [IN_PATH, PUSH_SUB_PATH],
+ 'eof': ERROR,
+ 'else': [IN_SUB_PATH, APPEND]
+ };
+
+ pathStateMachine[IN_SINGLE_QUOTE] = {
+ "'": [IN_SUB_PATH, APPEND],
+ 'eof': ERROR,
+ 'else': [IN_SINGLE_QUOTE, APPEND]
+ };
+
+ pathStateMachine[IN_DOUBLE_QUOTE] = {
+ '"': [IN_SUB_PATH, APPEND],
+ 'eof': ERROR,
+ 'else': [IN_DOUBLE_QUOTE, APPEND]
+ };
+
+ /**
+ * Determine the type of a character in a keypath.
+ *
+ * @param {Char} ch
+ * @return {String} type
+ */
+
+ function getPathCharType(ch) {
+ if (ch === undefined) {
+ return 'eof';
+ }
+
+ var code = ch.charCodeAt(0);
+
+ switch (code) {
+ case 0x5B: // [
+ case 0x5D: // ]
+ case 0x2E: // .
+ case 0x22: // "
+ case 0x27: // '
+ case 0x30:
+ // 0
+ return ch;
+
+ case 0x5F: // _
+ case 0x24:
+ // $
+ return 'ident';
+
+ case 0x20: // Space
+ case 0x09: // Tab
+ case 0x0A: // Newline
+ case 0x0D: // Return
+ case 0xA0: // No-break space
+ case 0xFEFF: // Byte Order Mark
+ case 0x2028: // Line Separator
+ case 0x2029:
+ // Paragraph Separator
+ return 'ws';
+ }
+
+ // a-z, A-Z
+ if (code >= 0x61 && code <= 0x7A || code >= 0x41 && code <= 0x5A) {
+ return 'ident';
+ }
+
+ // 1-9
+ if (code >= 0x31 && code <= 0x39) {
+ return 'number';
+ }
+
+ return 'else';
+ }
+
+ /**
+ * Format a subPath, return its plain form if it is
+ * a literal string or number. Otherwise prepend the
+ * dynamic indicator (*).
+ *
+ * @param {String} path
+ * @return {String}
+ */
+
+ function formatSubPath(path) {
+ var trimmed = path.trim();
+ // invalid leading 0
+ if (path.charAt(0) === '0' && isNaN(path)) {
+ return false;
+ }
+ return isLiteral(trimmed) ? stripQuotes(trimmed) : '*' + trimmed;
+ }
+
+ /**
+ * Parse a string path into an array of segments
+ *
+ * @param {String} path
+ * @return {Array|undefined}
+ */
+
+ function parse(path) {
+ var keys = [];
+ var index = -1;
+ var mode = BEFORE_PATH;
+ var subPathDepth = 0;
+ var c, newChar, key, type, transition, action, typeMap;
+
+ var actions = [];
+
+ actions[PUSH] = function () {
+ if (key !== undefined) {
+ keys.push(key);
+ key = undefined;
+ }
+ };
+
+ actions[APPEND] = function () {
+ if (key === undefined) {
+ key = newChar;
+ } else {
+ key += newChar;
+ }
+ };
+
+ actions[INC_SUB_PATH_DEPTH] = function () {
+ actions[APPEND]();
+ subPathDepth++;
+ };
+
+ actions[PUSH_SUB_PATH] = function () {
+ if (subPathDepth > 0) {
+ subPathDepth--;
+ mode = IN_SUB_PATH;
+ actions[APPEND]();
+ } else {
+ subPathDepth = 0;
+ key = formatSubPath(key);
+ if (key === false) {
+ return false;
+ } else {
+ actions[PUSH]();
+ }
+ }
+ };
+
+ function maybeUnescapeQuote() {
+ var nextChar = path[index + 1];
+ if (mode === IN_SINGLE_QUOTE && nextChar === "'" || mode === IN_DOUBLE_QUOTE && nextChar === '"') {
+ index++;
+ newChar = '\\' + nextChar;
+ actions[APPEND]();
+ return true;
+ }
+ }
+
+ while (mode != null) {
+ index++;
+ c = path[index];
+
+ if (c === '\\' && maybeUnescapeQuote()) {
+ continue;
+ }
+
+ type = getPathCharType(c);
+ typeMap = pathStateMachine[mode];
+ transition = typeMap[type] || typeMap['else'] || ERROR;
+
+ if (transition === ERROR) {
+ return; // parse error
+ }
+
+ mode = transition[0];
+ action = actions[transition[1]];
+ if (action) {
+ newChar = transition[2];
+ newChar = newChar === undefined ? c : newChar;
+ if (action() === false) {
+ return;
+ }
+ }
+
+ if (mode === AFTER_PATH) {
+ keys.raw = path;
+ return keys;
+ }
+ }
+ }
+
+ /**
+ * External parse that check for a cache hit first
+ *
+ * @param {String} path
+ * @return {Array|undefined}
+ */
+
+ function parsePath(path) {
+ var hit = pathCache.get(path);
+ if (!hit) {
+ hit = parse(path);
+ if (hit) {
+ pathCache.put(path, hit);
+ }
+ }
+ return hit;
+ }
+
+ /**
+ * Get from an object from a path string
+ *
+ * @param {Object} obj
+ * @param {String} path
+ */
+
+ function getPath(obj, path) {
+ return parseExpression(path).get(obj);
+ }
+
+ /**
+ * Warn against setting non-existent root path on a vm.
+ */
+
+ var warnNonExistent;
+ if ('development' !== 'production') {
+ warnNonExistent = function (path, vm) {
+ warn('You are setting a non-existent path "' + path.raw + '" ' + 'on a vm instance. Consider pre-initializing the property ' + 'with the "data" option for more reliable reactivity ' + 'and better performance.', vm);
+ };
+ }
+
+ /**
+ * Set on an object from a path
+ *
+ * @param {Object} obj
+ * @param {String | Array} path
+ * @param {*} val
+ */
+
+ function setPath(obj, path, val) {
+ var original = obj;
+ if (typeof path === 'string') {
+ path = parse(path);
+ }
+ if (!path || !isObject(obj)) {
+ return false;
+ }
+ var last, key;
+ for (var i = 0, l = path.length; i < l; i++) {
+ last = obj;
+ key = path[i];
+ if (key.charAt(0) === '*') {
+ key = parseExpression(key.slice(1)).get.call(original, original);
+ }
+ if (i < l - 1) {
+ obj = obj[key];
+ if (!isObject(obj)) {
+ obj = {};
+ if ('development' !== 'production' && last._isVue) {
+ warnNonExistent(path, last);
+ }
+ set(last, key, obj);
+ }
+ } else {
+ if (isArray(obj)) {
+ obj.$set(key, val);
+ } else if (key in obj) {
+ obj[key] = val;
+ } else {
+ if ('development' !== 'production' && obj._isVue) {
+ warnNonExistent(path, obj);
+ }
+ set(obj, key, val);
+ }
+ }
+ }
+ return true;
+ }
+
+var path = Object.freeze({
+ parsePath: parsePath,
+ getPath: getPath,
+ setPath: setPath
+ });
+
+ var expressionCache = new Cache(1000);
+
+ var allowedKeywords = 'Math,Date,this,true,false,null,undefined,Infinity,NaN,' + 'isNaN,isFinite,decodeURI,decodeURIComponent,encodeURI,' + 'encodeURIComponent,parseInt,parseFloat';
+ var allowedKeywordsRE = new RegExp('^(' + allowedKeywords.replace(/,/g, '\\b|') + '\\b)');
+
+ // keywords that don't make sense inside expressions
+ var improperKeywords = 'break,case,class,catch,const,continue,debugger,default,' + 'delete,do,else,export,extends,finally,for,function,if,' + 'import,in,instanceof,let,return,super,switch,throw,try,' + 'var,while,with,yield,enum,await,implements,package,' + 'protected,static,interface,private,public';
+ var improperKeywordsRE = new RegExp('^(' + improperKeywords.replace(/,/g, '\\b|') + '\\b)');
+
+ var wsRE = /\s/g;
+ var newlineRE = /\n/g;
+ var saveRE = /[\{,]\s*[\w\$_]+\s*:|('(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`)|new |typeof |void /g;
+ var restoreRE = /"(\d+)"/g;
+ var pathTestRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['.*?'\]|\[".*?"\]|\[\d+\]|\[[A-Za-z_$][\w$]*\])*$/;
+ var identRE = /[^\w$\.](?:[A-Za-z_$][\w$]*)/g;
+ var literalValueRE$1 = /^(?:true|false|null|undefined|Infinity|NaN)$/;
+
+ function noop() {}
+
+ /**
+ * Save / Rewrite / Restore
+ *
+ * When rewriting paths found in an expression, it is
+ * possible for the same letter sequences to be found in
+ * strings and Object literal property keys. Therefore we
+ * remove and store these parts in a temporary array, and
+ * restore them after the path rewrite.
+ */
+
+ var saved = [];
+
+ /**
+ * Save replacer
+ *
+ * The save regex can match two possible cases:
+ * 1. An opening object literal
+ * 2. A string
+ * If matched as a plain string, we need to escape its
+ * newlines, since the string needs to be preserved when
+ * generating the function body.
+ *
+ * @param {String} str
+ * @param {String} isString - str if matched as a string
+ * @return {String} - placeholder with index
+ */
+
+ function save(str, isString) {
+ var i = saved.length;
+ saved[i] = isString ? str.replace(newlineRE, '\\n') : str;
+ return '"' + i + '"';
+ }
+
+ /**
+ * Path rewrite replacer
+ *
+ * @param {String} raw
+ * @return {String}
+ */
+
+ function rewrite(raw) {
+ var c = raw.charAt(0);
+ var path = raw.slice(1);
+ if (allowedKeywordsRE.test(path)) {
+ return raw;
+ } else {
+ path = path.indexOf('"') > -1 ? path.replace(restoreRE, restore) : path;
+ return c + 'scope.' + path;
+ }
+ }
+
+ /**
+ * Restore replacer
+ *
+ * @param {String} str
+ * @param {String} i - matched save index
+ * @return {String}
+ */
+
+ function restore(str, i) {
+ return saved[i];
+ }
+
+ /**
+ * Rewrite an expression, prefixing all path accessors with
+ * `scope.` and generate getter/setter functions.
+ *
+ * @param {String} exp
+ * @return {Function}
+ */
+
+ function compileGetter(exp) {
+ if (improperKeywordsRE.test(exp)) {
+ 'development' !== 'production' && warn('Avoid using reserved keywords in expression: ' + exp);
+ }
+ // reset state
+ saved.length = 0;
+ // save strings and object literal keys
+ var body = exp.replace(saveRE, save).replace(wsRE, '');
+ // rewrite all paths
+ // pad 1 space here because the regex matches 1 extra char
+ body = (' ' + body).replace(identRE, rewrite).replace(restoreRE, restore);
+ return makeGetterFn(body);
+ }
+
+ /**
+ * Build a getter function. Requires eval.
+ *
+ * We isolate the try/catch so it doesn't affect the
+ * optimization of the parse function when it is not called.
+ *
+ * @param {String} body
+ * @return {Function|undefined}
+ */
+
+ function makeGetterFn(body) {
+ try {
+ /* eslint-disable no-new-func */
+ return new Function('scope', 'return ' + body + ';');
+ /* eslint-enable no-new-func */
+ } catch (e) {
+ if ('development' !== 'production') {
+ /* istanbul ignore if */
+ if (e.toString().match(/unsafe-eval|CSP/)) {
+ warn('It seems you are using the default build of Vue.js in an environment ' + 'with Content Security Policy that prohibits unsafe-eval. ' + 'Use the CSP-compliant build instead: ' + 'http://vuejs.org/guide/installation.html#CSP-compliant-build');
+ } else {
+ warn('Invalid expression. ' + 'Generated function body: ' + body);
+ }
+ }
+ return noop;
+ }
+ }
+
+ /**
+ * Compile a setter function for the expression.
+ *
+ * @param {String} exp
+ * @return {Function|undefined}
+ */
+
+ function compileSetter(exp) {
+ var path = parsePath(exp);
+ if (path) {
+ return function (scope, val) {
+ setPath(scope, path, val);
+ };
+ } else {
+ 'development' !== 'production' && warn('Invalid setter expression: ' + exp);
+ }
+ }
+
+ /**
+ * Parse an expression into re-written getter/setters.
+ *
+ * @param {String} exp
+ * @param {Boolean} needSet
+ * @return {Function}
+ */
+
+ function parseExpression(exp, needSet) {
+ exp = exp.trim();
+ // try cache
+ var hit = expressionCache.get(exp);
+ if (hit) {
+ if (needSet && !hit.set) {
+ hit.set = compileSetter(hit.exp);
+ }
+ return hit;
+ }
+ var res = { exp: exp };
+ res.get = isSimplePath(exp) && exp.indexOf('[') < 0
+ // optimized super simple getter
+ ? makeGetterFn('scope.' + exp)
+ // dynamic getter
+ : compileGetter(exp);
+ if (needSet) {
+ res.set = compileSetter(exp);
+ }
+ expressionCache.put(exp, res);
+ return res;
+ }
+
+ /**
+ * Check if an expression is a simple path.
+ *
+ * @param {String} exp
+ * @return {Boolean}
+ */
+
+ function isSimplePath(exp) {
+ return pathTestRE.test(exp) &&
+ // don't treat literal values as paths
+ !literalValueRE$1.test(exp) &&
+ // Math constants e.g. Math.PI, Math.E etc.
+ exp.slice(0, 5) !== 'Math.';
+ }
+
+var expression = Object.freeze({
+ parseExpression: parseExpression,
+ isSimplePath: isSimplePath
+ });
+
+ // we have two separate queues: one for directive updates
+ // and one for user watcher registered via $watch().
+ // we want to guarantee directive updates to be called
+ // before user watchers so that when user watchers are
+ // triggered, the DOM would have already been in updated
+ // state.
+
+ var queue = [];
+ var userQueue = [];
+ var has = {};
+ var circular = {};
+ var waiting = false;
+
+ /**
+ * Reset the batcher's state.
+ */
+
+ function resetBatcherState() {
+ queue.length = 0;
+ userQueue.length = 0;
+ has = {};
+ circular = {};
+ waiting = false;
+ }
+
+ /**
+ * Flush both queues and run the watchers.
+ */
+
+ function flushBatcherQueue() {
+ var _again = true;
+
+ _function: while (_again) {
+ _again = false;
+
+ runBatcherQueue(queue);
+ runBatcherQueue(userQueue);
+ // user watchers triggered more watchers,
+ // keep flushing until it depletes
+ if (queue.length) {
+ _again = true;
+ continue _function;
+ }
+ // dev tool hook
+ /* istanbul ignore if */
+ if (devtools && config.devtools) {
+ devtools.emit('flush');
+ }
+ resetBatcherState();
+ }
+ }
+
+ /**
+ * Run the watchers in a single queue.
+ *
+ * @param {Array} queue
+ */
+
+ function runBatcherQueue(queue) {
+ // do not cache length because more watchers might be pushed
+ // as we run existing watchers
+ for (var i = 0; i < queue.length; i++) {
+ var watcher = queue[i];
+ var id = watcher.id;
+ has[id] = null;
+ watcher.run();
+ // in dev build, check and stop circular updates.
+ if ('development' !== 'production' && has[id] != null) {
+ circular[id] = (circular[id] || 0) + 1;
+ if (circular[id] > config._maxUpdateCount) {
+ warn('You may have an infinite update loop for watcher ' + 'with expression "' + watcher.expression + '"', watcher.vm);
+ break;
+ }
+ }
+ }
+ queue.length = 0;
+ }
+
+ /**
+ * Push a watcher into the watcher queue.
+ * Jobs with duplicate IDs will be skipped unless it's
+ * pushed when the queue is being flushed.
+ *
+ * @param {Watcher} watcher
+ * properties:
+ * - {Number} id
+ * - {Function} run
+ */
+
+ function pushWatcher(watcher) {
+ var id = watcher.id;
+ if (has[id] == null) {
+ // push watcher into appropriate queue
+ var q = watcher.user ? userQueue : queue;
+ has[id] = q.length;
+ q.push(watcher);
+ // queue the flush
+ if (!waiting) {
+ waiting = true;
+ nextTick(flushBatcherQueue);
+ }
+ }
+ }
+
+ var uid$2 = 0;
+
+ /**
+ * A watcher parses an expression, collects dependencies,
+ * and fires callback when the expression value changes.
+ * This is used for both the $watch() api and directives.
+ *
+ * @param {Vue} vm
+ * @param {String|Function} expOrFn
+ * @param {Function} cb
+ * @param {Object} options
+ * - {Array} filters
+ * - {Boolean} twoWay
+ * - {Boolean} deep
+ * - {Boolean} user
+ * - {Boolean} sync
+ * - {Boolean} lazy
+ * - {Function} [preProcess]
+ * - {Function} [postProcess]
+ * @constructor
+ */
+ function Watcher(vm, expOrFn, cb, options) {
+ // mix in options
+ if (options) {
+ extend(this, options);
+ }
+ var isFn = typeof expOrFn === 'function';
+ this.vm = vm;
+ vm._watchers.push(this);
+ this.expression = expOrFn;
+ this.cb = cb;
+ this.id = ++uid$2; // uid for batching
+ this.active = true;
+ this.dirty = this.lazy; // for lazy watchers
+ this.deps = [];
+ this.newDeps = [];
+ this.depIds = new _Set();
+ this.newDepIds = new _Set();
+ this.prevError = null; // for async error stacks
+ // parse expression for getter/setter
+ if (isFn) {
+ this.getter = expOrFn;
+ this.setter = undefined;
+ } else {
+ var res = parseExpression(expOrFn, this.twoWay);
+ this.getter = res.get;
+ this.setter = res.set;
+ }
+ this.value = this.lazy ? undefined : this.get();
+ // state for avoiding false triggers for deep and Array
+ // watchers during vm._digest()
+ this.queued = this.shallow = false;
+ }
+
+ /**
+ * Evaluate the getter, and re-collect dependencies.
+ */
+
+ Watcher.prototype.get = function () {
+ this.beforeGet();
+ var scope = this.scope || this.vm;
+ var value;
+ try {
+ value = this.getter.call(scope, scope);
+ } catch (e) {
+ if ('development' !== 'production' && config.warnExpressionErrors) {
+ warn('Error when evaluating expression ' + '"' + this.expression + '": ' + e.toString(), this.vm);
+ }
+ }
+ // "touch" every property so they are all tracked as
+ // dependencies for deep watching
+ if (this.deep) {
+ traverse(value);
+ }
+ if (this.preProcess) {
+ value = this.preProcess(value);
+ }
+ if (this.filters) {
+ value = scope._applyFilters(value, null, this.filters, false);
+ }
+ if (this.postProcess) {
+ value = this.postProcess(value);
+ }
+ this.afterGet();
+ return value;
+ };
+
+ /**
+ * Set the corresponding value with the setter.
+ *
+ * @param {*} value
+ */
+
+ Watcher.prototype.set = function (value) {
+ var scope = this.scope || this.vm;
+ if (this.filters) {
+ value = scope._applyFilters(value, this.value, this.filters, true);
+ }
+ try {
+ this.setter.call(scope, scope, value);
+ } catch (e) {
+ if ('development' !== 'production' && config.warnExpressionErrors) {
+ warn('Error when evaluating setter ' + '"' + this.expression + '": ' + e.toString(), this.vm);
+ }
+ }
+ // two-way sync for v-for alias
+ var forContext = scope.$forContext;
+ if (forContext && forContext.alias === this.expression) {
+ if (forContext.filters) {
+ 'development' !== 'production' && warn('It seems you are using two-way binding on ' + 'a v-for alias (' + this.expression + '), and the ' + 'v-for has filters. This will not work properly. ' + 'Either remove the filters or use an array of ' + 'objects and bind to object properties instead.', this.vm);
+ return;
+ }
+ forContext._withLock(function () {
+ if (scope.$key) {
+ // original is an object
+ forContext.rawValue[scope.$key] = value;
+ } else {
+ forContext.rawValue.$set(scope.$index, value);
+ }
+ });
+ }
+ };
+
+ /**
+ * Prepare for dependency collection.
+ */
+
+ Watcher.prototype.beforeGet = function () {
+ Dep.target = this;
+ };
+
+ /**
+ * Add a dependency to this directive.
+ *
+ * @param {Dep} dep
+ */
+
+ Watcher.prototype.addDep = function (dep) {
+ var id = dep.id;
+ if (!this.newDepIds.has(id)) {
+ this.newDepIds.add(id);
+ this.newDeps.push(dep);
+ if (!this.depIds.has(id)) {
+ dep.addSub(this);
+ }
+ }
+ };
+
+ /**
+ * Clean up for dependency collection.
+ */
+
+ Watcher.prototype.afterGet = function () {
+ Dep.target = null;
+ var i = this.deps.length;
+ while (i--) {
+ var dep = this.deps[i];
+ if (!this.newDepIds.has(dep.id)) {
+ dep.removeSub(this);
+ }
+ }
+ var tmp = this.depIds;
+ this.depIds = this.newDepIds;
+ this.newDepIds = tmp;
+ this.newDepIds.clear();
+ tmp = this.deps;
+ this.deps = this.newDeps;
+ this.newDeps = tmp;
+ this.newDeps.length = 0;
+ };
+
+ /**
+ * Subscriber interface.
+ * Will be called when a dependency changes.
+ *
+ * @param {Boolean} shallow
+ */
+
+ Watcher.prototype.update = function (shallow) {
+ if (this.lazy) {
+ this.dirty = true;
+ } else if (this.sync || !config.async) {
+ this.run();
+ } else {
+ // if queued, only overwrite shallow with non-shallow,
+ // but not the other way around.
+ this.shallow = this.queued ? shallow ? this.shallow : false : !!shallow;
+ this.queued = true;
+ // record before-push error stack in debug mode
+ /* istanbul ignore if */
+ if ('development' !== 'production' && config.debug) {
+ this.prevError = new Error('[vue] async stack trace');
+ }
+ pushWatcher(this);
+ }
+ };
+
+ /**
+ * Batcher job interface.
+ * Will be called by the batcher.
+ */
+
+ Watcher.prototype.run = function () {
+ if (this.active) {
+ var value = this.get();
+ if (value !== this.value ||
+ // Deep watchers and watchers on Object/Arrays should fire even
+ // when the value is the same, because the value may
+ // have mutated; but only do so if this is a
+ // non-shallow update (caused by a vm digest).
+ (isObject(value) || this.deep) && !this.shallow) {
+ // set new value
+ var oldValue = this.value;
+ this.value = value;
+ // in debug + async mode, when a watcher callbacks
+ // throws, we also throw the saved before-push error
+ // so the full cross-tick stack trace is available.
+ var prevError = this.prevError;
+ /* istanbul ignore if */
+ if ('development' !== 'production' && config.debug && prevError) {
+ this.prevError = null;
+ try {
+ this.cb.call(this.vm, value, oldValue);
+ } catch (e) {
+ nextTick(function () {
+ throw prevError;
+ }, 0);
+ throw e;
+ }
+ } else {
+ this.cb.call(this.vm, value, oldValue);
+ }
+ }
+ this.queued = this.shallow = false;
+ }
+ };
+
+ /**
+ * Evaluate the value of the watcher.
+ * This only gets called for lazy watchers.
+ */
+
+ Watcher.prototype.evaluate = function () {
+ // avoid overwriting another watcher that is being
+ // collected.
+ var current = Dep.target;
+ this.value = this.get();
+ this.dirty = false;
+ Dep.target = current;
+ };
+
+ /**
+ * Depend on all deps collected by this watcher.
+ */
+
+ Watcher.prototype.depend = function () {
+ var i = this.deps.length;
+ while (i--) {
+ this.deps[i].depend();
+ }
+ };
+
+ /**
+ * Remove self from all dependencies' subcriber list.
+ */
+
+ Watcher.prototype.teardown = function () {
+ if (this.active) {
+ // remove self from vm's watcher list
+ // this is a somewhat expensive operation so we skip it
+ // if the vm is being destroyed or is performing a v-for
+ // re-render (the watcher list is then filtered by v-for).
+ if (!this.vm._isBeingDestroyed && !this.vm._vForRemoving) {
+ this.vm._watchers.$remove(this);
+ }
+ var i = this.deps.length;
+ while (i--) {
+ this.deps[i].removeSub(this);
+ }
+ this.active = false;
+ this.vm = this.cb = this.value = null;
+ }
+ };
+
+ /**
+ * Recrusively traverse an object to evoke all converted
+ * getters, so that every nested property inside the object
+ * is collected as a "deep" dependency.
+ *
+ * @param {*} val
+ */
+
+ var seenObjects = new _Set();
+ function traverse(val, seen) {
+ var i = undefined,
+ keys = undefined;
+ if (!seen) {
+ seen = seenObjects;
+ seen.clear();
+ }
+ var isA = isArray(val);
+ var isO = isObject(val);
+ if ((isA || isO) && Object.isExtensible(val)) {
+ if (val.__ob__) {
+ var depId = val.__ob__.dep.id;
+ if (seen.has(depId)) {
+ return;
+ } else {
+ seen.add(depId);
+ }
+ }
+ if (isA) {
+ i = val.length;
+ while (i--) traverse(val[i], seen);
+ } else if (isO) {
+ keys = Object.keys(val);
+ i = keys.length;
+ while (i--) traverse(val[keys[i]], seen);
+ }
+ }
+ }
+
+ var text$1 = {
+
+ bind: function bind() {
+ this.attr = this.el.nodeType === 3 ? 'data' : 'textContent';
+ },
+
+ update: function update(value) {
+ this.el[this.attr] = _toString(value);
+ }
+ };
+
+ var templateCache = new Cache(1000);
+ var idSelectorCache = new Cache(1000);
+
+ var map = {
+ efault: [0, '', ''],
+ legend: [1, '<fieldset>', '</fieldset>'],
+ tr: [2, '<table><tbody>', '</tbody></table>'],
+ col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>']
+ };
+
+ map.td = map.th = [3, '<table><tbody><tr>', '</tr></tbody></table>'];
+
+ map.option = map.optgroup = [1, '<select multiple="multiple">', '</select>'];
+
+ map.thead = map.tbody = map.colgroup = map.caption = map.tfoot = [1, '<table>', '</table>'];
+
+ map.g = map.defs = map.symbol = map.use = map.image = map.text = map.circle = map.ellipse = map.line = map.path = map.polygon = map.polyline = map.rect = [1, '<svg ' + 'xmlns="http://www.w3.org/2000/svg" ' + 'xmlns:xlink="http://www.w3.org/1999/xlink" ' + 'xmlns:ev="http://www.w3.org/2001/xml-events"' + 'version="1.1">', '</svg>'];
+
+ /**
+ * Check if a node is a supported template node with a
+ * DocumentFragment content.
+ *
+ * @param {Node} node
+ * @return {Boolean}
+ */
+
+ function isRealTemplate(node) {
+ return isTemplate(node) && isFragment(node.content);
+ }
+
+ var tagRE$1 = /<([\w:-]+)/;
+ var entityRE = /&#?\w+?;/;
+ var commentRE = /<!--/;
+
+ /**
+ * Convert a string template to a DocumentFragment.
+ * Determines correct wrapping by tag types. Wrapping
+ * strategy found in jQuery & component/domify.
+ *
+ * @param {String} templateString
+ * @param {Boolean} raw
+ * @return {DocumentFragment}
+ */
+
+ function stringToFragment(templateString, raw) {
+ // try a cache hit first
+ var cacheKey = raw ? templateString : templateString.trim();
+ var hit = templateCache.get(cacheKey);
+ if (hit) {
+ return hit;
+ }
+
+ var frag = document.createDocumentFragment();
+ var tagMatch = templateString.match(tagRE$1);
+ var entityMatch = entityRE.test(templateString);
+ var commentMatch = commentRE.test(templateString);
+
+ if (!tagMatch && !entityMatch && !commentMatch) {
+ // text only, return a single text node.
+ frag.appendChild(document.createTextNode(templateString));
+ } else {
+ var tag = tagMatch && tagMatch[1];
+ var wrap = map[tag] || map.efault;
+ var depth = wrap[0];
+ var prefix = wrap[1];
+ var suffix = wrap[2];
+ var node = document.createElement('div');
+
+ node.innerHTML = prefix + templateString + suffix;
+ while (depth--) {
+ node = node.lastChild;
+ }
+
+ var child;
+ /* eslint-disable no-cond-assign */
+ while (child = node.firstChild) {
+ /* eslint-enable no-cond-assign */
+ frag.appendChild(child);
+ }
+ }
+ if (!raw) {
+ trimNode(frag);
+ }
+ templateCache.put(cacheKey, frag);
+ return frag;
+ }
+
+ /**
+ * Convert a template node to a DocumentFragment.
+ *
+ * @param {Node} node
+ * @return {DocumentFragment}
+ */
+
+ function nodeToFragment(node) {
+ // if its a template tag and the browser supports it,
+ // its content is already a document fragment. However, iOS Safari has
+ // bug when using directly cloned template content with touch
+ // events and can cause crashes when the nodes are removed from DOM, so we
+ // have to treat template elements as string templates. (#2805)
+ /* istanbul ignore if */
+ if (isRealTemplate(node)) {
+ return stringToFragment(node.innerHTML);
+ }
+ // script template
+ if (node.tagName === 'SCRIPT') {
+ return stringToFragment(node.textContent);
+ }
+ // normal node, clone it to avoid mutating the original
+ var clonedNode = cloneNode(node);
+ var frag = document.createDocumentFragment();
+ var child;
+ /* eslint-disable no-cond-assign */
+ while (child = clonedNode.firstChild) {
+ /* eslint-enable no-cond-assign */
+ frag.appendChild(child);
+ }
+ trimNode(frag);
+ return frag;
+ }
+
+ // Test for the presence of the Safari template cloning bug
+ // https://bugs.webkit.org/showug.cgi?id=137755
+ var hasBrokenTemplate = (function () {
+ /* istanbul ignore else */
+ if (inBrowser) {
+ var a = document.createElement('div');
+ a.innerHTML = '<template>1</template>';
+ return !a.cloneNode(true).firstChild.innerHTML;
+ } else {
+ return false;
+ }
+ })();
+
+ // Test for IE10/11 textarea placeholder clone bug
+ var hasTextareaCloneBug = (function () {
+ /* istanbul ignore else */
+ if (inBrowser) {
+ var t = document.createElement('textarea');
+ t.placeholder = 't';
+ return t.cloneNode(true).value === 't';
+ } else {
+ return false;
+ }
+ })();
+
+ /**
+ * 1. Deal with Safari cloning nested <template> bug by
+ * manually cloning all template instances.
+ * 2. Deal with IE10/11 textarea placeholder bug by setting
+ * the correct value after cloning.
+ *
+ * @param {Element|DocumentFragment} node
+ * @return {Element|DocumentFragment}
+ */
+
+ function cloneNode(node) {
+ /* istanbul ignore if */
+ if (!node.querySelectorAll) {
+ return node.cloneNode();
+ }
+ var res = node.cloneNode(true);
+ var i, original, cloned;
+ /* istanbul ignore if */
+ if (hasBrokenTemplate) {
+ var tempClone = res;
+ if (isRealTemplate(node)) {
+ node = node.content;
+ tempClone = res.content;
+ }
+ original = node.querySelectorAll('template');
+ if (original.length) {
+ cloned = tempClone.querySelectorAll('template');
+ i = cloned.length;
+ while (i--) {
+ cloned[i].parentNode.replaceChild(cloneNode(original[i]), cloned[i]);
+ }
+ }
+ }
+ /* istanbul ignore if */
+ if (hasTextareaCloneBug) {
+ if (node.tagName === 'TEXTAREA') {
+ res.value = node.value;
+ } else {
+ original = node.querySelectorAll('textarea');
+ if (original.length) {
+ cloned = res.querySelectorAll('textarea');
+ i = cloned.length;
+ while (i--) {
+ cloned[i].value = original[i].value;
+ }
+ }
+ }
+ }
+ return res;
+ }
+
+ /**
+ * Process the template option and normalizes it into a
+ * a DocumentFragment that can be used as a partial or a
+ * instance template.
+ *
+ * @param {*} template
+ * Possible values include:
+ * - DocumentFragment object
+ * - Node object of type Template
+ * - id selector: '#some-template-id'
+ * - template string: '<div><span>{{msg}}</span></div>'
+ * @param {Boolean} shouldClone
+ * @param {Boolean} raw
+ * inline HTML interpolation. Do not check for id
+ * selector and keep whitespace in the string.
+ * @return {DocumentFragment|undefined}
+ */
+
+ function parseTemplate(template, shouldClone, raw) {
+ var node, frag;
+
+ // if the template is already a document fragment,
+ // do nothing
+ if (isFragment(template)) {
+ trimNode(template);
+ return shouldClone ? cloneNode(template) : template;
+ }
+
+ if (typeof template === 'string') {
+ // id selector
+ if (!raw && template.charAt(0) === '#') {
+ // id selector can be cached too
+ frag = idSelectorCache.get(template);
+ if (!frag) {
+ node = document.getElementById(template.slice(1));
+ if (node) {
+ frag = nodeToFragment(node);
+ // save selector to cache
+ idSelectorCache.put(template, frag);
+ }
+ }
+ } else {
+ // normal string template
+ frag = stringToFragment(template, raw);
+ }
+ } else if (template.nodeType) {
+ // a direct node
+ frag = nodeToFragment(template);
+ }
+
+ return frag && shouldClone ? cloneNode(frag) : frag;
+ }
+
+var template = Object.freeze({
+ cloneNode: cloneNode,
+ parseTemplate: parseTemplate
+ });
+
+ var html = {
+
+ bind: function bind() {
+ // a comment node means this is a binding for
+ // {{{ inline unescaped html }}}
+ if (this.el.nodeType === 8) {
+ // hold nodes
+ this.nodes = [];
+ // replace the placeholder with proper anchor
+ this.anchor = createAnchor('v-html');
+ replace(this.el, this.anchor);
+ }
+ },
+
+ update: function update(value) {
+ value = _toString(value);
+ if (this.nodes) {
+ this.swap(value);
+ } else {
+ this.el.innerHTML = value;
+ }
+ },
+
+ swap: function swap(value) {
+ // remove old nodes
+ var i = this.nodes.length;
+ while (i--) {
+ remove(this.nodes[i]);
+ }
+ // convert new value to a fragment
+ // do not attempt to retrieve from id selector
+ var frag = parseTemplate(value, true, true);
+ // save a reference to these nodes so we can remove later
+ this.nodes = toArray(frag.childNodes);
+ before(frag, this.anchor);
+ }
+ };
+
+ /**
+ * Abstraction for a partially-compiled fragment.
+ * Can optionally compile content with a child scope.
+ *
+ * @param {Function} linker
+ * @param {Vue} vm
+ * @param {DocumentFragment} frag
+ * @param {Vue} [host]
+ * @param {Object} [scope]
+ * @param {Fragment} [parentFrag]
+ */
+ function Fragment(linker, vm, frag, host, scope, parentFrag) {
+ this.children = [];
+ this.childFrags = [];
+ this.vm = vm;
+ this.scope = scope;
+ this.inserted = false;
+ this.parentFrag = parentFrag;
+ if (parentFrag) {
+ parentFrag.childFrags.push(this);
+ }
+ this.unlink = linker(vm, frag, host, scope, this);
+ var single = this.single = frag.childNodes.length === 1 &&
+ // do not go single mode if the only node is an anchor
+ !frag.childNodes[0].__v_anchor;
+ if (single) {
+ this.node = frag.childNodes[0];
+ this.before = singleBefore;
+ this.remove = singleRemove;
+ } else {
+ this.node = createAnchor('fragment-start');
+ this.end = createAnchor('fragment-end');
+ this.frag = frag;
+ prepend(this.node, frag);
+ frag.appendChild(this.end);
+ this.before = multiBefore;
+ this.remove = multiRemove;
+ }
+ this.node.__v_frag = this;
+ }
+
+ /**
+ * Call attach/detach for all components contained within
+ * this fragment. Also do so recursively for all child
+ * fragments.
+ *
+ * @param {Function} hook
+ */
+
+ Fragment.prototype.callHook = function (hook) {
+ var i, l;
+ for (i = 0, l = this.childFrags.length; i < l; i++) {
+ this.childFrags[i].callHook(hook);
+ }
+ for (i = 0, l = this.children.length; i < l; i++) {
+ hook(this.children[i]);
+ }
+ };
+
+ /**
+ * Insert fragment before target, single node version
+ *
+ * @param {Node} target
+ * @param {Boolean} withTransition
+ */
+
+ function singleBefore(target, withTransition) {
+ this.inserted = true;
+ var method = withTransition !== false ? beforeWithTransition : before;
+ method(this.node, target, this.vm);
+ if (inDoc(this.node)) {
+ this.callHook(attach);
+ }
+ }
+
+ /**
+ * Remove fragment, single node version
+ */
+
+ function singleRemove() {
+ this.inserted = false;
+ var shouldCallRemove = inDoc(this.node);
+ var self = this;
+ this.beforeRemove();
+ removeWithTransition(this.node, this.vm, function () {
+ if (shouldCallRemove) {
+ self.callHook(detach);
+ }
+ self.destroy();
+ });
+ }
+
+ /**
+ * Insert fragment before target, multi-nodes version
+ *
+ * @param {Node} target
+ * @param {Boolean} withTransition
+ */
+
+ function multiBefore(target, withTransition) {
+ this.inserted = true;
+ var vm = this.vm;
+ var method = withTransition !== false ? beforeWithTransition : before;
+ mapNodeRange(this.node, this.end, function (node) {
+ method(node, target, vm);
+ });
+ if (inDoc(this.node)) {
+ this.callHook(attach);
+ }
+ }
+
+ /**
+ * Remove fragment, multi-nodes version
+ */
+
+ function multiRemove() {
+ this.inserted = false;
+ var self = this;
+ var shouldCallRemove = inDoc(this.node);
+ this.beforeRemove();
+ removeNodeRange(this.node, this.end, this.vm, this.frag, function () {
+ if (shouldCallRemove) {
+ self.callHook(detach);
+ }
+ self.destroy();
+ });
+ }
+
+ /**
+ * Prepare the fragment for removal.
+ */
+
+ Fragment.prototype.beforeRemove = function () {
+ var i, l;
+ for (i = 0, l = this.childFrags.length; i < l; i++) {
+ // call the same method recursively on child
+ // fragments, depth-first
+ this.childFrags[i].beforeRemove(false);
+ }
+ for (i = 0, l = this.children.length; i < l; i++) {
+ // Call destroy for all contained instances,
+ // with remove:false and defer:true.
+ // Defer is necessary because we need to
+ // keep the children to call detach hooks
+ // on them.
+ this.children[i].$destroy(false, true);
+ }
+ var dirs = this.unlink.dirs;
+ for (i = 0, l = dirs.length; i < l; i++) {
+ // disable the watchers on all the directives
+ // so that the rendered content stays the same
+ // during removal.
+ dirs[i]._watcher && dirs[i]._watcher.teardown();
+ }
+ };
+
+ /**
+ * Destroy the fragment.
+ */
+
+ Fragment.prototype.destroy = function () {
+ if (this.parentFrag) {
+ this.parentFrag.childFrags.$remove(this);
+ }
+ this.node.__v_frag = null;
+ this.unlink();
+ };
+
+ /**
+ * Call attach hook for a Vue instance.
+ *
+ * @param {Vue} child
+ */
+
+ function attach(child) {
+ if (!child._isAttached && inDoc(child.$el)) {
+ child._callHook('attached');
+ }
+ }
+
+ /**
+ * Call detach hook for a Vue instance.
+ *
+ * @param {Vue} child
+ */
+
+ function detach(child) {
+ if (child._isAttached && !inDoc(child.$el)) {
+ child._callHook('detached');
+ }
+ }
+
+ var linkerCache = new Cache(5000);
+
+ /**
+ * A factory that can be used to create instances of a
+ * fragment. Caches the compiled linker if possible.
+ *
+ * @param {Vue} vm
+ * @param {Element|String} el
+ */
+ function FragmentFactory(vm, el) {
+ this.vm = vm;
+ var template;
+ var isString = typeof el === 'string';
+ if (isString || isTemplate(el) && !el.hasAttribute('v-if')) {
+ template = parseTemplate(el, true);
+ } else {
+ template = document.createDocumentFragment();
+ template.appendChild(el);
+ }
+ this.template = template;
+ // linker can be cached, but only for components
+ var linker;
+ var cid = vm.constructor.cid;
+ if (cid > 0) {
+ var cacheId = cid + (isString ? el : getOuterHTML(el));
+ linker = linkerCache.get(cacheId);
+ if (!linker) {
+ linker = compile(template, vm.$options, true);
+ linkerCache.put(cacheId, linker);
+ }
+ } else {
+ linker = compile(template, vm.$options, true);
+ }
+ this.linker = linker;
+ }
+
+ /**
+ * Create a fragment instance with given host and scope.
+ *
+ * @param {Vue} host
+ * @param {Object} scope
+ * @param {Fragment} parentFrag
+ */
+
+ FragmentFactory.prototype.create = function (host, scope, parentFrag) {
+ var frag = cloneNode(this.template);
+ return new Fragment(this.linker, this.vm, frag, host, scope, parentFrag);
+ };
+
+ var ON = 700;
+ var MODEL = 800;
+ var BIND = 850;
+ var TRANSITION = 1100;
+ var EL = 1500;
+ var COMPONENT = 1500;
+ var PARTIAL = 1750;
+ var IF = 2100;
+ var FOR = 2200;
+ var SLOT = 2300;
+
+ var uid$3 = 0;
+
+ var vFor = {
+
+ priority: FOR,
+ terminal: true,
+
+ params: ['track-by', 'stagger', 'enter-stagger', 'leave-stagger'],
+
+ bind: function bind() {
+ // support "item in/of items" syntax
+ var inMatch = this.expression.match(/(.*) (?:in|of) (.*)/);
+ if (inMatch) {
+ var itMatch = inMatch[1].match(/\((.*),(.*)\)/);
+ if (itMatch) {
+ this.iterator = itMatch[1].trim();
+ this.alias = itMatch[2].trim();
+ } else {
+ this.alias = inMatch[1].trim();
+ }
+ this.expression = inMatch[2];
+ }
+
+ if (!this.alias) {
+ 'development' !== 'production' && warn('Invalid v-for expression "' + this.descriptor.raw + '": ' + 'alias is required.', this.vm);
+ return;
+ }
+
+ // uid as a cache identifier
+ this.id = '__v-for__' + ++uid$3;
+
+ // check if this is an option list,
+ // so that we know if we need to update the <select>'s
+ // v-model when the option list has changed.
+ // because v-model has a lower priority than v-for,
+ // the v-model is not bound here yet, so we have to
+ // retrive it in the actual updateModel() function.
+ var tag = this.el.tagName;
+ this.isOption = (tag === 'OPTION' || tag === 'OPTGROUP') && this.el.parentNode.tagName === 'SELECT';
+
+ // setup anchor nodes
+ this.start = createAnchor('v-for-start');
+ this.end = createAnchor('v-for-end');
+ replace(this.el, this.end);
+ before(this.start, this.end);
+
+ // cache
+ this.cache = Object.create(null);
+
+ // fragment factory
+ this.factory = new FragmentFactory(this.vm, this.el);
+ },
+
+ update: function update(data) {
+ this.diff(data);
+ this.updateRef();
+ this.updateModel();
+ },
+
+ /**
+ * Diff, based on new data and old data, determine the
+ * minimum amount of DOM manipulations needed to make the
+ * DOM reflect the new data Array.
+ *
+ * The algorithm diffs the new data Array by storing a
+ * hidden reference to an owner vm instance on previously
+ * seen data. This allows us to achieve O(n) which is
+ * better than a levenshtein distance based algorithm,
+ * which is O(m * n).
+ *
+ * @param {Array} data
+ */
+
+ diff: function diff(data) {
+ // check if the Array was converted from an Object
+ var item = data[0];
+ var convertedFromObject = this.fromObject = isObject(item) && hasOwn(item, '$key') && hasOwn(item, '$value');
+
+ var trackByKey = this.params.trackBy;
+ var oldFrags = this.frags;
+ var frags = this.frags = new Array(data.length);
+ var alias = this.alias;
+ var iterator = this.iterator;
+ var start = this.start;
+ var end = this.end;
+ var inDocument = inDoc(start);
+ var init = !oldFrags;
+ var i, l, frag, key, value, primitive;
+
+ // First pass, go through the new Array and fill up
+ // the new frags array. If a piece of data has a cached
+ // instance for it, we reuse it. Otherwise build a new
+ // instance.
+ for (i = 0, l = data.length; i < l; i++) {
+ item = data[i];
+ key = convertedFromObject ? item.$key : null;
+ value = convertedFromObject ? item.$value : item;
+ primitive = !isObject(value);
+ frag = !init && this.getCachedFrag(value, i, key);
+ if (frag) {
+ // reusable fragment
+ frag.reused = true;
+ // update $index
+ frag.scope.$index = i;
+ // update $key
+ if (key) {
+ frag.scope.$key = key;
+ }
+ // update iterator
+ if (iterator) {
+ frag.scope[iterator] = key !== null ? key : i;
+ }
+ // update data for track-by, object repeat &
+ // primitive values.
+ if (trackByKey || convertedFromObject || primitive) {
+ withoutConversion(function () {
+ frag.scope[alias] = value;
+ });
+ }
+ } else {
+ // new isntance
+ frag = this.create(value, alias, i, key);
+ frag.fresh = !init;
+ }
+ frags[i] = frag;
+ if (init) {
+ frag.before(end);
+ }
+ }
+
+ // we're done for the initial render.
+ if (init) {
+ return;
+ }
+
+ // Second pass, go through the old fragments and
+ // destroy those who are not reused (and remove them
+ // from cache)
+ var removalIndex = 0;
+ var totalRemoved = oldFrags.length - frags.length;
+ // when removing a large number of fragments, watcher removal
+ // turns out to be a perf bottleneck, so we batch the watcher
+ // removals into a single filter call!
+ this.vm._vForRemoving = true;
+ for (i = 0, l = oldFrags.length; i < l; i++) {
+ frag = oldFrags[i];
+ if (!frag.reused) {
+ this.deleteCachedFrag(frag);
+ this.remove(frag, removalIndex++, totalRemoved, inDocument);
+ }
+ }
+ this.vm._vForRemoving = false;
+ if (removalIndex) {
+ this.vm._watchers = this.vm._watchers.filter(function (w) {
+ return w.active;
+ });
+ }
+
+ // Final pass, move/insert new fragments into the
+ // right place.
+ var targetPrev, prevEl, currentPrev;
+ var insertionIndex = 0;
+ for (i = 0, l = frags.length; i < l; i++) {
+ frag = frags[i];
+ // this is the frag that we should be after
+ targetPrev = frags[i - 1];
+ prevEl = targetPrev ? targetPrev.staggerCb ? targetPrev.staggerAnchor : targetPrev.end || targetPrev.node : start;
+ if (frag.reused && !frag.staggerCb) {
+ currentPrev = findPrevFrag(frag, start, this.id);
+ if (currentPrev !== targetPrev && (!currentPrev ||
+ // optimization for moving a single item.
+ // thanks to suggestions by @livoras in #1807
+ findPrevFrag(currentPrev, start, this.id) !== targetPrev)) {
+ this.move(frag, prevEl);
+ }
+ } else {
+ // new instance, or still in stagger.
+ // insert with updated stagger index.
+ this.insert(frag, insertionIndex++, prevEl, inDocument);
+ }
+ frag.reused = frag.fresh = false;
+ }
+ },
+
+ /**
+ * Create a new fragment instance.
+ *
+ * @param {*} value
+ * @param {String} alias
+ * @param {Number} index
+ * @param {String} [key]
+ * @return {Fragment}
+ */
+
+ create: function create(value, alias, index, key) {
+ var host = this._host;
+ // create iteration scope
+ var parentScope = this._scope || this.vm;
+ var scope = Object.create(parentScope);
+ // ref holder for the scope
+ scope.$refs = Object.create(parentScope.$refs);
+ scope.$els = Object.create(parentScope.$els);
+ // make sure point $parent to parent scope
+ scope.$parent = parentScope;
+ // for two-way binding on alias
+ scope.$forContext = this;
+ // define scope properties
+ // important: define the scope alias without forced conversion
+ // so that frozen data structures remain non-reactive.
+ withoutConversion(function () {
+ defineReactive(scope, alias, value);
+ });
+ defineReactive(scope, '$index', index);
+ if (key) {
+ defineReactive(scope, '$key', key);
+ } else if (scope.$key) {
+ // avoid accidental fallback
+ def(scope, '$key', null);
+ }
+ if (this.iterator) {
+ defineReactive(scope, this.iterator, key !== null ? key : index);
+ }
+ var frag = this.factory.create(host, scope, this._frag);
+ frag.forId = this.id;
+ this.cacheFrag(value, frag, index, key);
+ return frag;
+ },
+
+ /**
+ * Update the v-ref on owner vm.
+ */
+
+ updateRef: function updateRef() {
+ var ref = this.descriptor.ref;
+ if (!ref) return;
+ var hash = (this._scope || this.vm).$refs;
+ var refs;
+ if (!this.fromObject) {
+ refs = this.frags.map(findVmFromFrag);
+ } else {
+ refs = {};
+ this.frags.forEach(function (frag) {
+ refs[frag.scope.$key] = findVmFromFrag(frag);
+ });
+ }
+ hash[ref] = refs;
+ },
+
+ /**
+ * For option lists, update the containing v-model on
+ * parent <select>.
+ */
+
+ updateModel: function updateModel() {
+ if (this.isOption) {
+ var parent = this.start.parentNode;
+ var model = parent && parent.__v_model;
+ if (model) {
+ model.forceUpdate();
+ }
+ }
+ },
+
+ /**
+ * Insert a fragment. Handles staggering.
+ *
+ * @param {Fragment} frag
+ * @param {Number} index
+ * @param {Node} prevEl
+ * @param {Boolean} inDocument
+ */
+
+ insert: function insert(frag, index, prevEl, inDocument) {
+ if (frag.staggerCb) {
+ frag.staggerCb.cancel();
+ frag.staggerCb = null;
+ }
+ var staggerAmount = this.getStagger(frag, index, null, 'enter');
+ if (inDocument && staggerAmount) {
+ // create an anchor and insert it synchronously,
+ // so that we can resolve the correct order without
+ // worrying about some elements not inserted yet
+ var anchor = frag.staggerAnchor;
+ if (!anchor) {
+ anchor = frag.staggerAnchor = createAnchor('stagger-anchor');
+ anchor.__v_frag = frag;
+ }
+ after(anchor, prevEl);
+ var op = frag.staggerCb = cancellable(function () {
+ frag.staggerCb = null;
+ frag.before(anchor);
+ remove(anchor);
+ });
+ setTimeout(op, staggerAmount);
+ } else {
+ var target = prevEl.nextSibling;
+ /* istanbul ignore if */
+ if (!target) {
+ // reset end anchor position in case the position was messed up
+ // by an external drag-n-drop library.
+ after(this.end, prevEl);
+ target = this.end;
+ }
+ frag.before(target);
+ }
+ },
+
+ /**
+ * Remove a fragment. Handles staggering.
+ *
+ * @param {Fragment} frag
+ * @param {Number} index
+ * @param {Number} total
+ * @param {Boolean} inDocument
+ */
+
+ remove: function remove(frag, index, total, inDocument) {
+ if (frag.staggerCb) {
+ frag.staggerCb.cancel();
+ frag.staggerCb = null;
+ // it's not possible for the same frag to be removed
+ // twice, so if we have a pending stagger callback,
+ // it means this frag is queued for enter but removed
+ // before its transition started. Since it is already
+ // destroyed, we can just leave it in detached state.
+ return;
+ }
+ var staggerAmount = this.getStagger(frag, index, total, 'leave');
+ if (inDocument && staggerAmount) {
+ var op = frag.staggerCb = cancellable(function () {
+ frag.staggerCb = null;
+ frag.remove();
+ });
+ setTimeout(op, staggerAmount);
+ } else {
+ frag.remove();
+ }
+ },
+
+ /**
+ * Move a fragment to a new position.
+ * Force no transition.
+ *
+ * @param {Fragment} frag
+ * @param {Node} prevEl
+ */
+
+ move: function move(frag, prevEl) {
+ // fix a common issue with Sortable:
+ // if prevEl doesn't have nextSibling, this means it's
+ // been dragged after the end anchor. Just re-position
+ // the end anchor to the end of the container.
+ /* istanbul ignore if */
+ if (!prevEl.nextSibling) {
+ this.end.parentNode.appendChild(this.end);
+ }
+ frag.before(prevEl.nextSibling, false);
+ },
+
+ /**
+ * Cache a fragment using track-by or the object key.
+ *
+ * @param {*} value
+ * @param {Fragment} frag
+ * @param {Number} index
+ * @param {String} [key]
+ */
+
+ cacheFrag: function cacheFrag(value, frag, index, key) {
+ var trackByKey = this.params.trackBy;
+ var cache = this.cache;
+ var primitive = !isObject(value);
+ var id;
+ if (key || trackByKey || primitive) {
+ id = getTrackByKey(index, key, value, trackByKey);
+ if (!cache[id]) {
+ cache[id] = frag;
+ } else if (trackByKey !== '$index') {
+ 'development' !== 'production' && this.warnDuplicate(value);
+ }
+ } else {
+ id = this.id;
+ if (hasOwn(value, id)) {
+ if (value[id] === null) {
+ value[id] = frag;
+ } else {
+ 'development' !== 'production' && this.warnDuplicate(value);
+ }
+ } else if (Object.isExtensible(value)) {
+ def(value, id, frag);
+ } else if ('development' !== 'production') {
+ warn('Frozen v-for objects cannot be automatically tracked, make sure to ' + 'provide a track-by key.');
+ }
+ }
+ frag.raw = value;
+ },
+
+ /**
+ * Get a cached fragment from the value/index/key
+ *
+ * @param {*} value
+ * @param {Number} index
+ * @param {String} key
+ * @return {Fragment}
+ */
+
+ getCachedFrag: function getCachedFrag(value, index, key) {
+ var trackByKey = this.params.trackBy;
+ var primitive = !isObject(value);
+ var frag;
+ if (key || trackByKey || primitive) {
+ var id = getTrackByKey(index, key, value, trackByKey);
+ frag = this.cache[id];
+ } else {
+ frag = value[this.id];
+ }
+ if (frag && (frag.reused || frag.fresh)) {
+ 'development' !== 'production' && this.warnDuplicate(value);
+ }
+ return frag;
+ },
+
+ /**
+ * Delete a fragment from cache.
+ *
+ * @param {Fragment} frag
+ */
+
+ deleteCachedFrag: function deleteCachedFrag(frag) {
+ var value = frag.raw;
+ var trackByKey = this.params.trackBy;
+ var scope = frag.scope;
+ var index = scope.$index;
+ // fix #948: avoid accidentally fall through to
+ // a parent repeater which happens to have $key.
+ var key = hasOwn(scope, '$key') && scope.$key;
+ var primitive = !isObject(value);
+ if (trackByKey || key || primitive) {
+ var id = getTrackByKey(index, key, value, trackByKey);
+ this.cache[id] = null;
+ } else {
+ value[this.id] = null;
+ frag.raw = null;
+ }
+ },
+
+ /**
+ * Get the stagger amount for an insertion/removal.
+ *
+ * @param {Fragment} frag
+ * @param {Number} index
+ * @param {Number} total
+ * @param {String} type
+ */
+
+ getStagger: function getStagger(frag, index, total, type) {
+ type = type + 'Stagger';
+ var trans = frag.node.__v_trans;
+ var hooks = trans && trans.hooks;
+ var hook = hooks && (hooks[type] || hooks.stagger);
+ return hook ? hook.call(frag, index, total) : index * parseInt(this.params[type] || this.params.stagger, 10);
+ },
+
+ /**
+ * Pre-process the value before piping it through the
+ * filters. This is passed to and called by the watcher.
+ */
+
+ _preProcess: function _preProcess(value) {
+ // regardless of type, store the un-filtered raw value.
+ this.rawValue = value;
+ return value;
+ },
+
+ /**
+ * Post-process the value after it has been piped through
+ * the filters. This is passed to and called by the watcher.
+ *
+ * It is necessary for this to be called during the
+ * watcher's dependency collection phase because we want
+ * the v-for to update when the source Object is mutated.
+ */
+
+ _postProcess: function _postProcess(value) {
+ if (isArray(value)) {
+ return value;
+ } else if (isPlainObject(value)) {
+ // convert plain object to array.
+ var keys = Object.keys(value);
+ var i = keys.length;
+ var res = new Array(i);
+ var key;
+ while (i--) {
+ key = keys[i];
+ res[i] = {
+ $key: key,
+ $value: value[key]
+ };
+ }
+ return res;
+ } else {
+ if (typeof value === 'number' && !isNaN(value)) {
+ value = range(value);
+ }
+ return value || [];
+ }
+ },
+
+ unbind: function unbind() {
+ if (this.descriptor.ref) {
+ (this._scope || this.vm).$refs[this.descriptor.ref] = null;
+ }
+ if (this.frags) {
+ var i = this.frags.length;
+ var frag;
+ while (i--) {
+ frag = this.frags[i];
+ this.deleteCachedFrag(frag);
+ frag.destroy();
+ }
+ }
+ }
+ };
+
+ /**
+ * Helper to find the previous element that is a fragment
+ * anchor. This is necessary because a destroyed frag's
+ * element could still be lingering in the DOM before its
+ * leaving transition finishes, but its inserted flag
+ * should have been set to false so we can skip them.
+ *
+ * If this is a block repeat, we want to make sure we only
+ * return frag that is bound to this v-for. (see #929)
+ *
+ * @param {Fragment} frag
+ * @param {Comment|Text} anchor
+ * @param {String} id
+ * @return {Fragment}
+ */
+
+ function findPrevFrag(frag, anchor, id) {
+ var el = frag.node.previousSibling;
+ /* istanbul ignore if */
+ if (!el) return;
+ frag = el.__v_frag;
+ while ((!frag || frag.forId !== id || !frag.inserted) && el !== anchor) {
+ el = el.previousSibling;
+ /* istanbul ignore if */
+ if (!el) return;
+ frag = el.__v_frag;
+ }
+ return frag;
+ }
+
+ /**
+ * Find a vm from a fragment.
+ *
+ * @param {Fragment} frag
+ * @return {Vue|undefined}
+ */
+
+ function findVmFromFrag(frag) {
+ var node = frag.node;
+ // handle multi-node frag
+ if (frag.end) {
+ while (!node.__vue__ && node !== frag.end && node.nextSibling) {
+ node = node.nextSibling;
+ }
+ }
+ return node.__vue__;
+ }
+
+ /**
+ * Create a range array from given number.
+ *
+ * @param {Number} n
+ * @return {Array}
+ */
+
+ function range(n) {
+ var i = -1;
+ var ret = new Array(Math.floor(n));
+ while (++i < n) {
+ ret[i] = i;
+ }
+ return ret;
+ }
+
+ /**
+ * Get the track by key for an item.
+ *
+ * @param {Number} index
+ * @param {String} key
+ * @param {*} value
+ * @param {String} [trackByKey]
+ */
+
+ function getTrackByKey(index, key, value, trackByKey) {
+ return trackByKey ? trackByKey === '$index' ? index : trackByKey.charAt(0).match(/\w/) ? getPath(value, trackByKey) : value[trackByKey] : key || value;
+ }
+
+ if ('development' !== 'production') {
+ vFor.warnDuplicate = function (value) {
+ warn('Duplicate value found in v-for="' + this.descriptor.raw + '": ' + JSON.stringify(value) + '. Use track-by="$index" if ' + 'you are expecting duplicate values.', this.vm);
+ };
+ }
+
+ var vIf = {
+
+ priority: IF,
+ terminal: true,
+
+ bind: function bind() {
+ var el = this.el;
+ if (!el.__vue__) {
+ // check else block
+ var next = el.nextElementSibling;
+ if (next && getAttr(next, 'v-else') !== null) {
+ remove(next);
+ this.elseEl = next;
+ }
+ // check main block
+ this.anchor = createAnchor('v-if');
+ replace(el, this.anchor);
+ } else {
+ 'development' !== 'production' && warn('v-if="' + this.expression + '" cannot be ' + 'used on an instance root element.', this.vm);
+ this.invalid = true;
+ }
+ },
+
+ update: function update(value) {
+ if (this.invalid) return;
+ if (value) {
+ if (!this.frag) {
+ this.insert();
+ }
+ } else {
+ this.remove();
+ }
+ },
+
+ insert: function insert() {
+ if (this.elseFrag) {
+ this.elseFrag.remove();
+ this.elseFrag = null;
+ }
+ // lazy init factory
+ if (!this.factory) {
+ this.factory = new FragmentFactory(this.vm, this.el);
+ }
+ this.frag = this.factory.create(this._host, this._scope, this._frag);
+ this.frag.before(this.anchor);
+ },
+
+ remove: function remove() {
+ if (this.frag) {
+ this.frag.remove();
+ this.frag = null;
+ }
+ if (this.elseEl && !this.elseFrag) {
+ if (!this.elseFactory) {
+ this.elseFactory = new FragmentFactory(this.elseEl._context || this.vm, this.elseEl);
+ }
+ this.elseFrag = this.elseFactory.create(this._host, this._scope, this._frag);
+ this.elseFrag.before(this.anchor);
+ }
+ },
+
+ unbind: function unbind() {
+ if (this.frag) {
+ this.frag.destroy();
+ }
+ if (this.elseFrag) {
+ this.elseFrag.destroy();
+ }
+ }
+ };
+
+ var show = {
+
+ bind: function bind() {
+ // check else block
+ var next = this.el.nextElementSibling;
+ if (next && getAttr(next, 'v-else') !== null) {
+ this.elseEl = next;
+ }
+ },
+
+ update: function update(value) {
+ this.apply(this.el, value);
+ if (this.elseEl) {
+ this.apply(this.elseEl, !value);
+ }
+ },
+
+ apply: function apply(el, value) {
+ if (inDoc(el)) {
+ applyTransition(el, value ? 1 : -1, toggle, this.vm);
+ } else {
+ toggle();
+ }
+ function toggle() {
+ el.style.display = value ? '' : 'none';
+ }
+ }
+ };
+
+ var text$2 = {
+
+ bind: function bind() {
+ var self = this;
+ var el = this.el;
+ var isRange = el.type === 'range';
+ var lazy = this.params.lazy;
+ var number = this.params.number;
+ var debounce = this.params.debounce;
+
+ // handle composition events.
+ // http://blog.evanyou.me/2014/01/03/composition-event/
+ // skip this for Android because it handles composition
+ // events quite differently. Android doesn't trigger
+ // composition events for language input methods e.g.
+ // Chinese, but instead triggers them for spelling
+ // suggestions... (see Discussion/#162)
+ var composing = false;
+ if (!isAndroid && !isRange) {
+ this.on('compositionstart', function () {
+ composing = true;
+ });
+ this.on('compositionend', function () {
+ composing = false;
+ // in IE11 the "compositionend" event fires AFTER
+ // the "input" event, so the input handler is blocked
+ // at the end... have to call it here.
+ //
+ // #1327: in lazy mode this is unecessary.
+ if (!lazy) {
+ self.listener();
+ }
+ });
+ }
+
+ // prevent messing with the input when user is typing,
+ // and force update on blur.
+ this.focused = false;
+ if (!isRange && !lazy) {
+ this.on('focus', function () {
+ self.focused = true;
+ });
+ this.on('blur', function () {
+ self.focused = false;
+ // do not sync value after fragment removal (#2017)
+ if (!self._frag || self._frag.inserted) {
+ self.rawListener();
+ }
+ });
+ }
+
+ // Now attach the main listener
+ this.listener = this.rawListener = function () {
+ if (composing || !self._bound) {
+ return;
+ }
+ var val = number || isRange ? toNumber(el.value) : el.value;
+ self.set(val);
+ // force update on next tick to avoid lock & same value
+ // also only update when user is not typing
+ nextTick(function () {
+ if (self._bound && !self.focused) {
+ self.update(self._watcher.value);
+ }
+ });
+ };
+
+ // apply debounce
+ if (debounce) {
+ this.listener = _debounce(this.listener, debounce);
+ }
+
+ // Support jQuery events, since jQuery.trigger() doesn't
+ // trigger native events in some cases and some plugins
+ // rely on $.trigger()
+ //
+ // We want to make sure if a listener is attached using
+ // jQuery, it is also removed with jQuery, that's why
+ // we do the check for each directive instance and
+ // store that check result on itself. This also allows
+ // easier test coverage control by unsetting the global
+ // jQuery variable in tests.
+ this.hasjQuery = typeof jQuery === 'function';
+ if (this.hasjQuery) {
+ var method = jQuery.fn.on ? 'on' : 'bind';
+ jQuery(el)[method]('change', this.rawListener);
+ if (!lazy) {
+ jQuery(el)[method]('input', this.listener);
+ }
+ } else {
+ this.on('change', this.rawListener);
+ if (!lazy) {
+ this.on('input', this.listener);
+ }
+ }
+
+ // IE9 doesn't fire input event on backspace/del/cut
+ if (!lazy && isIE9) {
+ this.on('cut', function () {
+ nextTick(self.listener);
+ });
+ this.on('keyup', function (e) {
+ if (e.keyCode === 46 || e.keyCode === 8) {
+ self.listener();
+ }
+ });
+ }
+
+ // set initial value if present
+ if (el.hasAttribute('value') || el.tagName === 'TEXTAREA' && el.value.trim()) {
+ this.afterBind = this.listener;
+ }
+ },
+
+ update: function update(value) {
+ // #3029 only update when the value changes. This prevent
+ // browsers from overwriting values like selectionStart
+ value = _toString(value);
+ if (value !== this.el.value) this.el.value = value;
+ },
+
+ unbind: function unbind() {
+ var el = this.el;
+ if (this.hasjQuery) {
+ var method = jQuery.fn.off ? 'off' : 'unbind';
+ jQuery(el)[method]('change', this.listener);
+ jQuery(el)[method]('input', this.listener);
+ }
+ }
+ };
+
+ var radio = {
+
+ bind: function bind() {
+ var self = this;
+ var el = this.el;
+
+ this.getValue = function () {
+ // value overwrite via v-bind:value
+ if (el.hasOwnProperty('_value')) {
+ return el._value;
+ }
+ var val = el.value;
+ if (self.params.number) {
+ val = toNumber(val);
+ }
+ return val;
+ };
+
+ this.listener = function () {
+ self.set(self.getValue());
+ };
+ this.on('change', this.listener);
+
+ if (el.hasAttribute('checked')) {
+ this.afterBind = this.listener;
+ }
+ },
+
+ update: function update(value) {
+ this.el.checked = looseEqual(value, this.getValue());
+ }
+ };
+
+ var select = {
+
+ bind: function bind() {
+ var _this = this;
+
+ var self = this;
+ var el = this.el;
+
+ // method to force update DOM using latest value.
+ this.forceUpdate = function () {
+ if (self._watcher) {
+ self.update(self._watcher.get());
+ }
+ };
+
+ // check if this is a multiple select
+ var multiple = this.multiple = el.hasAttribute('multiple');
+
+ // attach listener
+ this.listener = function () {
+ var value = getValue(el, multiple);
+ value = self.params.number ? isArray(value) ? value.map(toNumber) : toNumber(value) : value;
+ self.set(value);
+ };
+ this.on('change', this.listener);
+
+ // if has initial value, set afterBind
+ var initValue = getValue(el, multiple, true);
+ if (multiple && initValue.length || !multiple && initValue !== null) {
+ this.afterBind = this.listener;
+ }
+
+ // All major browsers except Firefox resets
+ // selectedIndex with value -1 to 0 when the element
+ // is appended to a new parent, therefore we have to
+ // force a DOM update whenever that happens...
+ this.vm.$on('hook:attached', function () {
+ nextTick(_this.forceUpdate);
+ });
+ if (!inDoc(el)) {
+ nextTick(this.forceUpdate);
+ }
+ },
+
+ update: function update(value) {
+ var el = this.el;
+ el.selectedIndex = -1;
+ var multi = this.multiple && isArray(value);
+ var options = el.options;
+ var i = options.length;
+ var op, val;
+ while (i--) {
+ op = options[i];
+ val = op.hasOwnProperty('_value') ? op._value : op.value;
+ /* eslint-disable eqeqeq */
+ op.selected = multi ? indexOf$1(value, val) > -1 : looseEqual(value, val);
+ /* eslint-enable eqeqeq */
+ }
+ },
+
+ unbind: function unbind() {
+ /* istanbul ignore next */
+ this.vm.$off('hook:attached', this.forceUpdate);
+ }
+ };
+
+ /**
+ * Get select value
+ *
+ * @param {SelectElement} el
+ * @param {Boolean} multi
+ * @param {Boolean} init
+ * @return {Array|*}
+ */
+
+ function getValue(el, multi, init) {
+ var res = multi ? [] : null;
+ var op, val, selected;
+ for (var i = 0, l = el.options.length; i < l; i++) {
+ op = el.options[i];
+ selected = init ? op.hasAttribute('selected') : op.selected;
+ if (selected) {
+ val = op.hasOwnProperty('_value') ? op._value : op.value;
+ if (multi) {
+ res.push(val);
+ } else {
+ return val;
+ }
+ }
+ }
+ return res;
+ }
+
+ /**
+ * Native Array.indexOf uses strict equal, but in this
+ * case we need to match string/numbers with custom equal.
+ *
+ * @param {Array} arr
+ * @param {*} val
+ */
+
+ function indexOf$1(arr, val) {
+ var i = arr.length;
+ while (i--) {
+ if (looseEqual(arr[i], val)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ var checkbox = {
+
+ bind: function bind() {
+ var self = this;
+ var el = this.el;
+
+ this.getValue = function () {
+ return el.hasOwnProperty('_value') ? el._value : self.params.number ? toNumber(el.value) : el.value;
+ };
+
+ function getBooleanValue() {
+ var val = el.checked;
+ if (val && el.hasOwnProperty('_trueValue')) {
+ return el._trueValue;
+ }
+ if (!val && el.hasOwnProperty('_falseValue')) {
+ return el._falseValue;
+ }
+ return val;
+ }
+
+ this.listener = function () {
+ var model = self._watcher.value;
+ if (isArray(model)) {
+ var val = self.getValue();
+ if (el.checked) {
+ if (indexOf(model, val) < 0) {
+ model.push(val);
+ }
+ } else {
+ model.$remove(val);
+ }
+ } else {
+ self.set(getBooleanValue());
+ }
+ };
+
+ this.on('change', this.listener);
+ if (el.hasAttribute('checked')) {
+ this.afterBind = this.listener;
+ }
+ },
+
+ update: function update(value) {
+ var el = this.el;
+ if (isArray(value)) {
+ el.checked = indexOf(value, this.getValue()) > -1;
+ } else {
+ if (el.hasOwnProperty('_trueValue')) {
+ el.checked = looseEqual(value, el._trueValue);
+ } else {
+ el.checked = !!value;
+ }
+ }
+ }
+ };
+
+ var handlers = {
+ text: text$2,
+ radio: radio,
+ select: select,
+ checkbox: checkbox
+ };
+
+ var model = {
+
+ priority: MODEL,
+ twoWay: true,
+ handlers: handlers,
+ params: ['lazy', 'number', 'debounce'],
+
+ /**
+ * Possible elements:
+ * <select>
+ * <textarea>
+ * <input type="*">
+ * - text
+ * - checkbox
+ * - radio
+ * - number
+ */
+
+ bind: function bind() {
+ // friendly warning...
+ this.checkFilters();
+ if (this.hasRead && !this.hasWrite) {
+ 'development' !== 'production' && warn('It seems you are using a read-only filter with ' + 'v-model="' + this.descriptor.raw + '". ' + 'You might want to use a two-way filter to ensure correct behavior.', this.vm);
+ }
+ var el = this.el;
+ var tag = el.tagName;
+ var handler;
+ if (tag === 'INPUT') {
+ handler = handlers[el.type] || handlers.text;
+ } else if (tag === 'SELECT') {
+ handler = handlers.select;
+ } else if (tag === 'TEXTAREA') {
+ handler = handlers.text;
+ } else {
+ 'development' !== 'production' && warn('v-model does not support element type: ' + tag, this.vm);
+ return;
+ }
+ el.__v_model = this;
+ handler.bind.call(this);
+ this.update = handler.update;
+ this._unbind = handler.unbind;
+ },
+
+ /**
+ * Check read/write filter stats.
+ */
+
+ checkFilters: function checkFilters() {
+ var filters = this.filters;
+ if (!filters) return;
+ var i = filters.length;
+ while (i--) {
+ var filter = resolveAsset(this.vm.$options, 'filters', filters[i].name);
+ if (typeof filter === 'function' || filter.read) {
+ this.hasRead = true;
+ }
+ if (filter.write) {
+ this.hasWrite = true;
+ }
+ }
+ },
+
+ unbind: function unbind() {
+ this.el.__v_model = null;
+ this._unbind && this._unbind();
+ }
+ };
+
+ // keyCode aliases
+ var keyCodes = {
+ esc: 27,
+ tab: 9,
+ enter: 13,
+ space: 32,
+ 'delete': [8, 46],
+ up: 38,
+ left: 37,
+ right: 39,
+ down: 40
+ };
+
+ function keyFilter(handler, keys) {
+ var codes = keys.map(function (key) {
+ var charCode = key.charCodeAt(0);
+ if (charCode > 47 && charCode < 58) {
+ return parseInt(key, 10);
+ }
+ if (key.length === 1) {
+ charCode = key.toUpperCase().charCodeAt(0);
+ if (charCode > 64 && charCode < 91) {
+ return charCode;
+ }
+ }
+ return keyCodes[key];
+ });
+ codes = [].concat.apply([], codes);
+ return function keyHandler(e) {
+ if (codes.indexOf(e.keyCode) > -1) {
+ return handler.call(this, e);
+ }
+ };
+ }
+
+ function stopFilter(handler) {
+ return function stopHandler(e) {
+ e.stopPropagation();
+ return handler.call(this, e);
+ };
+ }
+
+ function preventFilter(handler) {
+ return function preventHandler(e) {
+ e.preventDefault();
+ return handler.call(this, e);
+ };
+ }
+
+ function selfFilter(handler) {
+ return function selfHandler(e) {
+ if (e.target === e.currentTarget) {
+ return handler.call(this, e);
+ }
+ };
+ }
+
+ var on$1 = {
+
+ priority: ON,
+ acceptStatement: true,
+ keyCodes: keyCodes,
+
+ bind: function bind() {
+ // deal with iframes
+ if (this.el.tagName === 'IFRAME' && this.arg !== 'load') {
+ var self = this;
+ this.iframeBind = function () {
+ on(self.el.contentWindow, self.arg, self.handler, self.modifiers.capture);
+ };
+ this.on('load', this.iframeBind);
+ }
+ },
+
+ update: function update(handler) {
+ // stub a noop for v-on with no value,
+ // e.g. @mousedown.prevent
+ if (!this.descriptor.raw) {
+ handler = function () {};
+ }
+
+ if (typeof handler !== 'function') {
+ 'development' !== 'production' && warn('v-on:' + this.arg + '="' + this.expression + '" expects a function value, ' + 'got ' + handler, this.vm);
+ return;
+ }
+
+ // apply modifiers
+ if (this.modifiers.stop) {
+ handler = stopFilter(handler);
+ }
+ if (this.modifiers.prevent) {
+ handler = preventFilter(handler);
+ }
+ if (this.modifiers.self) {
+ handler = selfFilter(handler);
+ }
+ // key filter
+ var keys = Object.keys(this.modifiers).filter(function (key) {
+ return key !== 'stop' && key !== 'prevent' && key !== 'self' && key !== 'capture';
+ });
+ if (keys.length) {
+ handler = keyFilter(handler, keys);
+ }
+
+ this.reset();
+ this.handler = handler;
+
+ if (this.iframeBind) {
+ this.iframeBind();
+ } else {
+ on(this.el, this.arg, this.handler, this.modifiers.capture);
+ }
+ },
+
+ reset: function reset() {
+ var el = this.iframeBind ? this.el.contentWindow : this.el;
+ if (this.handler) {
+ off(el, this.arg, this.handler);
+ }
+ },
+
+ unbind: function unbind() {
+ this.reset();
+ }
+ };
+
+ var prefixes = ['-webkit-', '-moz-', '-ms-'];
+ var camelPrefixes = ['Webkit', 'Moz', 'ms'];
+ var importantRE = /!important;?$/;
+ var propCache = Object.create(null);
+
+ var testEl = null;
+
+ var style = {
+
+ deep: true,
+
+ update: function update(value) {
+ if (typeof value === 'string') {
+ this.el.style.cssText = value;
+ } else if (isArray(value)) {
+ this.handleObject(value.reduce(extend, {}));
+ } else {
+ this.handleObject(value || {});
+ }
+ },
+
+ handleObject: function handleObject(value) {
+ // cache object styles so that only changed props
+ // are actually updated.
+ var cache = this.cache || (this.cache = {});
+ var name, val;
+ for (name in cache) {
+ if (!(name in value)) {
+ this.handleSingle(name, null);
+ delete cache[name];
+ }
+ }
+ for (name in value) {
+ val = value[name];
+ if (val !== cache[name]) {
+ cache[name] = val;
+ this.handleSingle(name, val);
+ }
+ }
+ },
+
+ handleSingle: function handleSingle(prop, value) {
+ prop = normalize(prop);
+ if (!prop) return; // unsupported prop
+ // cast possible numbers/booleans into strings
+ if (value != null) value += '';
+ if (value) {
+ var isImportant = importantRE.test(value) ? 'important' : '';
+ if (isImportant) {
+ /* istanbul ignore if */
+ if ('development' !== 'production') {
+ warn('It\'s probably a bad idea to use !important with inline rules. ' + 'This feature will be deprecated in a future version of Vue.');
+ }
+ value = value.replace(importantRE, '').trim();
+ this.el.style.setProperty(prop.kebab, value, isImportant);
+ } else {
+ this.el.style[prop.camel] = value;
+ }
+ } else {
+ this.el.style[prop.camel] = '';
+ }
+ }
+
+ };
+
+ /**
+ * Normalize a CSS property name.
+ * - cache result
+ * - auto prefix
+ * - camelCase -> dash-case
+ *
+ * @param {String} prop
+ * @return {String}
+ */
+
+ function normalize(prop) {
+ if (propCache[prop]) {
+ return propCache[prop];
+ }
+ var res = prefix(prop);
+ propCache[prop] = propCache[res] = res;
+ return res;
+ }
+
+ /**
+ * Auto detect the appropriate prefix for a CSS property.
+ * https://gist.github.com/paulirish/523692
+ *
+ * @param {String} prop
+ * @return {String}
+ */
+
+ function prefix(prop) {
+ prop = hyphenate(prop);
+ var camel = camelize(prop);
+ var upper = camel.charAt(0).toUpperCase() + camel.slice(1);
+ if (!testEl) {
+ testEl = document.createElement('div');
+ }
+ var i = prefixes.length;
+ var prefixed;
+ if (camel !== 'filter' && camel in testEl.style) {
+ return {
+ kebab: prop,
+ camel: camel
+ };
+ }
+ while (i--) {
+ prefixed = camelPrefixes[i] + upper;
+ if (prefixed in testEl.style) {
+ return {
+ kebab: prefixes[i] + prop,
+ camel: prefixed
+ };
+ }
+ }
+ }
+
+ // xlink
+ var xlinkNS = 'http://www.w3.org/1999/xlink';
+ var xlinkRE = /^xlink:/;
+
+ // check for attributes that prohibit interpolations
+ var disallowedInterpAttrRE = /^v-|^:|^@|^(?:is|transition|transition-mode|debounce|track-by|stagger|enter-stagger|leave-stagger)$/;
+ // these attributes should also set their corresponding properties
+ // because they only affect the initial state of the element
+ var attrWithPropsRE = /^(?:value|checked|selected|muted)$/;
+ // these attributes expect enumrated values of "true" or "false"
+ // but are not boolean attributes
+ var enumeratedAttrRE = /^(?:draggable|contenteditable|spellcheck)$/;
+
+ // these attributes should set a hidden property for
+ // binding v-model to object values
+ var modelProps = {
+ value: '_value',
+ 'true-value': '_trueValue',
+ 'false-value': '_falseValue'
+ };
+
+ var bind$1 = {
+
+ priority: BIND,
+
+ bind: function bind() {
+ var attr = this.arg;
+ var tag = this.el.tagName;
+ // should be deep watch on object mode
+ if (!attr) {
+ this.deep = true;
+ }
+ // handle interpolation bindings
+ var descriptor = this.descriptor;
+ var tokens = descriptor.interp;
+ if (tokens) {
+ // handle interpolations with one-time tokens
+ if (descriptor.hasOneTime) {
+ this.expression = tokensToExp(tokens, this._scope || this.vm);
+ }
+
+ // only allow binding on native attributes
+ if (disallowedInterpAttrRE.test(attr) || attr === 'name' && (tag === 'PARTIAL' || tag === 'SLOT')) {
+ 'development' !== 'production' && warn(attr + '="' + descriptor.raw + '": ' + 'attribute interpolation is not allowed in Vue.js ' + 'directives and special attributes.', this.vm);
+ this.el.removeAttribute(attr);
+ this.invalid = true;
+ }
+
+ /* istanbul ignore if */
+ if ('development' !== 'production') {
+ var raw = attr + '="' + descriptor.raw + '": ';
+ // warn src
+ if (attr === 'src') {
+ warn(raw + 'interpolation in "src" attribute will cause ' + 'a 404 request. Use v-bind:src instead.', this.vm);
+ }
+
+ // warn style
+ if (attr === 'style') {
+ warn(raw + 'interpolation in "style" attribute will cause ' + 'the attribute to be discarded in Internet Explorer. ' + 'Use v-bind:style instead.', this.vm);
+ }
+ }
+ }
+ },
+
+ update: function update(value) {
+ if (this.invalid) {
+ return;
+ }
+ var attr = this.arg;
+ if (this.arg) {
+ this.handleSingle(attr, value);
+ } else {
+ this.handleObject(value || {});
+ }
+ },
+
+ // share object handler with v-bind:class
+ handleObject: style.handleObject,
+
+ handleSingle: function handleSingle(attr, value) {
+ var el = this.el;
+ var interp = this.descriptor.interp;
+ if (this.modifiers.camel) {
+ attr = camelize(attr);
+ }
+ if (!interp && attrWithPropsRE.test(attr) && attr in el) {
+ var attrValue = attr === 'value' ? value == null // IE9 will set input.value to "null" for null...
+ ? '' : value : value;
+
+ if (el[attr] !== attrValue) {
+ el[attr] = attrValue;
+ }
+ }
+ // set model props
+ var modelProp = modelProps[attr];
+ if (!interp && modelProp) {
+ el[modelProp] = value;
+ // update v-model if present
+ var model = el.__v_model;
+ if (model) {
+ model.listener();
+ }
+ }
+ // do not set value attribute for textarea
+ if (attr === 'value' && el.tagName === 'TEXTAREA') {
+ el.removeAttribute(attr);
+ return;
+ }
+ // update attribute
+ if (enumeratedAttrRE.test(attr)) {
+ el.setAttribute(attr, value ? 'true' : 'false');
+ } else if (value != null && value !== false) {
+ if (attr === 'class') {
+ // handle edge case #1960:
+ // class interpolation should not overwrite Vue transition class
+ if (el.__v_trans) {
+ value += ' ' + el.__v_trans.id + '-transition';
+ }
+ setClass(el, value);
+ } else if (xlinkRE.test(attr)) {
+ el.setAttributeNS(xlinkNS, attr, value === true ? '' : value);
+ } else {
+ el.setAttribute(attr, value === true ? '' : value);
+ }
+ } else {
+ el.removeAttribute(attr);
+ }
+ }
+ };
+
+ var el = {
+
+ priority: EL,
+
+ bind: function bind() {
+ /* istanbul ignore if */
+ if (!this.arg) {
+ return;
+ }
+ var id = this.id = camelize(this.arg);
+ var refs = (this._scope || this.vm).$els;
+ if (hasOwn(refs, id)) {
+ refs[id] = this.el;
+ } else {
+ defineReactive(refs, id, this.el);
+ }
+ },
+
+ unbind: function unbind() {
+ var refs = (this._scope || this.vm).$els;
+ if (refs[this.id] === this.el) {
+ refs[this.id] = null;
+ }
+ }
+ };
+
+ var ref = {
+ bind: function bind() {
+ 'development' !== 'production' && warn('v-ref:' + this.arg + ' must be used on a child ' + 'component. Found on <' + this.el.tagName.toLowerCase() + '>.', this.vm);
+ }
+ };
+
+ var cloak = {
+ bind: function bind() {
+ var el = this.el;
+ this.vm.$once('pre-hook:compiled', function () {
+ el.removeAttribute('v-cloak');
+ });
+ }
+ };
+
+ // must export plain object
+ var directives = {
+ text: text$1,
+ html: html,
+ 'for': vFor,
+ 'if': vIf,
+ show: show,
+ model: model,
+ on: on$1,
+ bind: bind$1,
+ el: el,
+ ref: ref,
+ cloak: cloak
+ };
+
+ var vClass = {
+
+ deep: true,
+
+ update: function update(value) {
+ if (!value) {
+ this.cleanup();
+ } else if (typeof value === 'string') {
+ this.setClass(value.trim().split(/\s+/));
+ } else {
+ this.setClass(normalize$1(value));
+ }
+ },
+
+ setClass: function setClass(value) {
+ this.cleanup(value);
+ for (var i = 0, l = value.length; i < l; i++) {
+ var val = value[i];
+ if (val) {
+ apply(this.el, val, addClass);
+ }
+ }
+ this.prevKeys = value;
+ },
+
+ cleanup: function cleanup(value) {
+ var prevKeys = this.prevKeys;
+ if (!prevKeys) return;
+ var i = prevKeys.length;
+ while (i--) {
+ var key = prevKeys[i];
+ if (!value || value.indexOf(key) < 0) {
+ apply(this.el, key, removeClass);
+ }
+ }
+ }
+ };
+
+ /**
+ * Normalize objects and arrays (potentially containing objects)
+ * into array of strings.
+ *
+ * @param {Object|Array<String|Object>} value
+ * @return {Array<String>}
+ */
+
+ function normalize$1(value) {
+ var res = [];
+ if (isArray(value)) {
+ for (var i = 0, l = value.length; i < l; i++) {
+ var _key = value[i];
+ if (_key) {
+ if (typeof _key === 'string') {
+ res.push(_key);
+ } else {
+ for (var k in _key) {
+ if (_key[k]) res.push(k);
+ }
+ }
+ }
+ }
+ } else if (isObject(value)) {
+ for (var key in value) {
+ if (value[key]) res.push(key);
+ }
+ }
+ return res;
+ }
+
+ /**
+ * Add or remove a class/classes on an element
+ *
+ * @param {Element} el
+ * @param {String} key The class name. This may or may not
+ * contain a space character, in such a
+ * case we'll deal with multiple class
+ * names at once.
+ * @param {Function} fn
+ */
+
+ function apply(el, key, fn) {
+ key = key.trim();
+ if (key.indexOf(' ') === -1) {
+ fn(el, key);
+ return;
+ }
+ // The key contains one or more space characters.
+ // Since a class name doesn't accept such characters, we
+ // treat it as multiple classes.
+ var keys = key.split(/\s+/);
+ for (var i = 0, l = keys.length; i < l; i++) {
+ fn(el, keys[i]);
+ }
+ }
+
+ var component = {
+
+ priority: COMPONENT,
+
+ params: ['keep-alive', 'transition-mode', 'inline-template'],
+
+ /**
+ * Setup. Two possible usages:
+ *
+ * - static:
+ * <comp> or <div v-component="comp">
+ *
+ * - dynamic:
+ * <component :is="view">
+ */
+
+ bind: function bind() {
+ if (!this.el.__vue__) {
+ // keep-alive cache
+ this.keepAlive = this.params.keepAlive;
+ if (this.keepAlive) {
+ this.cache = {};
+ }
+ // check inline-template
+ if (this.params.inlineTemplate) {
+ // extract inline template as a DocumentFragment
+ this.inlineTemplate = extractContent(this.el, true);
+ }
+ // component resolution related state
+ this.pendingComponentCb = this.Component = null;
+ // transition related state
+ this.pendingRemovals = 0;
+ this.pendingRemovalCb = null;
+ // create a ref anchor
+ this.anchor = createAnchor('v-component');
+ replace(this.el, this.anchor);
+ // remove is attribute.
+ // this is removed during compilation, but because compilation is
+ // cached, when the component is used elsewhere this attribute
+ // will remain at link time.
+ this.el.removeAttribute('is');
+ this.el.removeAttribute(':is');
+ // remove ref, same as above
+ if (this.descriptor.ref) {
+ this.el.removeAttribute('v-ref:' + hyphenate(this.descriptor.ref));
+ }
+ // if static, build right now.
+ if (this.literal) {
+ this.setComponent(this.expression);
+ }
+ } else {
+ 'development' !== 'production' && warn('cannot mount component "' + this.expression + '" ' + 'on already mounted element: ' + this.el);
+ }
+ },
+
+ /**
+ * Public update, called by the watcher in the dynamic
+ * literal scenario, e.g. <component :is="view">
+ */
+
+ update: function update(value) {
+ if (!this.literal) {
+ this.setComponent(value);
+ }
+ },
+
+ /**
+ * Switch dynamic components. May resolve the component
+ * asynchronously, and perform transition based on
+ * specified transition mode. Accepts a few additional
+ * arguments specifically for vue-router.
+ *
+ * The callback is called when the full transition is
+ * finished.
+ *
+ * @param {String} value
+ * @param {Function} [cb]
+ */
+
+ setComponent: function setComponent(value, cb) {
+ this.invalidatePending();
+ if (!value) {
+ // just remove current
+ this.unbuild(true);
+ this.remove(this.childVM, cb);
+ this.childVM = null;
+ } else {
+ var self = this;
+ this.resolveComponent(value, function () {
+ self.mountComponent(cb);
+ });
+ }
+ },
+
+ /**
+ * Resolve the component constructor to use when creating
+ * the child vm.
+ *
+ * @param {String|Function} value
+ * @param {Function} cb
+ */
+
+ resolveComponent: function resolveComponent(value, cb) {
+ var self = this;
+ this.pendingComponentCb = cancellable(function (Component) {
+ self.ComponentName = Component.options.name || (typeof value === 'string' ? value : null);
+ self.Component = Component;
+ cb();
+ });
+ this.vm._resolveComponent(value, this.pendingComponentCb);
+ },
+
+ /**
+ * Create a new instance using the current constructor and
+ * replace the existing instance. This method doesn't care
+ * whether the new component and the old one are actually
+ * the same.
+ *
+ * @param {Function} [cb]
+ */
+
+ mountComponent: function mountComponent(cb) {
+ // actual mount
+ this.unbuild(true);
+ var self = this;
+ var activateHooks = this.Component.options.activate;
+ var cached = this.getCached();
+ var newComponent = this.build();
+ if (activateHooks && !cached) {
+ this.waitingFor = newComponent;
+ callActivateHooks(activateHooks, newComponent, function () {
+ if (self.waitingFor !== newComponent) {
+ return;
+ }
+ self.waitingFor = null;
+ self.transition(newComponent, cb);
+ });
+ } else {
+ // update ref for kept-alive component
+ if (cached) {
+ newComponent._updateRef();
+ }
+ this.transition(newComponent, cb);
+ }
+ },
+
+ /**
+ * When the component changes or unbinds before an async
+ * constructor is resolved, we need to invalidate its
+ * pending callback.
+ */
+
+ invalidatePending: function invalidatePending() {
+ if (this.pendingComponentCb) {
+ this.pendingComponentCb.cancel();
+ this.pendingComponentCb = null;
+ }
+ },
+
+ /**
+ * Instantiate/insert a new child vm.
+ * If keep alive and has cached instance, insert that
+ * instance; otherwise build a new one and cache it.
+ *
+ * @param {Object} [extraOptions]
+ * @return {Vue} - the created instance
+ */
+
+ build: function build(extraOptions) {
+ var cached = this.getCached();
+ if (cached) {
+ return cached;
+ }
+ if (this.Component) {
+ // default options
+ var options = {
+ name: this.ComponentName,
+ el: cloneNode(this.el),
+ template: this.inlineTemplate,
+ // make sure to add the child with correct parent
+ // if this is a transcluded component, its parent
+ // should be the transclusion host.
+ parent: this._host || this.vm,
+ // if no inline-template, then the compiled
+ // linker can be cached for better performance.
+ _linkerCachable: !this.inlineTemplate,
+ _ref: this.descriptor.ref,
+ _asComponent: true,
+ _isRouterView: this._isRouterView,
+ // if this is a transcluded component, context
+ // will be the common parent vm of this instance
+ // and its host.
+ _context: this.vm,
+ // if this is inside an inline v-for, the scope
+ // will be the intermediate scope created for this
+ // repeat fragment. this is used for linking props
+ // and container directives.
+ _scope: this._scope,
+ // pass in the owner fragment of this component.
+ // this is necessary so that the fragment can keep
+ // track of its contained components in order to
+ // call attach/detach hooks for them.
+ _frag: this._frag
+ };
+ // extra options
+ // in 1.0.0 this is used by vue-router only
+ /* istanbul ignore if */
+ if (extraOptions) {
+ extend(options, extraOptions);
+ }
+ var child = new this.Component(options);
+ if (this.keepAlive) {
+ this.cache[this.Component.cid] = child;
+ }
+ /* istanbul ignore if */
+ if ('development' !== 'production' && this.el.hasAttribute('transition') && child._isFragment) {
+ warn('Transitions will not work on a fragment instance. ' + 'Template: ' + child.$options.template, child);
+ }
+ return child;
+ }
+ },
+
+ /**
+ * Try to get a cached instance of the current component.
+ *
+ * @return {Vue|undefined}
+ */
+
+ getCached: function getCached() {
+ return this.keepAlive && this.cache[this.Component.cid];
+ },
+
+ /**
+ * Teardown the current child, but defers cleanup so
+ * that we can separate the destroy and removal steps.
+ *
+ * @param {Boolean} defer
+ */
+
+ unbuild: function unbuild(defer) {
+ if (this.waitingFor) {
+ if (!this.keepAlive) {
+ this.waitingFor.$destroy();
+ }
+ this.waitingFor = null;
+ }
+ var child = this.childVM;
+ if (!child || this.keepAlive) {
+ if (child) {
+ // remove ref
+ child._inactive = true;
+ child._updateRef(true);
+ }
+ return;
+ }
+ // the sole purpose of `deferCleanup` is so that we can
+ // "deactivate" the vm right now and perform DOM removal
+ // later.
+ child.$destroy(false, defer);
+ },
+
+ /**
+ * Remove current destroyed child and manually do
+ * the cleanup after removal.
+ *
+ * @param {Function} cb
+ */
+
+ remove: function remove(child, cb) {
+ var keepAlive = this.keepAlive;
+ if (child) {
+ // we may have a component switch when a previous
+ // component is still being transitioned out.
+ // we want to trigger only one lastest insertion cb
+ // when the existing transition finishes. (#1119)
+ this.pendingRemovals++;
+ this.pendingRemovalCb = cb;
+ var self = this;
+ child.$remove(function () {
+ self.pendingRemovals--;
+ if (!keepAlive) child._cleanup();
+ if (!self.pendingRemovals && self.pendingRemovalCb) {
+ self.pendingRemovalCb();
+ self.pendingRemovalCb = null;
+ }
+ });
+ } else if (cb) {
+ cb();
+ }
+ },
+
+ /**
+ * Actually swap the components, depending on the
+ * transition mode. Defaults to simultaneous.
+ *
+ * @param {Vue} target
+ * @param {Function} [cb]
+ */
+
+ transition: function transition(target, cb) {
+ var self = this;
+ var current = this.childVM;
+ // for devtool inspection
+ if (current) current._inactive = true;
+ target._inactive = false;
+ this.childVM = target;
+ switch (self.params.transitionMode) {
+ case 'in-out':
+ target.$before(self.anchor, function () {
+ self.remove(current, cb);
+ });
+ break;
+ case 'out-in':
+ self.remove(current, function () {
+ target.$before(self.anchor, cb);
+ });
+ break;
+ default:
+ self.remove(current);
+ target.$before(self.anchor, cb);
+ }
+ },
+
+ /**
+ * Unbind.
+ */
+
+ unbind: function unbind() {
+ this.invalidatePending();
+ // Do not defer cleanup when unbinding
+ this.unbuild();
+ // destroy all keep-alive cached instances
+ if (this.cache) {
+ for (var key in this.cache) {
+ this.cache[key].$destroy();
+ }
+ this.cache = null;
+ }
+ }
+ };
+
+ /**
+ * Call activate hooks in order (asynchronous)
+ *
+ * @param {Array} hooks
+ * @param {Vue} vm
+ * @param {Function} cb
+ */
+
+ function callActivateHooks(hooks, vm, cb) {
+ var total = hooks.length;
+ var called = 0;
+ hooks[0].call(vm, next);
+ function next() {
+ if (++called >= total) {
+ cb();
+ } else {
+ hooks[called].call(vm, next);
+ }
+ }
+ }
+
+ var propBindingModes = config._propBindingModes;
+ var empty = {};
+
+ // regexes
+ var identRE$1 = /^[$_a-zA-Z]+[\w$]*$/;
+ var settablePathRE = /^[A-Za-z_$][\w$]*(\.[A-Za-z_$][\w$]*|\[[^\[\]]+\])*$/;
+
+ /**
+ * Compile props on a root element and return
+ * a props link function.
+ *
+ * @param {Element|DocumentFragment} el
+ * @param {Array} propOptions
+ * @param {Vue} vm
+ * @return {Function} propsLinkFn
+ */
+
+ function compileProps(el, propOptions, vm) {
+ var props = [];
+ var names = Object.keys(propOptions);
+ var i = names.length;
+ var options, name, attr, value, path, parsed, prop;
+ while (i--) {
+ name = names[i];
+ options = propOptions[name] || empty;
+
+ if ('development' !== 'production' && name === '$data') {
+ warn('Do not use $data as prop.', vm);
+ continue;
+ }
+
+ // props could contain dashes, which will be
+ // interpreted as minus calculations by the parser
+ // so we need to camelize the path here
+ path = camelize(name);
+ if (!identRE$1.test(path)) {
+ 'development' !== 'production' && warn('Invalid prop key: "' + name + '". Prop keys ' + 'must be valid identifiers.', vm);
+ continue;
+ }
+
+ prop = {
+ name: name,
+ path: path,
+ options: options,
+ mode: propBindingModes.ONE_WAY,
+ raw: null
+ };
+
+ attr = hyphenate(name);
+ // first check dynamic version
+ if ((value = getBindAttr(el, attr)) === null) {
+ if ((value = getBindAttr(el, attr + '.sync')) !== null) {
+ prop.mode = propBindingModes.TWO_WAY;
+ } else if ((value = getBindAttr(el, attr + '.once')) !== null) {
+ prop.mode = propBindingModes.ONE_TIME;
+ }
+ }
+ if (value !== null) {
+ // has dynamic binding!
+ prop.raw = value;
+ parsed = parseDirective(value);
+ value = parsed.expression;
+ prop.filters = parsed.filters;
+ // check binding type
+ if (isLiteral(value) && !parsed.filters) {
+ // for expressions containing literal numbers and
+ // booleans, there's no need to setup a prop binding,
+ // so we can optimize them as a one-time set.
+ prop.optimizedLiteral = true;
+ } else {
+ prop.dynamic = true;
+ // check non-settable path for two-way bindings
+ if ('development' !== 'production' && prop.mode === propBindingModes.TWO_WAY && !settablePathRE.test(value)) {
+ prop.mode = propBindingModes.ONE_WAY;
+ warn('Cannot bind two-way prop with non-settable ' + 'parent path: ' + value, vm);
+ }
+ }
+ prop.parentPath = value;
+
+ // warn required two-way
+ if ('development' !== 'production' && options.twoWay && prop.mode !== propBindingModes.TWO_WAY) {
+ warn('Prop "' + name + '" expects a two-way binding type.', vm);
+ }
+ } else if ((value = getAttr(el, attr)) !== null) {
+ // has literal binding!
+ prop.raw = value;
+ } else if ('development' !== 'production') {
+ // check possible camelCase prop usage
+ var lowerCaseName = path.toLowerCase();
+ value = /[A-Z\-]/.test(name) && (el.getAttribute(lowerCaseName) || el.getAttribute(':' + lowerCaseName) || el.getAttribute('v-bind:' + lowerCaseName) || el.getAttribute(':' + lowerCaseName + '.once') || el.getAttribute('v-bind:' + lowerCaseName + '.once') || el.getAttribute(':' + lowerCaseName + '.sync') || el.getAttribute('v-bind:' + lowerCaseName + '.sync'));
+ if (value) {
+ warn('Possible usage error for prop `' + lowerCaseName + '` - ' + 'did you mean `' + attr + '`? HTML is case-insensitive, remember to use ' + 'kebab-case for props in templates.', vm);
+ } else if (options.required) {
+ // warn missing required
+ warn('Missing required prop: ' + name, vm);
+ }
+ }
+ // push prop
+ props.push(prop);
+ }
+ return makePropsLinkFn(props);
+ }
+
+ /**
+ * Build a function that applies props to a vm.
+ *
+ * @param {Array} props
+ * @return {Function} propsLinkFn
+ */
+
+ function makePropsLinkFn(props) {
+ return function propsLinkFn(vm, scope) {
+ // store resolved props info
+ vm._props = {};
+ var inlineProps = vm.$options.propsData;
+ var i = props.length;
+ var prop, path, options, value, raw;
+ while (i--) {
+ prop = props[i];
+ raw = prop.raw;
+ path = prop.path;
+ options = prop.options;
+ vm._props[path] = prop;
+ if (inlineProps && hasOwn(inlineProps, path)) {
+ initProp(vm, prop, inlineProps[path]);
+ }if (raw === null) {
+ // initialize absent prop
+ initProp(vm, prop, undefined);
+ } else if (prop.dynamic) {
+ // dynamic prop
+ if (prop.mode === propBindingModes.ONE_TIME) {
+ // one time binding
+ value = (scope || vm._context || vm).$get(prop.parentPath);
+ initProp(vm, prop, value);
+ } else {
+ if (vm._context) {
+ // dynamic binding
+ vm._bindDir({
+ name: 'prop',
+ def: propDef,
+ prop: prop
+ }, null, null, scope); // el, host, scope
+ } else {
+ // root instance
+ initProp(vm, prop, vm.$get(prop.parentPath));
+ }
+ }
+ } else if (prop.optimizedLiteral) {
+ // optimized literal, cast it and just set once
+ var stripped = stripQuotes(raw);
+ value = stripped === raw ? toBoolean(toNumber(raw)) : stripped;
+ initProp(vm, prop, value);
+ } else {
+ // string literal, but we need to cater for
+ // Boolean props with no value, or with same
+ // literal value (e.g. disabled="disabled")
+ // see https://github.com/vuejs/vue-loader/issues/182
+ value = options.type === Boolean && (raw === '' || raw === hyphenate(prop.name)) ? true : raw;
+ initProp(vm, prop, value);
+ }
+ }
+ };
+ }
+
+ /**
+ * Process a prop with a rawValue, applying necessary coersions,
+ * default values & assertions and call the given callback with
+ * processed value.
+ *
+ * @param {Vue} vm
+ * @param {Object} prop
+ * @param {*} rawValue
+ * @param {Function} fn
+ */
+
+ function processPropValue(vm, prop, rawValue, fn) {
+ var isSimple = prop.dynamic && isSimplePath(prop.parentPath);
+ var value = rawValue;
+ if (value === undefined) {
+ value = getPropDefaultValue(vm, prop);
+ }
+ value = coerceProp(prop, value, vm);
+ var coerced = value !== rawValue;
+ if (!assertProp(prop, value, vm)) {
+ value = undefined;
+ }
+ if (isSimple && !coerced) {
+ withoutConversion(function () {
+ fn(value);
+ });
+ } else {
+ fn(value);
+ }
+ }
+
+ /**
+ * Set a prop's initial value on a vm and its data object.
+ *
+ * @param {Vue} vm
+ * @param {Object} prop
+ * @param {*} value
+ */
+
+ function initProp(vm, prop, value) {
+ processPropValue(vm, prop, value, function (value) {
+ defineReactive(vm, prop.path, value);
+ });
+ }
+
+ /**
+ * Update a prop's value on a vm.
+ *
+ * @param {Vue} vm
+ * @param {Object} prop
+ * @param {*} value
+ */
+
+ function updateProp(vm, prop, value) {
+ processPropValue(vm, prop, value, function (value) {
+ vm[prop.path] = value;
+ });
+ }
+
+ /**
+ * Get the default value of a prop.
+ *
+ * @param {Vue} vm
+ * @param {Object} prop
+ * @return {*}
+ */
+
+ function getPropDefaultValue(vm, prop) {
+ // no default, return undefined
+ var options = prop.options;
+ if (!hasOwn(options, 'default')) {
+ // absent boolean value defaults to false
+ return options.type === Boolean ? false : undefined;
+ }
+ var def = options['default'];
+ // warn against non-factory defaults for Object & Array
+ if (isObject(def)) {
+ 'development' !== 'production' && warn('Invalid default value for prop "' + prop.name + '": ' + 'Props with type Object/Array must use a factory function ' + 'to return the default value.', vm);
+ }
+ // call factory function for non-Function types
+ return typeof def === 'function' && options.type !== Function ? def.call(vm) : def;
+ }
+
+ /**
+ * Assert whether a prop is valid.
+ *
+ * @param {Object} prop
+ * @param {*} value
+ * @param {Vue} vm
+ */
+
+ function assertProp(prop, value, vm) {
+ if (!prop.options.required && ( // non-required
+ prop.raw === null || // abscent
+ value == null) // null or undefined
+ ) {
+ return true;
+ }
+ var options = prop.options;
+ var type = options.type;
+ var valid = !type;
+ var expectedTypes = [];
+ if (type) {
+ if (!isArray(type)) {
+ type = [type];
+ }
+ for (var i = 0; i < type.length && !valid; i++) {
+ var assertedType = assertType(value, type[i]);
+ expectedTypes.push(assertedType.expectedType);
+ valid = assertedType.valid;
+ }
+ }
+ if (!valid) {
+ if ('development' !== 'production') {
+ warn('Invalid prop: type check failed for prop "' + prop.name + '".' + ' Expected ' + expectedTypes.map(formatType).join(', ') + ', got ' + formatValue(value) + '.', vm);
+ }
+ return false;
+ }
+ var validator = options.validator;
+ if (validator) {
+ if (!validator(value)) {
+ 'development' !== 'production' && warn('Invalid prop: custom validator check failed for prop "' + prop.name + '".', vm);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Force parsing value with coerce option.
+ *
+ * @param {*} value
+ * @param {Object} options
+ * @return {*}
+ */
+
+ function coerceProp(prop, value, vm) {
+ var coerce = prop.options.coerce;
+ if (!coerce) {
+ return value;
+ }
+ if (typeof coerce === 'function') {
+ return coerce(value);
+ } else {
+ 'development' !== 'production' && warn('Invalid coerce for prop "' + prop.name + '": expected function, got ' + typeof coerce + '.', vm);
+ return value;
+ }
+ }
+
+ /**
+ * Assert the type of a value
+ *
+ * @param {*} value
+ * @param {Function} type
+ * @return {Object}
+ */
+
+ function assertType(value, type) {
+ var valid;
+ var expectedType;
+ if (type === String) {
+ expectedType = 'string';
+ valid = typeof value === expectedType;
+ } else if (type === Number) {
+ expectedType = 'number';
+ valid = typeof value === expectedType;
+ } else if (type === Boolean) {
+ expectedType = 'boolean';
+ valid = typeof value === expectedType;
+ } else if (type === Function) {
+ expectedType = 'function';
+ valid = typeof value === expectedType;
+ } else if (type === Object) {
+ expectedType = 'object';
+ valid = isPlainObject(value);
+ } else if (type === Array) {
+ expectedType = 'array';
+ valid = isArray(value);
+ } else {
+ valid = value instanceof type;
+ }
+ return {
+ valid: valid,
+ expectedType: expectedType
+ };
+ }
+
+ /**
+ * Format type for output
+ *
+ * @param {String} type
+ * @return {String}
+ */
+
+ function formatType(type) {
+ return type ? type.charAt(0).toUpperCase() + type.slice(1) : 'custom type';
+ }
+
+ /**
+ * Format value
+ *
+ * @param {*} value
+ * @return {String}
+ */
+
+ function formatValue(val) {
+ return Object.prototype.toString.call(val).slice(8, -1);
+ }
+
+ var bindingModes = config._propBindingModes;
+
+ var propDef = {
+
+ bind: function bind() {
+ var child = this.vm;
+ var parent = child._context;
+ // passed in from compiler directly
+ var prop = this.descriptor.prop;
+ var childKey = prop.path;
+ var parentKey = prop.parentPath;
+ var twoWay = prop.mode === bindingModes.TWO_WAY;
+
+ var parentWatcher = this.parentWatcher = new Watcher(parent, parentKey, function (val) {
+ updateProp(child, prop, val);
+ }, {
+ twoWay: twoWay,
+ filters: prop.filters,
+ // important: props need to be observed on the
+ // v-for scope if present
+ scope: this._scope
+ });
+
+ // set the child initial value.
+ initProp(child, prop, parentWatcher.value);
+
+ // setup two-way binding
+ if (twoWay) {
+ // important: defer the child watcher creation until
+ // the created hook (after data observation)
+ var self = this;
+ child.$once('pre-hook:created', function () {
+ self.childWatcher = new Watcher(child, childKey, function (val) {
+ parentWatcher.set(val);
+ }, {
+ // ensure sync upward before parent sync down.
+ // this is necessary in cases e.g. the child
+ // mutates a prop array, then replaces it. (#1683)
+ sync: true
+ });
+ });
+ }
+ },
+
+ unbind: function unbind() {
+ this.parentWatcher.teardown();
+ if (this.childWatcher) {
+ this.childWatcher.teardown();
+ }
+ }
+ };
+
+ var queue$1 = [];
+ var queued = false;
+
+ /**
+ * Push a job into the queue.
+ *
+ * @param {Function} job
+ */
+
+ function pushJob(job) {
+ queue$1.push(job);
+ if (!queued) {
+ queued = true;
+ nextTick(flush);
+ }
+ }
+
+ /**
+ * Flush the queue, and do one forced reflow before
+ * triggering transitions.
+ */
+
+ function flush() {
+ // Force layout
+ var f = document.documentElement.offsetHeight;
+ for (var i = 0; i < queue$1.length; i++) {
+ queue$1[i]();
+ }
+ queue$1 = [];
+ queued = false;
+ // dummy return, so js linters don't complain about
+ // unused variable f
+ return f;
+ }
+
+ var TYPE_TRANSITION = 'transition';
+ var TYPE_ANIMATION = 'animation';
+ var transDurationProp = transitionProp + 'Duration';
+ var animDurationProp = animationProp + 'Duration';
+
+ /**
+ * If a just-entered element is applied the
+ * leave class while its enter transition hasn't started yet,
+ * and the transitioned property has the same value for both
+ * enter/leave, then the leave transition will be skipped and
+ * the transitionend event never fires. This function ensures
+ * its callback to be called after a transition has started
+ * by waiting for double raf.
+ *
+ * It falls back to setTimeout on devices that support CSS
+ * transitions but not raf (e.g. Android 4.2 browser) - since
+ * these environments are usually slow, we are giving it a
+ * relatively large timeout.
+ */
+
+ var raf = inBrowser && window.requestAnimationFrame;
+ var waitForTransitionStart = raf
+ /* istanbul ignore next */
+ ? function (fn) {
+ raf(function () {
+ raf(fn);
+ });
+ } : function (fn) {
+ setTimeout(fn, 50);
+ };
+
+ /**
+ * A Transition object that encapsulates the state and logic
+ * of the transition.
+ *
+ * @param {Element} el
+ * @param {String} id
+ * @param {Object} hooks
+ * @param {Vue} vm
+ */
+ function Transition(el, id, hooks, vm) {
+ this.id = id;
+ this.el = el;
+ this.enterClass = hooks && hooks.enterClass || id + '-enter';
+ this.leaveClass = hooks && hooks.leaveClass || id + '-leave';
+ this.hooks = hooks;
+ this.vm = vm;
+ // async state
+ this.pendingCssEvent = this.pendingCssCb = this.cancel = this.pendingJsCb = this.op = this.cb = null;
+ this.justEntered = false;
+ this.entered = this.left = false;
+ this.typeCache = {};
+ // check css transition type
+ this.type = hooks && hooks.type;
+ /* istanbul ignore if */
+ if ('development' !== 'production') {
+ if (this.type && this.type !== TYPE_TRANSITION && this.type !== TYPE_ANIMATION) {
+ warn('invalid CSS transition type for transition="' + this.id + '": ' + this.type, vm);
+ }
+ }
+ // bind
+ var self = this;['enterNextTick', 'enterDone', 'leaveNextTick', 'leaveDone'].forEach(function (m) {
+ self[m] = bind(self[m], self);
+ });
+ }
+
+ var p$1 = Transition.prototype;
+
+ /**
+ * Start an entering transition.
+ *
+ * 1. enter transition triggered
+ * 2. call beforeEnter hook
+ * 3. add enter class
+ * 4. insert/show element
+ * 5. call enter hook (with possible explicit js callback)
+ * 6. reflow
+ * 7. based on transition type:
+ * - transition:
+ * remove class now, wait for transitionend,
+ * then done if there's no explicit js callback.
+ * - animation:
+ * wait for animationend, remove class,
+ * then done if there's no explicit js callback.
+ * - no css transition:
+ * done now if there's no explicit js callback.
+ * 8. wait for either done or js callback, then call
+ * afterEnter hook.
+ *
+ * @param {Function} op - insert/show the element
+ * @param {Function} [cb]
+ */
+
+ p$1.enter = function (op, cb) {
+ this.cancelPending();
+ this.callHook('beforeEnter');
+ this.cb = cb;
+ addClass(this.el, this.enterClass);
+ op();
+ this.entered = false;
+ this.callHookWithCb('enter');
+ if (this.entered) {
+ return; // user called done synchronously.
+ }
+ this.cancel = this.hooks && this.hooks.enterCancelled;
+ pushJob(this.enterNextTick);
+ };
+
+ /**
+ * The "nextTick" phase of an entering transition, which is
+ * to be pushed into a queue and executed after a reflow so
+ * that removing the class can trigger a CSS transition.
+ */
+
+ p$1.enterNextTick = function () {
+ var _this = this;
+
+ // prevent transition skipping
+ this.justEntered = true;
+ waitForTransitionStart(function () {
+ _this.justEntered = false;
+ });
+ var enterDone = this.enterDone;
+ var type = this.getCssTransitionType(this.enterClass);
+ if (!this.pendingJsCb) {
+ if (type === TYPE_TRANSITION) {
+ // trigger transition by removing enter class now
+ removeClass(this.el, this.enterClass);
+ this.setupCssCb(transitionEndEvent, enterDone);
+ } else if (type === TYPE_ANIMATION) {
+ this.setupCssCb(animationEndEvent, enterDone);
+ } else {
+ enterDone();
+ }
+ } else if (type === TYPE_TRANSITION) {
+ removeClass(this.el, this.enterClass);
+ }
+ };
+
+ /**
+ * The "cleanup" phase of an entering transition.
+ */
+
+ p$1.enterDone = function () {
+ this.entered = true;
+ this.cancel = this.pendingJsCb = null;
+ removeClass(this.el, this.enterClass);
+ this.callHook('afterEnter');
+ if (this.cb) this.cb();
+ };
+
+ /**
+ * Start a leaving transition.
+ *
+ * 1. leave transition triggered.
+ * 2. call beforeLeave hook
+ * 3. add leave class (trigger css transition)
+ * 4. call leave hook (with possible explicit js callback)
+ * 5. reflow if no explicit js callback is provided
+ * 6. based on transition type:
+ * - transition or animation:
+ * wait for end event, remove class, then done if
+ * there's no explicit js callback.
+ * - no css transition:
+ * done if there's no explicit js callback.
+ * 7. wait for either done or js callback, then call
+ * afterLeave hook.
+ *
+ * @param {Function} op - remove/hide the element
+ * @param {Function} [cb]
+ */
+
+ p$1.leave = function (op, cb) {
+ this.cancelPending();
+ this.callHook('beforeLeave');
+ this.op = op;
+ this.cb = cb;
+ addClass(this.el, this.leaveClass);
+ this.left = false;
+ this.callHookWithCb('leave');
+ if (this.left) {
+ return; // user called done synchronously.
+ }
+ this.cancel = this.hooks && this.hooks.leaveCancelled;
+ // only need to handle leaveDone if
+ // 1. the transition is already done (synchronously called
+ // by the user, which causes this.op set to null)
+ // 2. there's no explicit js callback
+ if (this.op && !this.pendingJsCb) {
+ // if a CSS transition leaves immediately after enter,
+ // the transitionend event never fires. therefore we
+ // detect such cases and end the leave immediately.
+ if (this.justEntered) {
+ this.leaveDone();
+ } else {
+ pushJob(this.leaveNextTick);
+ }
+ }
+ };
+
+ /**
+ * The "nextTick" phase of a leaving transition.
+ */
+
+ p$1.leaveNextTick = function () {
+ var type = this.getCssTransitionType(this.leaveClass);
+ if (type) {
+ var event = type === TYPE_TRANSITION ? transitionEndEvent : animationEndEvent;
+ this.setupCssCb(event, this.leaveDone);
+ } else {
+ this.leaveDone();
+ }
+ };
+
+ /**
+ * The "cleanup" phase of a leaving transition.
+ */
+
+ p$1.leaveDone = function () {
+ this.left = true;
+ this.cancel = this.pendingJsCb = null;
+ this.op();
+ removeClass(this.el, this.leaveClass);
+ this.callHook('afterLeave');
+ if (this.cb) this.cb();
+ this.op = null;
+ };
+
+ /**
+ * Cancel any pending callbacks from a previously running
+ * but not finished transition.
+ */
+
+ p$1.cancelPending = function () {
+ this.op = this.cb = null;
+ var hasPending = false;
+ if (this.pendingCssCb) {
+ hasPending = true;
+ off(this.el, this.pendingCssEvent, this.pendingCssCb);
+ this.pendingCssEvent = this.pendingCssCb = null;
+ }
+ if (this.pendingJsCb) {
+ hasPending = true;
+ this.pendingJsCb.cancel();
+ this.pendingJsCb = null;
+ }
+ if (hasPending) {
+ removeClass(this.el, this.enterClass);
+ removeClass(this.el, this.leaveClass);
+ }
+ if (this.cancel) {
+ this.cancel.call(this.vm, this.el);
+ this.cancel = null;
+ }
+ };
+
+ /**
+ * Call a user-provided synchronous hook function.
+ *
+ * @param {String} type
+ */
+
+ p$1.callHook = function (type) {
+ if (this.hooks && this.hooks[type]) {
+ this.hooks[type].call(this.vm, this.el);
+ }
+ };
+
+ /**
+ * Call a user-provided, potentially-async hook function.
+ * We check for the length of arguments to see if the hook
+ * expects a `done` callback. If true, the transition's end
+ * will be determined by when the user calls that callback;
+ * otherwise, the end is determined by the CSS transition or
+ * animation.
+ *
+ * @param {String} type
+ */
+
+ p$1.callHookWithCb = function (type) {
+ var hook = this.hooks && this.hooks[type];
+ if (hook) {
+ if (hook.length > 1) {
+ this.pendingJsCb = cancellable(this[type + 'Done']);
+ }
+ hook.call(this.vm, this.el, this.pendingJsCb);
+ }
+ };
+
+ /**
+ * Get an element's transition type based on the
+ * calculated styles.
+ *
+ * @param {String} className
+ * @return {Number}
+ */
+
+ p$1.getCssTransitionType = function (className) {
+ /* istanbul ignore if */
+ if (!transitionEndEvent ||
+ // skip CSS transitions if page is not visible -
+ // this solves the issue of transitionend events not
+ // firing until the page is visible again.
+ // pageVisibility API is supported in IE10+, same as
+ // CSS transitions.
+ document.hidden ||
+ // explicit js-only transition
+ this.hooks && this.hooks.css === false ||
+ // element is hidden
+ isHidden(this.el)) {
+ return;
+ }
+ var type = this.type || this.typeCache[className];
+ if (type) return type;
+ var inlineStyles = this.el.style;
+ var computedStyles = window.getComputedStyle(this.el);
+ var transDuration = inlineStyles[transDurationProp] || computedStyles[transDurationProp];
+ if (transDuration && transDuration !== '0s') {
+ type = TYPE_TRANSITION;
+ } else {
+ var animDuration = inlineStyles[animDurationProp] || computedStyles[animDurationProp];
+ if (animDuration && animDuration !== '0s') {
+ type = TYPE_ANIMATION;
+ }
+ }
+ if (type) {
+ this.typeCache[className] = type;
+ }
+ return type;
+ };
+
+ /**
+ * Setup a CSS transitionend/animationend callback.
+ *
+ * @param {String} event
+ * @param {Function} cb
+ */
+
+ p$1.setupCssCb = function (event, cb) {
+ this.pendingCssEvent = event;
+ var self = this;
+ var el = this.el;
+ var onEnd = this.pendingCssCb = function (e) {
+ if (e.target === el) {
+ off(el, event, onEnd);
+ self.pendingCssEvent = self.pendingCssCb = null;
+ if (!self.pendingJsCb && cb) {
+ cb();
+ }
+ }
+ };
+ on(el, event, onEnd);
+ };
+
+ /**
+ * Check if an element is hidden - in that case we can just
+ * skip the transition alltogether.
+ *
+ * @param {Element} el
+ * @return {Boolean}
+ */
+
+ function isHidden(el) {
+ if (/svg$/.test(el.namespaceURI)) {
+ // SVG elements do not have offset(Width|Height)
+ // so we need to check the client rect
+ var rect = el.getBoundingClientRect();
+ return !(rect.width || rect.height);
+ } else {
+ return !(el.offsetWidth || el.offsetHeight || el.getClientRects().length);
+ }
+ }
+
+ var transition$1 = {
+
+ priority: TRANSITION,
+
+ update: function update(id, oldId) {
+ var el = this.el;
+ // resolve on owner vm
+ var hooks = resolveAsset(this.vm.$options, 'transitions', id);
+ id = id || 'v';
+ oldId = oldId || 'v';
+ el.__v_trans = new Transition(el, id, hooks, this.vm);
+ removeClass(el, oldId + '-transition');
+ addClass(el, id + '-transition');
+ }
+ };
+
+ var internalDirectives = {
+ style: style,
+ 'class': vClass,
+ component: component,
+ prop: propDef,
+ transition: transition$1
+ };
+
+ // special binding prefixes
+ var bindRE = /^v-bind:|^:/;
+ var onRE = /^v-on:|^@/;
+ var dirAttrRE = /^v-([^:]+)(?:$|:(.*)$)/;
+ var modifierRE = /\.[^\.]+/g;
+ var transitionRE = /^(v-bind:|:)?transition$/;
+
+ // default directive priority
+ var DEFAULT_PRIORITY = 1000;
+ var DEFAULT_TERMINAL_PRIORITY = 2000;
+
+ /**
+ * Compile a template and return a reusable composite link
+ * function, which recursively contains more link functions
+ * inside. This top level compile function would normally
+ * be called on instance root nodes, but can also be used
+ * for partial compilation if the partial argument is true.
+ *
+ * The returned composite link function, when called, will
+ * return an unlink function that tearsdown all directives
+ * created during the linking phase.
+ *
+ * @param {Element|DocumentFragment} el
+ * @param {Object} options
+ * @param {Boolean} partial
+ * @return {Function}
+ */
+
+ function compile(el, options, partial) {
+ // link function for the node itself.
+ var nodeLinkFn = partial || !options._asComponent ? compileNode(el, options) : null;
+ // link function for the childNodes
+ var childLinkFn = !(nodeLinkFn && nodeLinkFn.terminal) && !isScript(el) && el.hasChildNodes() ? compileNodeList(el.childNodes, options) : null;
+
+ /**
+ * A composite linker function to be called on a already
+ * compiled piece of DOM, which instantiates all directive
+ * instances.
+ *
+ * @param {Vue} vm
+ * @param {Element|DocumentFragment} el
+ * @param {Vue} [host] - host vm of transcluded content
+ * @param {Object} [scope] - v-for scope
+ * @param {Fragment} [frag] - link context fragment
+ * @return {Function|undefined}
+ */
+
+ return function compositeLinkFn(vm, el, host, scope, frag) {
+ // cache childNodes before linking parent, fix #657
+ var childNodes = toArray(el.childNodes);
+ // link
+ var dirs = linkAndCapture(function compositeLinkCapturer() {
+ if (nodeLinkFn) nodeLinkFn(vm, el, host, scope, frag);
+ if (childLinkFn) childLinkFn(vm, childNodes, host, scope, frag);
+ }, vm);
+ return makeUnlinkFn(vm, dirs);
+ };
+ }
+
+ /**
+ * Apply a linker to a vm/element pair and capture the
+ * directives created during the process.
+ *
+ * @param {Function} linker
+ * @param {Vue} vm
+ */
+
+ function linkAndCapture(linker, vm) {
+ /* istanbul ignore if */
+ if ('development' === 'production') {}
+ var originalDirCount = vm._directives.length;
+ linker();
+ var dirs = vm._directives.slice(originalDirCount);
+ dirs.sort(directiveComparator);
+ for (var i = 0, l = dirs.length; i < l; i++) {
+ dirs[i]._bind();
+ }
+ return dirs;
+ }
+
+ /**
+ * Directive priority sort comparator
+ *
+ * @param {Object} a
+ * @param {Object} b
+ */
+
+ function directiveComparator(a, b) {
+ a = a.descriptor.def.priority || DEFAULT_PRIORITY;
+ b = b.descriptor.def.priority || DEFAULT_PRIORITY;
+ return a > b ? -1 : a === b ? 0 : 1;
+ }
+
+ /**
+ * Linker functions return an unlink function that
+ * tearsdown all directives instances generated during
+ * the process.
+ *
+ * We create unlink functions with only the necessary
+ * information to avoid retaining additional closures.
+ *
+ * @param {Vue} vm
+ * @param {Array} dirs
+ * @param {Vue} [context]
+ * @param {Array} [contextDirs]
+ * @return {Function}
+ */
+
+ function makeUnlinkFn(vm, dirs, context, contextDirs) {
+ function unlink(destroying) {
+ teardownDirs(vm, dirs, destroying);
+ if (context && contextDirs) {
+ teardownDirs(context, contextDirs);
+ }
+ }
+ // expose linked directives
+ unlink.dirs = dirs;
+ return unlink;
+ }
+
+ /**
+ * Teardown partial linked directives.
+ *
+ * @param {Vue} vm
+ * @param {Array} dirs
+ * @param {Boolean} destroying
+ */
+
+ function teardownDirs(vm, dirs, destroying) {
+ var i = dirs.length;
+ while (i--) {
+ dirs[i]._teardown();
+ if ('development' !== 'production' && !destroying) {
+ vm._directives.$remove(dirs[i]);
+ }
+ }
+ }
+
+ /**
+ * Compile link props on an instance.
+ *
+ * @param {Vue} vm
+ * @param {Element} el
+ * @param {Object} props
+ * @param {Object} [scope]
+ * @return {Function}
+ */
+
+ function compileAndLinkProps(vm, el, props, scope) {
+ var propsLinkFn = compileProps(el, props, vm);
+ var propDirs = linkAndCapture(function () {
+ propsLinkFn(vm, scope);
+ }, vm);
+ return makeUnlinkFn(vm, propDirs);
+ }
+
+ /**
+ * Compile the root element of an instance.
+ *
+ * 1. attrs on context container (context scope)
+ * 2. attrs on the component template root node, if
+ * replace:true (child scope)
+ *
+ * If this is a fragment instance, we only need to compile 1.
+ *
+ * @param {Element} el
+ * @param {Object} options
+ * @param {Object} contextOptions
+ * @return {Function}
+ */
+
+ function compileRoot(el, options, contextOptions) {
+ var containerAttrs = options._containerAttrs;
+ var replacerAttrs = options._replacerAttrs;
+ var contextLinkFn, replacerLinkFn;
+
+ // only need to compile other attributes for
+ // non-fragment instances
+ if (el.nodeType !== 11) {
+ // for components, container and replacer need to be
+ // compiled separately and linked in different scopes.
+ if (options._asComponent) {
+ // 2. container attributes
+ if (containerAttrs && contextOptions) {
+ contextLinkFn = compileDirectives(containerAttrs, contextOptions);
+ }
+ if (replacerAttrs) {
+ // 3. replacer attributes
+ replacerLinkFn = compileDirectives(replacerAttrs, options);
+ }
+ } else {
+ // non-component, just compile as a normal element.
+ replacerLinkFn = compileDirectives(el.attributes, options);
+ }
+ } else if ('development' !== 'production' && containerAttrs) {
+ // warn container directives for fragment instances
+ var names = containerAttrs.filter(function (attr) {
+ // allow vue-loader/vueify scoped css attributes
+ return attr.name.indexOf('_v-') < 0 &&
+ // allow event listeners
+ !onRE.test(attr.name) &&
+ // allow slots
+ attr.name !== 'slot';
+ }).map(function (attr) {
+ return '"' + attr.name + '"';
+ });
+ if (names.length) {
+ var plural = names.length > 1;
+ warn('Attribute' + (plural ? 's ' : ' ') + names.join(', ') + (plural ? ' are' : ' is') + ' ignored on component ' + '<' + options.el.tagName.toLowerCase() + '> because ' + 'the component is a fragment instance: ' + 'http://vuejs.org/guide/components.html#Fragment-Instance');
+ }
+ }
+
+ options._containerAttrs = options._replacerAttrs = null;
+ return function rootLinkFn(vm, el, scope) {
+ // link context scope dirs
+ var context = vm._context;
+ var contextDirs;
+ if (context && contextLinkFn) {
+ contextDirs = linkAndCapture(function () {
+ contextLinkFn(context, el, null, scope);
+ }, context);
+ }
+
+ // link self
+ var selfDirs = linkAndCapture(function () {
+ if (replacerLinkFn) replacerLinkFn(vm, el);
+ }, vm);
+
+ // return the unlink function that tearsdown context
+ // container directives.
+ return makeUnlinkFn(vm, selfDirs, context, contextDirs);
+ };
+ }
+
+ /**
+ * Compile a node and return a nodeLinkFn based on the
+ * node type.
+ *
+ * @param {Node} node
+ * @param {Object} options
+ * @return {Function|null}
+ */
+
+ function compileNode(node, options) {
+ var type = node.nodeType;
+ if (type === 1 && !isScript(node)) {
+ return compileElement(node, options);
+ } else if (type === 3 && node.data.trim()) {
+ return compileTextNode(node, options);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Compile an element and return a nodeLinkFn.
+ *
+ * @param {Element} el
+ * @param {Object} options
+ * @return {Function|null}
+ */
+
+ function compileElement(el, options) {
+ // preprocess textareas.
+ // textarea treats its text content as the initial value.
+ // just bind it as an attr directive for value.
+ if (el.tagName === 'TEXTAREA') {
+ var tokens = parseText(el.value);
+ if (tokens) {
+ el.setAttribute(':value', tokensToExp(tokens));
+ el.value = '';
+ }
+ }
+ var linkFn;
+ var hasAttrs = el.hasAttributes();
+ var attrs = hasAttrs && toArray(el.attributes);
+ // check terminal directives (for & if)
+ if (hasAttrs) {
+ linkFn = checkTerminalDirectives(el, attrs, options);
+ }
+ // check element directives
+ if (!linkFn) {
+ linkFn = checkElementDirectives(el, options);
+ }
+ // check component
+ if (!linkFn) {
+ linkFn = checkComponent(el, options);
+ }
+ // normal directives
+ if (!linkFn && hasAttrs) {
+ linkFn = compileDirectives(attrs, options);
+ }
+ return linkFn;
+ }
+
+ /**
+ * Compile a textNode and return a nodeLinkFn.
+ *
+ * @param {TextNode} node
+ * @param {Object} options
+ * @return {Function|null} textNodeLinkFn
+ */
+
+ function compileTextNode(node, options) {
+ // skip marked text nodes
+ if (node._skip) {
+ return removeText;
+ }
+
+ var tokens = parseText(node.wholeText);
+ if (!tokens) {
+ return null;
+ }
+
+ // mark adjacent text nodes as skipped,
+ // because we are using node.wholeText to compile
+ // all adjacent text nodes together. This fixes
+ // issues in IE where sometimes it splits up a single
+ // text node into multiple ones.
+ var next = node.nextSibling;
+ while (next && next.nodeType === 3) {
+ next._skip = true;
+ next = next.nextSibling;
+ }
+
+ var frag = document.createDocumentFragment();
+ var el, token;
+ for (var i = 0, l = tokens.length; i < l; i++) {
+ token = tokens[i];
+ el = token.tag ? processTextToken(token, options) : document.createTextNode(token.value);
+ frag.appendChild(el);
+ }
+ return makeTextNodeLinkFn(tokens, frag, options);
+ }
+
+ /**
+ * Linker for an skipped text node.
+ *
+ * @param {Vue} vm
+ * @param {Text} node
+ */
+
+ function removeText(vm, node) {
+ remove(node);
+ }
+
+ /**
+ * Process a single text token.
+ *
+ * @param {Object} token
+ * @param {Object} options
+ * @return {Node}
+ */
+
+ function processTextToken(token, options) {
+ var el;
+ if (token.oneTime) {
+ el = document.createTextNode(token.value);
+ } else {
+ if (token.html) {
+ el = document.createComment('v-html');
+ setTokenType('html');
+ } else {
+ // IE will clean up empty textNodes during
+ // frag.cloneNode(true), so we have to give it
+ // something here...
+ el = document.createTextNode(' ');
+ setTokenType('text');
+ }
+ }
+ function setTokenType(type) {
+ if (token.descriptor) return;
+ var parsed = parseDirective(token.value);
+ token.descriptor = {
+ name: type,
+ def: directives[type],
+ expression: parsed.expression,
+ filters: parsed.filters
+ };
+ }
+ return el;
+ }
+
+ /**
+ * Build a function that processes a textNode.
+ *
+ * @param {Array<Object>} tokens
+ * @param {DocumentFragment} frag
+ */
+
+ function makeTextNodeLinkFn(tokens, frag) {
+ return function textNodeLinkFn(vm, el, host, scope) {
+ var fragClone = frag.cloneNode(true);
+ var childNodes = toArray(fragClone.childNodes);
+ var token, value, node;
+ for (var i = 0, l = tokens.length; i < l; i++) {
+ token = tokens[i];
+ value = token.value;
+ if (token.tag) {
+ node = childNodes[i];
+ if (token.oneTime) {
+ value = (scope || vm).$eval(value);
+ if (token.html) {
+ replace(node, parseTemplate(value, true));
+ } else {
+ node.data = _toString(value);
+ }
+ } else {
+ vm._bindDir(token.descriptor, node, host, scope);
+ }
+ }
+ }
+ replace(el, fragClone);
+ };
+ }
+
+ /**
+ * Compile a node list and return a childLinkFn.
+ *
+ * @param {NodeList} nodeList
+ * @param {Object} options
+ * @return {Function|undefined}
+ */
+
+ function compileNodeList(nodeList, options) {
+ var linkFns = [];
+ var nodeLinkFn, childLinkFn, node;
+ for (var i = 0, l = nodeList.length; i < l; i++) {
+ node = nodeList[i];
+ nodeLinkFn = compileNode(node, options);
+ childLinkFn = !(nodeLinkFn && nodeLinkFn.terminal) && node.tagName !== 'SCRIPT' && node.hasChildNodes() ? compileNodeList(node.childNodes, options) : null;
+ linkFns.push(nodeLinkFn, childLinkFn);
+ }
+ return linkFns.length ? makeChildLinkFn(linkFns) : null;
+ }
+
+ /**
+ * Make a child link function for a node's childNodes.
+ *
+ * @param {Array<Function>} linkFns
+ * @return {Function} childLinkFn
+ */
+
+ function makeChildLinkFn(linkFns) {
+ return function childLinkFn(vm, nodes, host, scope, frag) {
+ var node, nodeLinkFn, childrenLinkFn;
+ for (var i = 0, n = 0, l = linkFns.length; i < l; n++) {
+ node = nodes[n];
+ nodeLinkFn = linkFns[i++];
+ childrenLinkFn = linkFns[i++];
+ // cache childNodes before linking parent, fix #657
+ var childNodes = toArray(node.childNodes);
+ if (nodeLinkFn) {
+ nodeLinkFn(vm, node, host, scope, frag);
+ }
+ if (childrenLinkFn) {
+ childrenLinkFn(vm, childNodes, host, scope, frag);
+ }
+ }
+ };
+ }
+
+ /**
+ * Check for element directives (custom elements that should
+ * be resovled as terminal directives).
+ *
+ * @param {Element} el
+ * @param {Object} options
+ */
+
+ function checkElementDirectives(el, options) {
+ var tag = el.tagName.toLowerCase();
+ if (commonTagRE.test(tag)) {
+ return;
+ }
+ var def = resolveAsset(options, 'elementDirectives', tag);
+ if (def) {
+ return makeTerminalNodeLinkFn(el, tag, '', options, def);
+ }
+ }
+
+ /**
+ * Check if an element is a component. If yes, return
+ * a component link function.
+ *
+ * @param {Element} el
+ * @param {Object} options
+ * @return {Function|undefined}
+ */
+
+ function checkComponent(el, options) {
+ var component = checkComponentAttr(el, options);
+ if (component) {
+ var ref = findRef(el);
+ var descriptor = {
+ name: 'component',
+ ref: ref,
+ expression: component.id,
+ def: internalDirectives.component,
+ modifiers: {
+ literal: !component.dynamic
+ }
+ };
+ var componentLinkFn = function componentLinkFn(vm, el, host, scope, frag) {
+ if (ref) {
+ defineReactive((scope || vm).$refs, ref, null);
+ }
+ vm._bindDir(descriptor, el, host, scope, frag);
+ };
+ componentLinkFn.terminal = true;
+ return componentLinkFn;
+ }
+ }
+
+ /**
+ * Check an element for terminal directives in fixed order.
+ * If it finds one, return a terminal link function.
+ *
+ * @param {Element} el
+ * @param {Array} attrs
+ * @param {Object} options
+ * @return {Function} terminalLinkFn
+ */
+
+ function checkTerminalDirectives(el, attrs, options) {
+ // skip v-pre
+ if (getAttr(el, 'v-pre') !== null) {
+ return skip;
+ }
+ // skip v-else block, but only if following v-if
+ if (el.hasAttribute('v-else')) {
+ var prev = el.previousElementSibling;
+ if (prev && prev.hasAttribute('v-if')) {
+ return skip;
+ }
+ }
+
+ var attr, name, value, modifiers, matched, dirName, rawName, arg, def, termDef;
+ for (var i = 0, j = attrs.length; i < j; i++) {
+ attr = attrs[i];
+ name = attr.name.replace(modifierRE, '');
+ if (matched = name.match(dirAttrRE)) {
+ def = resolveAsset(options, 'directives', matched[1]);
+ if (def && def.terminal) {
+ if (!termDef || (def.priority || DEFAULT_TERMINAL_PRIORITY) > termDef.priority) {
+ termDef = def;
+ rawName = attr.name;
+ modifiers = parseModifiers(attr.name);
+ value = attr.value;
+ dirName = matched[1];
+ arg = matched[2];
+ }
+ }
+ }
+ }
+
+ if (termDef) {
+ return makeTerminalNodeLinkFn(el, dirName, value, options, termDef, rawName, arg, modifiers);
+ }
+ }
+
+ function skip() {}
+ skip.terminal = true;
+
+ /**
+ * Build a node link function for a terminal directive.
+ * A terminal link function terminates the current
+ * compilation recursion and handles compilation of the
+ * subtree in the directive.
+ *
+ * @param {Element} el
+ * @param {String} dirName
+ * @param {String} value
+ * @param {Object} options
+ * @param {Object} def
+ * @param {String} [rawName]
+ * @param {String} [arg]
+ * @param {Object} [modifiers]
+ * @return {Function} terminalLinkFn
+ */
+
+ function makeTerminalNodeLinkFn(el, dirName, value, options, def, rawName, arg, modifiers) {
+ var parsed = parseDirective(value);
+ var descriptor = {
+ name: dirName,
+ arg: arg,
+ expression: parsed.expression,
+ filters: parsed.filters,
+ raw: value,
+ attr: rawName,
+ modifiers: modifiers,
+ def: def
+ };
+ // check ref for v-for and router-view
+ if (dirName === 'for' || dirName === 'router-view') {
+ descriptor.ref = findRef(el);
+ }
+ var fn = function terminalNodeLinkFn(vm, el, host, scope, frag) {
+ if (descriptor.ref) {
+ defineReactive((scope || vm).$refs, descriptor.ref, null);
+ }
+ vm._bindDir(descriptor, el, host, scope, frag);
+ };
+ fn.terminal = true;
+ return fn;
+ }
+
+ /**
+ * Compile the directives on an element and return a linker.
+ *
+ * @param {Array|NamedNodeMap} attrs
+ * @param {Object} options
+ * @return {Function}
+ */
+
+ function compileDirectives(attrs, options) {
+ var i = attrs.length;
+ var dirs = [];
+ var attr, name, value, rawName, rawValue, dirName, arg, modifiers, dirDef, tokens, matched;
+ while (i--) {
+ attr = attrs[i];
+ name = rawName = attr.name;
+ value = rawValue = attr.value;
+ tokens = parseText(value);
+ // reset arg
+ arg = null;
+ // check modifiers
+ modifiers = parseModifiers(name);
+ name = name.replace(modifierRE, '');
+
+ // attribute interpolations
+ if (tokens) {
+ value = tokensToExp(tokens);
+ arg = name;
+ pushDir('bind', directives.bind, tokens);
+ // warn against mixing mustaches with v-bind
+ if ('development' !== 'production') {
+ if (name === 'class' && Array.prototype.some.call(attrs, function (attr) {
+ return attr.name === ':class' || attr.name === 'v-bind:class';
+ })) {
+ warn('class="' + rawValue + '": Do not mix mustache interpolation ' + 'and v-bind for "class" on the same element. Use one or the other.', options);
+ }
+ }
+ } else
+
+ // special attribute: transition
+ if (transitionRE.test(name)) {
+ modifiers.literal = !bindRE.test(name);
+ pushDir('transition', internalDirectives.transition);
+ } else
+
+ // event handlers
+ if (onRE.test(name)) {
+ arg = name.replace(onRE, '');
+ pushDir('on', directives.on);
+ } else
+
+ // attribute bindings
+ if (bindRE.test(name)) {
+ dirName = name.replace(bindRE, '');
+ if (dirName === 'style' || dirName === 'class') {
+ pushDir(dirName, internalDirectives[dirName]);
+ } else {
+ arg = dirName;
+ pushDir('bind', directives.bind);
+ }
+ } else
+
+ // normal directives
+ if (matched = name.match(dirAttrRE)) {
+ dirName = matched[1];
+ arg = matched[2];
+
+ // skip v-else (when used with v-show)
+ if (dirName === 'else') {
+ continue;
+ }
+
+ dirDef = resolveAsset(options, 'directives', dirName, true);
+ if (dirDef) {
+ pushDir(dirName, dirDef);
+ }
+ }
+ }
+
+ /**
+ * Push a directive.
+ *
+ * @param {String} dirName
+ * @param {Object|Function} def
+ * @param {Array} [interpTokens]
+ */
+
+ function pushDir(dirName, def, interpTokens) {
+ var hasOneTimeToken = interpTokens && hasOneTime(interpTokens);
+ var parsed = !hasOneTimeToken && parseDirective(value);
+ dirs.push({
+ name: dirName,
+ attr: rawName,
+ raw: rawValue,
+ def: def,
+ arg: arg,
+ modifiers: modifiers,
+ // conversion from interpolation strings with one-time token
+ // to expression is differed until directive bind time so that we
+ // have access to the actual vm context for one-time bindings.
+ expression: parsed && parsed.expression,
+ filters: parsed && parsed.filters,
+ interp: interpTokens,
+ hasOneTime: hasOneTimeToken
+ });
+ }
+
+ if (dirs.length) {
+ return makeNodeLinkFn(dirs);
+ }
+ }
+
+ /**
+ * Parse modifiers from directive attribute name.
+ *
+ * @param {String} name
+ * @return {Object}
+ */
+
+ function parseModifiers(name) {
+ var res = Object.create(null);
+ var match = name.match(modifierRE);
+ if (match) {
+ var i = match.length;
+ while (i--) {
+ res[match[i].slice(1)] = true;
+ }
+ }
+ return res;
+ }
+
+ /**
+ * Build a link function for all directives on a single node.
+ *
+ * @param {Array} directives
+ * @return {Function} directivesLinkFn
+ */
+
+ function makeNodeLinkFn(directives) {
+ return function nodeLinkFn(vm, el, host, scope, frag) {
+ // reverse apply because it's sorted low to high
+ var i = directives.length;
+ while (i--) {
+ vm._bindDir(directives[i], el, host, scope, frag);
+ }
+ };
+ }
+
+ /**
+ * Check if an interpolation string contains one-time tokens.
+ *
+ * @param {Array} tokens
+ * @return {Boolean}
+ */
+
+ function hasOneTime(tokens) {
+ var i = tokens.length;
+ while (i--) {
+ if (tokens[i].oneTime) return true;
+ }
+ }
+
+ function isScript(el) {
+ return el.tagName === 'SCRIPT' && (!el.hasAttribute('type') || el.getAttribute('type') === 'text/javascript');
+ }
+
+ var specialCharRE = /[^\w\-:\.]/;
+
+ /**
+ * Process an element or a DocumentFragment based on a
+ * instance option object. This allows us to transclude
+ * a template node/fragment before the instance is created,
+ * so the processed fragment can then be cloned and reused
+ * in v-for.
+ *
+ * @param {Element} el
+ * @param {Object} options
+ * @return {Element|DocumentFragment}
+ */
+
+ function transclude(el, options) {
+ // extract container attributes to pass them down
+ // to compiler, because they need to be compiled in
+ // parent scope. we are mutating the options object here
+ // assuming the same object will be used for compile
+ // right after this.
+ if (options) {
+ options._containerAttrs = extractAttrs(el);
+ }
+ // for template tags, what we want is its content as
+ // a documentFragment (for fragment instances)
+ if (isTemplate(el)) {
+ el = parseTemplate(el);
+ }
+ if (options) {
+ if (options._asComponent && !options.template) {
+ options.template = '<slot></slot>';
+ }
+ if (options.template) {
+ options._content = extractContent(el);
+ el = transcludeTemplate(el, options);
+ }
+ }
+ if (isFragment(el)) {
+ // anchors for fragment instance
+ // passing in `persist: true` to avoid them being
+ // discarded by IE during template cloning
+ prepend(createAnchor('v-start', true), el);
+ el.appendChild(createAnchor('v-end', true));
+ }
+ return el;
+ }
+
+ /**
+ * Process the template option.
+ * If the replace option is true this will swap the $el.
+ *
+ * @param {Element} el
+ * @param {Object} options
+ * @return {Element|DocumentFragment}
+ */
+
+ function transcludeTemplate(el, options) {
+ var template = options.template;
+ var frag = parseTemplate(template, true);
+ if (frag) {
+ var replacer = frag.firstChild;
+ var tag = replacer.tagName && replacer.tagName.toLowerCase();
+ if (options.replace) {
+ /* istanbul ignore if */
+ if (el === document.body) {
+ 'development' !== 'production' && warn('You are mounting an instance with a template to ' + '<body>. This will replace <body> entirely. You ' + 'should probably use `replace: false` here.');
+ }
+ // there are many cases where the instance must
+ // become a fragment instance: basically anything that
+ // can create more than 1 root nodes.
+ if (
+ // multi-children template
+ frag.childNodes.length > 1 ||
+ // non-element template
+ replacer.nodeType !== 1 ||
+ // single nested component
+ tag === 'component' || resolveAsset(options, 'components', tag) || hasBindAttr(replacer, 'is') ||
+ // element directive
+ resolveAsset(options, 'elementDirectives', tag) ||
+ // for block
+ replacer.hasAttribute('v-for') ||
+ // if block
+ replacer.hasAttribute('v-if')) {
+ return frag;
+ } else {
+ options._replacerAttrs = extractAttrs(replacer);
+ mergeAttrs(el, replacer);
+ return replacer;
+ }
+ } else {
+ el.appendChild(frag);
+ return el;
+ }
+ } else {
+ 'development' !== 'production' && warn('Invalid template option: ' + template);
+ }
+ }
+
+ /**
+ * Helper to extract a component container's attributes
+ * into a plain object array.
+ *
+ * @param {Element} el
+ * @return {Array}
+ */
+
+ function extractAttrs(el) {
+ if (el.nodeType === 1 && el.hasAttributes()) {
+ return toArray(el.attributes);
+ }
+ }
+
+ /**
+ * Merge the attributes of two elements, and make sure
+ * the class names are merged properly.
+ *
+ * @param {Element} from
+ * @param {Element} to
+ */
+
+ function mergeAttrs(from, to) {
+ var attrs = from.attributes;
+ var i = attrs.length;
+ var name, value;
+ while (i--) {
+ name = attrs[i].name;
+ value = attrs[i].value;
+ if (!to.hasAttribute(name) && !specialCharRE.test(name)) {
+ to.setAttribute(name, value);
+ } else if (name === 'class' && !parseText(value) && (value = value.trim())) {
+ value.split(/\s+/).forEach(function (cls) {
+ addClass(to, cls);
+ });
+ }
+ }
+ }
+
+ /**
+ * Scan and determine slot content distribution.
+ * We do this during transclusion instead at compile time so that
+ * the distribution is decoupled from the compilation order of
+ * the slots.
+ *
+ * @param {Element|DocumentFragment} template
+ * @param {Element} content
+ * @param {Vue} vm
+ */
+
+ function resolveSlots(vm, content) {
+ if (!content) {
+ return;
+ }
+ var contents = vm._slotContents = Object.create(null);
+ var el, name;
+ for (var i = 0, l = content.children.length; i < l; i++) {
+ el = content.children[i];
+ /* eslint-disable no-cond-assign */
+ if (name = el.getAttribute('slot')) {
+ (contents[name] || (contents[name] = [])).push(el);
+ }
+ /* eslint-enable no-cond-assign */
+ if ('development' !== 'production' && getBindAttr(el, 'slot')) {
+ warn('The "slot" attribute must be static.', vm.$parent);
+ }
+ }
+ for (name in contents) {
+ contents[name] = extractFragment(contents[name], content);
+ }
+ if (content.hasChildNodes()) {
+ var nodes = content.childNodes;
+ if (nodes.length === 1 && nodes[0].nodeType === 3 && !nodes[0].data.trim()) {
+ return;
+ }
+ contents['default'] = extractFragment(content.childNodes, content);
+ }
+ }
+
+ /**
+ * Extract qualified content nodes from a node list.
+ *
+ * @param {NodeList} nodes
+ * @return {DocumentFragment}
+ */
+
+ function extractFragment(nodes, parent) {
+ var frag = document.createDocumentFragment();
+ nodes = toArray(nodes);
+ for (var i = 0, l = nodes.length; i < l; i++) {
+ var node = nodes[i];
+ if (isTemplate(node) && !node.hasAttribute('v-if') && !node.hasAttribute('v-for')) {
+ parent.removeChild(node);
+ node = parseTemplate(node, true);
+ }
+ frag.appendChild(node);
+ }
+ return frag;
+ }
+
+
+
+ var compiler = Object.freeze({
+ compile: compile,
+ compileAndLinkProps: compileAndLinkProps,
+ compileRoot: compileRoot,
+ transclude: transclude,
+ resolveSlots: resolveSlots
+ });
+
+ function stateMixin (Vue) {
+ /**
+ * Accessor for `$data` property, since setting $data
+ * requires observing the new object and updating
+ * proxied properties.
+ */
+
+ Object.defineProperty(Vue.prototype, '$data', {
+ get: function get() {
+ return this._data;
+ },
+ set: function set(newData) {
+ if (newData !== this._data) {
+ this._setData(newData);
+ }
+ }
+ });
+
+ /**
+ * Setup the scope of an instance, which contains:
+ * - observed data
+ * - computed properties
+ * - user methods
+ * - meta properties
+ */
+
+ Vue.prototype._initState = function () {
+ this._initProps();
+ this._initMeta();
+ this._initMethods();
+ this._initData();
+ this._initComputed();
+ };
+
+ /**
+ * Initialize props.
+ */
+
+ Vue.prototype._initProps = function () {
+ var options = this.$options;
+ var el = options.el;
+ var props = options.props;
+ if (props && !el) {
+ 'development' !== 'production' && warn('Props will not be compiled if no `el` option is ' + 'provided at instantiation.', this);
+ }
+ // make sure to convert string selectors into element now
+ el = options.el = query(el);
+ this._propsUnlinkFn = el && el.nodeType === 1 && props
+ // props must be linked in proper scope if inside v-for
+ ? compileAndLinkProps(this, el, props, this._scope) : null;
+ };
+
+ /**
+ * Initialize the data.
+ */
+
+ Vue.prototype._initData = function () {
+ var dataFn = this.$options.data;
+ var data = this._data = dataFn ? dataFn() : {};
+ if (!isPlainObject(data)) {
+ data = {};
+ 'development' !== 'production' && warn('data functions should return an object.', this);
+ }
+ var props = this._props;
+ // proxy data on instance
+ var keys = Object.keys(data);
+ var i, key;
+ i = keys.length;
+ while (i--) {
+ key = keys[i];
+ // there are two scenarios where we can proxy a data key:
+ // 1. it's not already defined as a prop
+ // 2. it's provided via a instantiation option AND there are no
+ // template prop present
+ if (!props || !hasOwn(props, key)) {
+ this._proxy(key);
+ } else if ('development' !== 'production') {
+ warn('Data field "' + key + '" is already defined ' + 'as a prop. To provide default value for a prop, use the "default" ' + 'prop option; if you want to pass prop values to an instantiation ' + 'call, use the "propsData" option.', this);
+ }
+ }
+ // observe data
+ observe(data, this);
+ };
+
+ /**
+ * Swap the instance's $data. Called in $data's setter.
+ *
+ * @param {Object} newData
+ */
+
+ Vue.prototype._setData = function (newData) {
+ newData = newData || {};
+ var oldData = this._data;
+ this._data = newData;
+ var keys, key, i;
+ // unproxy keys not present in new data
+ keys = Object.keys(oldData);
+ i = keys.length;
+ while (i--) {
+ key = keys[i];
+ if (!(key in newData)) {
+ this._unproxy(key);
+ }
+ }
+ // proxy keys not already proxied,
+ // and trigger change for changed values
+ keys = Object.keys(newData);
+ i = keys.length;
+ while (i--) {
+ key = keys[i];
+ if (!hasOwn(this, key)) {
+ // new property
+ this._proxy(key);
+ }
+ }
+ oldData.__ob__.removeVm(this);
+ observe(newData, this);
+ this._digest();
+ };
+
+ /**
+ * Proxy a property, so that
+ * vm.prop === vm._data.prop
+ *
+ * @param {String} key
+ */
+
+ Vue.prototype._proxy = function (key) {
+ if (!isReserved(key)) {
+ // need to store ref to self here
+ // because these getter/setters might
+ // be called by child scopes via
+ // prototype inheritance.
+ var self = this;
+ Object.defineProperty(self, key, {
+ configurable: true,
+ enumerable: true,
+ get: function proxyGetter() {
+ return self._data[key];
+ },
+ set: function proxySetter(val) {
+ self._data[key] = val;
+ }
+ });
+ }
+ };
+
+ /**
+ * Unproxy a property.
+ *
+ * @param {String} key
+ */
+
+ Vue.prototype._unproxy = function (key) {
+ if (!isReserved(key)) {
+ delete this[key];
+ }
+ };
+
+ /**
+ * Force update on every watcher in scope.
+ */
+
+ Vue.prototype._digest = function () {
+ for (var i = 0, l = this._watchers.length; i < l; i++) {
+ this._watchers[i].update(true); // shallow updates
+ }
+ };
+
+ /**
+ * Setup computed properties. They are essentially
+ * special getter/setters
+ */
+
+ function noop() {}
+ Vue.prototype._initComputed = function () {
+ var computed = this.$options.computed;
+ if (computed) {
+ for (var key in computed) {
+ var userDef = computed[key];
+ var def = {
+ enumerable: true,
+ configurable: true
+ };
+ if (typeof userDef === 'function') {
+ def.get = makeComputedGetter(userDef, this);
+ def.set = noop;
+ } else {
+ def.get = userDef.get ? userDef.cache !== false ? makeComputedGetter(userDef.get, this) : bind(userDef.get, this) : noop;
+ def.set = userDef.set ? bind(userDef.set, this) : noop;
+ }
+ Object.defineProperty(this, key, def);
+ }
+ }
+ };
+
+ function makeComputedGetter(getter, owner) {
+ var watcher = new Watcher(owner, getter, null, {
+ lazy: true
+ });
+ return function computedGetter() {
+ if (watcher.dirty) {
+ watcher.evaluate();
+ }
+ if (Dep.target) {
+ watcher.depend();
+ }
+ return watcher.value;
+ };
+ }
+
+ /**
+ * Setup instance methods. Methods must be bound to the
+ * instance since they might be passed down as a prop to
+ * child components.
+ */
+
+ Vue.prototype._initMethods = function () {
+ var methods = this.$options.methods;
+ if (methods) {
+ for (var key in methods) {
+ this[key] = bind(methods[key], this);
+ }
+ }
+ };
+
+ /**
+ * Initialize meta information like $index, $key & $value.
+ */
+
+ Vue.prototype._initMeta = function () {
+ var metas = this.$options._meta;
+ if (metas) {
+ for (var key in metas) {
+ defineReactive(this, key, metas[key]);
+ }
+ }
+ };
+ }
+
+ var eventRE = /^v-on:|^@/;
+
+ function eventsMixin (Vue) {
+ /**
+ * Setup the instance's option events & watchers.
+ * If the value is a string, we pull it from the
+ * instance's methods by name.
+ */
+
+ Vue.prototype._initEvents = function () {
+ var options = this.$options;
+ if (options._asComponent) {
+ registerComponentEvents(this, options.el);
+ }
+ registerCallbacks(this, '$on', options.events);
+ registerCallbacks(this, '$watch', options.watch);
+ };
+
+ /**
+ * Register v-on events on a child component
+ *
+ * @param {Vue} vm
+ * @param {Element} el
+ */
+
+ function registerComponentEvents(vm, el) {
+ var attrs = el.attributes;
+ var name, value, handler;
+ for (var i = 0, l = attrs.length; i < l; i++) {
+ name = attrs[i].name;
+ if (eventRE.test(name)) {
+ name = name.replace(eventRE, '');
+ // force the expression into a statement so that
+ // it always dynamically resolves the method to call (#2670)
+ // kinda ugly hack, but does the job.
+ value = attrs[i].value;
+ if (isSimplePath(value)) {
+ value += '.apply(this, $arguments)';
+ }
+ handler = (vm._scope || vm._context).$eval(value, true);
+ handler._fromParent = true;
+ vm.$on(name.replace(eventRE), handler);
+ }
+ }
+ }
+
+ /**
+ * Register callbacks for option events and watchers.
+ *
+ * @param {Vue} vm
+ * @param {String} action
+ * @param {Object} hash
+ */
+
+ function registerCallbacks(vm, action, hash) {
+ if (!hash) return;
+ var handlers, key, i, j;
+ for (key in hash) {
+ handlers = hash[key];
+ if (isArray(handlers)) {
+ for (i = 0, j = handlers.length; i < j; i++) {
+ register(vm, action, key, handlers[i]);
+ }
+ } else {
+ register(vm, action, key, handlers);
+ }
+ }
+ }
+
+ /**
+ * Helper to register an event/watch callback.
+ *
+ * @param {Vue} vm
+ * @param {String} action
+ * @param {String} key
+ * @param {Function|String|Object} handler
+ * @param {Object} [options]
+ */
+
+ function register(vm, action, key, handler, options) {
+ var type = typeof handler;
+ if (type === 'function') {
+ vm[action](key, handler, options);
+ } else if (type === 'string') {
+ var methods = vm.$options.methods;
+ var method = methods && methods[handler];
+ if (method) {
+ vm[action](key, method, options);
+ } else {
+ 'development' !== 'production' && warn('Unknown method: "' + handler + '" when ' + 'registering callback for ' + action + ': "' + key + '".', vm);
+ }
+ } else if (handler && type === 'object') {
+ register(vm, action, key, handler.handler, handler);
+ }
+ }
+
+ /**
+ * Setup recursive attached/detached calls
+ */
+
+ Vue.prototype._initDOMHooks = function () {
+ this.$on('hook:attached', onAttached);
+ this.$on('hook:detached', onDetached);
+ };
+
+ /**
+ * Callback to recursively call attached hook on children
+ */
+
+ function onAttached() {
+ if (!this._isAttached) {
+ this._isAttached = true;
+ this.$children.forEach(callAttach);
+ }
+ }
+
+ /**
+ * Iterator to call attached hook
+ *
+ * @param {Vue} child
+ */
+
+ function callAttach(child) {
+ if (!child._isAttached && inDoc(child.$el)) {
+ child._callHook('attached');
+ }
+ }
+
+ /**
+ * Callback to recursively call detached hook on children
+ */
+
+ function onDetached() {
+ if (this._isAttached) {
+ this._isAttached = false;
+ this.$children.forEach(callDetach);
+ }
+ }
+
+ /**
+ * Iterator to call detached hook
+ *
+ * @param {Vue} child
+ */
+
+ function callDetach(child) {
+ if (child._isAttached && !inDoc(child.$el)) {
+ child._callHook('detached');
+ }
+ }
+
+ /**
+ * Trigger all handlers for a hook
+ *
+ * @param {String} hook
+ */
+
+ Vue.prototype._callHook = function (hook) {
+ this.$emit('pre-hook:' + hook);
+ var handlers = this.$options[hook];
+ if (handlers) {
+ for (var i = 0, j = handlers.length; i < j; i++) {
+ handlers[i].call(this);
+ }
+ }
+ this.$emit('hook:' + hook);
+ };
+ }
+
+ function noop$1() {}
+
+ /**
+ * A directive links a DOM element with a piece of data,
+ * which is the result of evaluating an expression.
+ * It registers a watcher with the expression and calls
+ * the DOM update function when a change is triggered.
+ *
+ * @param {Object} descriptor
+ * - {String} name
+ * - {Object} def
+ * - {String} expression
+ * - {Array<Object>} [filters]
+ * - {Object} [modifiers]
+ * - {Boolean} literal
+ * - {String} attr
+ * - {String} arg
+ * - {String} raw
+ * - {String} [ref]
+ * - {Array<Object>} [interp]
+ * - {Boolean} [hasOneTime]
+ * @param {Vue} vm
+ * @param {Node} el
+ * @param {Vue} [host] - transclusion host component
+ * @param {Object} [scope] - v-for scope
+ * @param {Fragment} [frag] - owner fragment
+ * @constructor
+ */
+ function Directive(descriptor, vm, el, host, scope, frag) {
+ this.vm = vm;
+ this.el = el;
+ // copy descriptor properties
+ this.descriptor = descriptor;
+ this.name = descriptor.name;
+ this.expression = descriptor.expression;
+ this.arg = descriptor.arg;
+ this.modifiers = descriptor.modifiers;
+ this.filters = descriptor.filters;
+ this.literal = this.modifiers && this.modifiers.literal;
+ // private
+ this._locked = false;
+ this._bound = false;
+ this._listeners = null;
+ // link context
+ this._host = host;
+ this._scope = scope;
+ this._frag = frag;
+ // store directives on node in dev mode
+ if ('development' !== 'production' && this.el) {
+ this.el._vue_directives = this.el._vue_directives || [];
+ this.el._vue_directives.push(this);
+ }
+ }
+
+ /**
+ * Initialize the directive, mixin definition properties,
+ * setup the watcher, call definition bind() and update()
+ * if present.
+ */
+
+ Directive.prototype._bind = function () {
+ var name = this.name;
+ var descriptor = this.descriptor;
+
+ // remove attribute
+ if ((name !== 'cloak' || this.vm._isCompiled) && this.el && this.el.removeAttribute) {
+ var attr = descriptor.attr || 'v-' + name;
+ this.el.removeAttribute(attr);
+ }
+
+ // copy def properties
+ var def = descriptor.def;
+ if (typeof def === 'function') {
+ this.update = def;
+ } else {
+ extend(this, def);
+ }
+
+ // setup directive params
+ this._setupParams();
+
+ // initial bind
+ if (this.bind) {
+ this.bind();
+ }
+ this._bound = true;
+
+ if (this.literal) {
+ this.update && this.update(descriptor.raw);
+ } else if ((this.expression || this.modifiers) && (this.update || this.twoWay) && !this._checkStatement()) {
+ // wrapped updater for context
+ var dir = this;
+ if (this.update) {
+ this._update = function (val, oldVal) {
+ if (!dir._locked) {
+ dir.update(val, oldVal);
+ }
+ };
+ } else {
+ this._update = noop$1;
+ }
+ var preProcess = this._preProcess ? bind(this._preProcess, this) : null;
+ var postProcess = this._postProcess ? bind(this._postProcess, this) : null;
+ var watcher = this._watcher = new Watcher(this.vm, this.expression, this._update, // callback
+ {
+ filters: this.filters,
+ twoWay: this.twoWay,
+ deep: this.deep,
+ preProcess: preProcess,
+ postProcess: postProcess,
+ scope: this._scope
+ });
+ // v-model with inital inline value need to sync back to
+ // model instead of update to DOM on init. They would
+ // set the afterBind hook to indicate that.
+ if (this.afterBind) {
+ this.afterBind();
+ } else if (this.update) {
+ this.update(watcher.value);
+ }
+ }
+ };
+
+ /**
+ * Setup all param attributes, e.g. track-by,
+ * transition-mode, etc...
+ */
+
+ Directive.prototype._setupParams = function () {
+ if (!this.params) {
+ return;
+ }
+ var params = this.params;
+ // swap the params array with a fresh object.
+ this.params = Object.create(null);
+ var i = params.length;
+ var key, val, mappedKey;
+ while (i--) {
+ key = hyphenate(params[i]);
+ mappedKey = camelize(key);
+ val = getBindAttr(this.el, key);
+ if (val != null) {
+ // dynamic
+ this._setupParamWatcher(mappedKey, val);
+ } else {
+ // static
+ val = getAttr(this.el, key);
+ if (val != null) {
+ this.params[mappedKey] = val === '' ? true : val;
+ }
+ }
+ }
+ };
+
+ /**
+ * Setup a watcher for a dynamic param.
+ *
+ * @param {String} key
+ * @param {String} expression
+ */
+
+ Directive.prototype._setupParamWatcher = function (key, expression) {
+ var self = this;
+ var called = false;
+ var unwatch = (this._scope || this.vm).$watch(expression, function (val, oldVal) {
+ self.params[key] = val;
+ // since we are in immediate mode,
+ // only call the param change callbacks if this is not the first update.
+ if (called) {
+ var cb = self.paramWatchers && self.paramWatchers[key];
+ if (cb) {
+ cb.call(self, val, oldVal);
+ }
+ } else {
+ called = true;
+ }
+ }, {
+ immediate: true,
+ user: false
+ });(this._paramUnwatchFns || (this._paramUnwatchFns = [])).push(unwatch);
+ };
+
+ /**
+ * Check if the directive is a function caller
+ * and if the expression is a callable one. If both true,
+ * we wrap up the expression and use it as the event
+ * handler.
+ *
+ * e.g. on-click="a++"
+ *
+ * @return {Boolean}
+ */
+
+ Directive.prototype._checkStatement = function () {
+ var expression = this.expression;
+ if (expression && this.acceptStatement && !isSimplePath(expression)) {
+ var fn = parseExpression(expression).get;
+ var scope = this._scope || this.vm;
+ var handler = function handler(e) {
+ scope.$event = e;
+ fn.call(scope, scope);
+ scope.$event = null;
+ };
+ if (this.filters) {
+ handler = scope._applyFilters(handler, null, this.filters);
+ }
+ this.update(handler);
+ return true;
+ }
+ };
+
+ /**
+ * Set the corresponding value with the setter.
+ * This should only be used in two-way directives
+ * e.g. v-model.
+ *
+ * @param {*} value
+ * @public
+ */
+
+ Directive.prototype.set = function (value) {
+ /* istanbul ignore else */
+ if (this.twoWay) {
+ this._withLock(function () {
+ this._watcher.set(value);
+ });
+ } else if ('development' !== 'production') {
+ warn('Directive.set() can only be used inside twoWay' + 'directives.');
+ }
+ };
+
+ /**
+ * Execute a function while preventing that function from
+ * triggering updates on this directive instance.
+ *
+ * @param {Function} fn
+ */
+
+ Directive.prototype._withLock = function (fn) {
+ var self = this;
+ self._locked = true;
+ fn.call(self);
+ nextTick(function () {
+ self._locked = false;
+ });
+ };
+
+ /**
+ * Convenience method that attaches a DOM event listener
+ * to the directive element and autometically tears it down
+ * during unbind.
+ *
+ * @param {String} event
+ * @param {Function} handler
+ * @param {Boolean} [useCapture]
+ */
+
+ Directive.prototype.on = function (event, handler, useCapture) {
+ on(this.el, event, handler, useCapture);(this._listeners || (this._listeners = [])).push([event, handler]);
+ };
+
+ /**
+ * Teardown the watcher and call unbind.
+ */
+
+ Directive.prototype._teardown = function () {
+ if (this._bound) {
+ this._bound = false;
+ if (this.unbind) {
+ this.unbind();
+ }
+ if (this._watcher) {
+ this._watcher.teardown();
+ }
+ var listeners = this._listeners;
+ var i;
+ if (listeners) {
+ i = listeners.length;
+ while (i--) {
+ off(this.el, listeners[i][0], listeners[i][1]);
+ }
+ }
+ var unwatchFns = this._paramUnwatchFns;
+ if (unwatchFns) {
+ i = unwatchFns.length;
+ while (i--) {
+ unwatchFns[i]();
+ }
+ }
+ if ('development' !== 'production' && this.el) {
+ this.el._vue_directives.$remove(this);
+ }
+ this.vm = this.el = this._watcher = this._listeners = null;
+ }
+ };
+
+ function lifecycleMixin (Vue) {
+ /**
+ * Update v-ref for component.
+ *
+ * @param {Boolean} remove
+ */
+
+ Vue.prototype._updateRef = function (remove) {
+ var ref = this.$options._ref;
+ if (ref) {
+ var refs = (this._scope || this._context).$refs;
+ if (remove) {
+ if (refs[ref] === this) {
+ refs[ref] = null;
+ }
+ } else {
+ refs[ref] = this;
+ }
+ }
+ };
+
+ /**
+ * Transclude, compile and link element.
+ *
+ * If a pre-compiled linker is available, that means the
+ * passed in element will be pre-transcluded and compiled
+ * as well - all we need to do is to call the linker.
+ *
+ * Otherwise we need to call transclude/compile/link here.
+ *
+ * @param {Element} el
+ */
+
+ Vue.prototype._compile = function (el) {
+ var options = this.$options;
+
+ // transclude and init element
+ // transclude can potentially replace original
+ // so we need to keep reference; this step also injects
+ // the template and caches the original attributes
+ // on the container node and replacer node.
+ var original = el;
+ el = transclude(el, options);
+ this._initElement(el);
+
+ // handle v-pre on root node (#2026)
+ if (el.nodeType === 1 && getAttr(el, 'v-pre') !== null) {
+ return;
+ }
+
+ // root is always compiled per-instance, because
+ // container attrs and props can be different every time.
+ var contextOptions = this._context && this._context.$options;
+ var rootLinker = compileRoot(el, options, contextOptions);
+
+ // resolve slot distribution
+ resolveSlots(this, options._content);
+
+ // compile and link the rest
+ var contentLinkFn;
+ var ctor = this.constructor;
+ // component compilation can be cached
+ // as long as it's not using inline-template
+ if (options._linkerCachable) {
+ contentLinkFn = ctor.linker;
+ if (!contentLinkFn) {
+ contentLinkFn = ctor.linker = compile(el, options);
+ }
+ }
+
+ // link phase
+ // make sure to link root with prop scope!
+ var rootUnlinkFn = rootLinker(this, el, this._scope);
+ var contentUnlinkFn = contentLinkFn ? contentLinkFn(this, el) : compile(el, options)(this, el);
+
+ // register composite unlink function
+ // to be called during instance destruction
+ this._unlinkFn = function () {
+ rootUnlinkFn();
+ // passing destroying: true to avoid searching and
+ // splicing the directives
+ contentUnlinkFn(true);
+ };
+
+ // finally replace original
+ if (options.replace) {
+ replace(original, el);
+ }
+
+ this._isCompiled = true;
+ this._callHook('compiled');
+ };
+
+ /**
+ * Initialize instance element. Called in the public
+ * $mount() method.
+ *
+ * @param {Element} el
+ */
+
+ Vue.prototype._initElement = function (el) {
+ if (isFragment(el)) {
+ this._isFragment = true;
+ this.$el = this._fragmentStart = el.firstChild;
+ this._fragmentEnd = el.lastChild;
+ // set persisted text anchors to empty
+ if (this._fragmentStart.nodeType === 3) {
+ this._fragmentStart.data = this._fragmentEnd.data = '';
+ }
+ this._fragment = el;
+ } else {
+ this.$el = el;
+ }
+ this.$el.__vue__ = this;
+ this._callHook('beforeCompile');
+ };
+
+ /**
+ * Create and bind a directive to an element.
+ *
+ * @param {Object} descriptor - parsed directive descriptor
+ * @param {Node} node - target node
+ * @param {Vue} [host] - transclusion host component
+ * @param {Object} [scope] - v-for scope
+ * @param {Fragment} [frag] - owner fragment
+ */
+
+ Vue.prototype._bindDir = function (descriptor, node, host, scope, frag) {
+ this._directives.push(new Directive(descriptor, this, node, host, scope, frag));
+ };
+
+ /**
+ * Teardown an instance, unobserves the data, unbind all the
+ * directives, turn off all the event listeners, etc.
+ *
+ * @param {Boolean} remove - whether to remove the DOM node.
+ * @param {Boolean} deferCleanup - if true, defer cleanup to
+ * be called later
+ */
+
+ Vue.prototype._destroy = function (remove, deferCleanup) {
+ if (this._isBeingDestroyed) {
+ if (!deferCleanup) {
+ this._cleanup();
+ }
+ return;
+ }
+
+ var destroyReady;
+ var pendingRemoval;
+
+ var self = this;
+ // Cleanup should be called either synchronously or asynchronoysly as
+ // callback of this.$remove(), or if remove and deferCleanup are false.
+ // In any case it should be called after all other removing, unbinding and
+ // turning of is done
+ var cleanupIfPossible = function cleanupIfPossible() {
+ if (destroyReady && !pendingRemoval && !deferCleanup) {
+ self._cleanup();
+ }
+ };
+
+ // remove DOM element
+ if (remove && this.$el) {
+ pendingRemoval = true;
+ this.$remove(function () {
+ pendingRemoval = false;
+ cleanupIfPossible();
+ });
+ }
+
+ this._callHook('beforeDestroy');
+ this._isBeingDestroyed = true;
+ var i;
+ // remove self from parent. only necessary
+ // if parent is not being destroyed as well.
+ var parent = this.$parent;
+ if (parent && !parent._isBeingDestroyed) {
+ parent.$children.$remove(this);
+ // unregister ref (remove: true)
+ this._updateRef(true);
+ }
+ // destroy all children.
+ i = this.$children.length;
+ while (i--) {
+ this.$children[i].$destroy();
+ }
+ // teardown props
+ if (this._propsUnlinkFn) {
+ this._propsUnlinkFn();
+ }
+ // teardown all directives. this also tearsdown all
+ // directive-owned watchers.
+ if (this._unlinkFn) {
+ this._unlinkFn();
+ }
+ i = this._watchers.length;
+ while (i--) {
+ this._watchers[i].teardown();
+ }
+ // remove reference to self on $el
+ if (this.$el) {
+ this.$el.__vue__ = null;
+ }
+
+ destroyReady = true;
+ cleanupIfPossible();
+ };
+
+ /**
+ * Clean up to ensure garbage collection.
+ * This is called after the leave transition if there
+ * is any.
+ */
+
+ Vue.prototype._cleanup = function () {
+ if (this._isDestroyed) {
+ return;
+ }
+ // remove self from owner fragment
+ // do it in cleanup so that we can call $destroy with
+ // defer right when a fragment is about to be removed.
+ if (this._frag) {
+ this._frag.children.$remove(this);
+ }
+ // remove reference from data ob
+ // frozen object may not have observer.
+ if (this._data && this._data.__ob__) {
+ this._data.__ob__.removeVm(this);
+ }
+ // Clean up references to private properties and other
+ // instances. preserve reference to _data so that proxy
+ // accessors still work. The only potential side effect
+ // here is that mutating the instance after it's destroyed
+ // may affect the state of other components that are still
+ // observing the same object, but that seems to be a
+ // reasonable responsibility for the user rather than
+ // always throwing an error on them.
+ this.$el = this.$parent = this.$root = this.$children = this._watchers = this._context = this._scope = this._directives = null;
+ // call the last hook...
+ this._isDestroyed = true;
+ this._callHook('destroyed');
+ // turn off all instance listeners.
+ this.$off();
+ };
+ }
+
+ function miscMixin (Vue) {
+ /**
+ * Apply a list of filter (descriptors) to a value.
+ * Using plain for loops here because this will be called in
+ * the getter of any watcher with filters so it is very
+ * performance sensitive.
+ *
+ * @param {*} value
+ * @param {*} [oldValue]
+ * @param {Array} filters
+ * @param {Boolean} write
+ * @return {*}
+ */
+
+ Vue.prototype._applyFilters = function (value, oldValue, filters, write) {
+ var filter, fn, args, arg, offset, i, l, j, k;
+ for (i = 0, l = filters.length; i < l; i++) {
+ filter = filters[write ? l - i - 1 : i];
+ fn = resolveAsset(this.$options, 'filters', filter.name, true);
+ if (!fn) continue;
+ fn = write ? fn.write : fn.read || fn;
+ if (typeof fn !== 'function') continue;
+ args = write ? [value, oldValue] : [value];
+ offset = write ? 2 : 1;
+ if (filter.args) {
+ for (j = 0, k = filter.args.length; j < k; j++) {
+ arg = filter.args[j];
+ args[j + offset] = arg.dynamic ? this.$get(arg.value) : arg.value;
+ }
+ }
+ value = fn.apply(this, args);
+ }
+ return value;
+ };
+
+ /**
+ * Resolve a component, depending on whether the component
+ * is defined normally or using an async factory function.
+ * Resolves synchronously if already resolved, otherwise
+ * resolves asynchronously and caches the resolved
+ * constructor on the factory.
+ *
+ * @param {String|Function} value
+ * @param {Function} cb
+ */
+
+ Vue.prototype._resolveComponent = function (value, cb) {
+ var factory;
+ if (typeof value === 'function') {
+ factory = value;
+ } else {
+ factory = resolveAsset(this.$options, 'components', value, true);
+ }
+ /* istanbul ignore if */
+ if (!factory) {
+ return;
+ }
+ // async component factory
+ if (!factory.options) {
+ if (factory.resolved) {
+ // cached
+ cb(factory.resolved);
+ } else if (factory.requested) {
+ // pool callbacks
+ factory.pendingCallbacks.push(cb);
+ } else {
+ factory.requested = true;
+ var cbs = factory.pendingCallbacks = [cb];
+ factory.call(this, function resolve(res) {
+ if (isPlainObject(res)) {
+ res = Vue.extend(res);
+ }
+ // cache resolved
+ factory.resolved = res;
+ // invoke callbacks
+ for (var i = 0, l = cbs.length; i < l; i++) {
+ cbs[i](res);
+ }
+ }, function reject(reason) {
+ 'development' !== 'production' && warn('Failed to resolve async component' + (typeof value === 'string' ? ': ' + value : '') + '. ' + (reason ? '\nReason: ' + reason : ''));
+ });
+ }
+ } else {
+ // normal component
+ cb(factory);
+ }
+ };
+ }
+
+ var filterRE$1 = /[^|]\|[^|]/;
+
+ function dataAPI (Vue) {
+ /**
+ * Get the value from an expression on this vm.
+ *
+ * @param {String} exp
+ * @param {Boolean} [asStatement]
+ * @return {*}
+ */
+
+ Vue.prototype.$get = function (exp, asStatement) {
+ var res = parseExpression(exp);
+ if (res) {
+ if (asStatement) {
+ var self = this;
+ return function statementHandler() {
+ self.$arguments = toArray(arguments);
+ var result = res.get.call(self, self);
+ self.$arguments = null;
+ return result;
+ };
+ } else {
+ try {
+ return res.get.call(this, this);
+ } catch (e) {}
+ }
+ }
+ };
+
+ /**
+ * Set the value from an expression on this vm.
+ * The expression must be a valid left-hand
+ * expression in an assignment.
+ *
+ * @param {String} exp
+ * @param {*} val
+ */
+
+ Vue.prototype.$set = function (exp, val) {
+ var res = parseExpression(exp, true);
+ if (res && res.set) {
+ res.set.call(this, this, val);
+ }
+ };
+
+ /**
+ * Delete a property on the VM
+ *
+ * @param {String} key
+ */
+
+ Vue.prototype.$delete = function (key) {
+ del(this._data, key);
+ };
+
+ /**
+ * Watch an expression, trigger callback when its
+ * value changes.
+ *
+ * @param {String|Function} expOrFn
+ * @param {Function} cb
+ * @param {Object} [options]
+ * - {Boolean} deep
+ * - {Boolean} immediate
+ * @return {Function} - unwatchFn
+ */
+
+ Vue.prototype.$watch = function (expOrFn, cb, options) {
+ var vm = this;
+ var parsed;
+ if (typeof expOrFn === 'string') {
+ parsed = parseDirective(expOrFn);
+ expOrFn = parsed.expression;
+ }
+ var watcher = new Watcher(vm, expOrFn, cb, {
+ deep: options && options.deep,
+ sync: options && options.sync,
+ filters: parsed && parsed.filters,
+ user: !options || options.user !== false
+ });
+ if (options && options.immediate) {
+ cb.call(vm, watcher.value);
+ }
+ return function unwatchFn() {
+ watcher.teardown();
+ };
+ };
+
+ /**
+ * Evaluate a text directive, including filters.
+ *
+ * @param {String} text
+ * @param {Boolean} [asStatement]
+ * @return {String}
+ */
+
+ Vue.prototype.$eval = function (text, asStatement) {
+ // check for filters.
+ if (filterRE$1.test(text)) {
+ var dir = parseDirective(text);
+ // the filter regex check might give false positive
+ // for pipes inside strings, so it's possible that
+ // we don't get any filters here
+ var val = this.$get(dir.expression, asStatement);
+ return dir.filters ? this._applyFilters(val, null, dir.filters) : val;
+ } else {
+ // no filter
+ return this.$get(text, asStatement);
+ }
+ };
+
+ /**
+ * Interpolate a piece of template text.
+ *
+ * @param {String} text
+ * @return {String}
+ */
+
+ Vue.prototype.$interpolate = function (text) {
+ var tokens = parseText(text);
+ var vm = this;
+ if (tokens) {
+ if (tokens.length === 1) {
+ return vm.$eval(tokens[0].value) + '';
+ } else {
+ return tokens.map(function (token) {
+ return token.tag ? vm.$eval(token.value) : token.value;
+ }).join('');
+ }
+ } else {
+ return text;
+ }
+ };
+
+ /**
+ * Log instance data as a plain JS object
+ * so that it is easier to inspect in console.
+ * This method assumes console is available.
+ *
+ * @param {String} [path]
+ */
+
+ Vue.prototype.$log = function (path) {
+ var data = path ? getPath(this._data, path) : this._data;
+ if (data) {
+ data = clean(data);
+ }
+ // include computed fields
+ if (!path) {
+ var key;
+ for (key in this.$options.computed) {
+ data[key] = clean(this[key]);
+ }
+ if (this._props) {
+ for (key in this._props) {
+ data[key] = clean(this[key]);
+ }
+ }
+ }
+ console.log(data);
+ };
+
+ /**
+ * "clean" a getter/setter converted object into a plain
+ * object copy.
+ *
+ * @param {Object} - obj
+ * @return {Object}
+ */
+
+ function clean(obj) {
+ return JSON.parse(JSON.stringify(obj));
+ }
+ }
+
+ function domAPI (Vue) {
+ /**
+ * Convenience on-instance nextTick. The callback is
+ * auto-bound to the instance, and this avoids component
+ * modules having to rely on the global Vue.
+ *
+ * @param {Function} fn
+ */
+
+ Vue.prototype.$nextTick = function (fn) {
+ nextTick(fn, this);
+ };
+
+ /**
+ * Append instance to target
+ *
+ * @param {Node} target
+ * @param {Function} [cb]
+ * @param {Boolean} [withTransition] - defaults to true
+ */
+
+ Vue.prototype.$appendTo = function (target, cb, withTransition) {
+ return insert(this, target, cb, withTransition, append, appendWithTransition);
+ };
+
+ /**
+ * Prepend instance to target
+ *
+ * @param {Node} target
+ * @param {Function} [cb]
+ * @param {Boolean} [withTransition] - defaults to true
+ */
+
+ Vue.prototype.$prependTo = function (target, cb, withTransition) {
+ target = query(target);
+ if (target.hasChildNodes()) {
+ this.$before(target.firstChild, cb, withTransition);
+ } else {
+ this.$appendTo(target, cb, withTransition);
+ }
+ return this;
+ };
+
+ /**
+ * Insert instance before target
+ *
+ * @param {Node} target
+ * @param {Function} [cb]
+ * @param {Boolean} [withTransition] - defaults to true
+ */
+
+ Vue.prototype.$before = function (target, cb, withTransition) {
+ return insert(this, target, cb, withTransition, beforeWithCb, beforeWithTransition);
+ };
+
+ /**
+ * Insert instance after target
+ *
+ * @param {Node} target
+ * @param {Function} [cb]
+ * @param {Boolean} [withTransition] - defaults to true
+ */
+
+ Vue.prototype.$after = function (target, cb, withTransition) {
+ target = query(target);
+ if (target.nextSibling) {
+ this.$before(target.nextSibling, cb, withTransition);
+ } else {
+ this.$appendTo(target.parentNode, cb, withTransition);
+ }
+ return this;
+ };
+
+ /**
+ * Remove instance from DOM
+ *
+ * @param {Function} [cb]
+ * @param {Boolean} [withTransition] - defaults to true
+ */
+
+ Vue.prototype.$remove = function (cb, withTransition) {
+ if (!this.$el.parentNode) {
+ return cb && cb();
+ }
+ var inDocument = this._isAttached && inDoc(this.$el);
+ // if we are not in document, no need to check
+ // for transitions
+ if (!inDocument) withTransition = false;
+ var self = this;
+ var realCb = function realCb() {
+ if (inDocument) self._callHook('detached');
+ if (cb) cb();
+ };
+ if (this._isFragment) {
+ removeNodeRange(this._fragmentStart, this._fragmentEnd, this, this._fragment, realCb);
+ } else {
+ var op = withTransition === false ? removeWithCb : removeWithTransition;
+ op(this.$el, this, realCb);
+ }
+ return this;
+ };
+
+ /**
+ * Shared DOM insertion function.
+ *
+ * @param {Vue} vm
+ * @param {Element} target
+ * @param {Function} [cb]
+ * @param {Boolean} [withTransition]
+ * @param {Function} op1 - op for non-transition insert
+ * @param {Function} op2 - op for transition insert
+ * @return vm
+ */
+
+ function insert(vm, target, cb, withTransition, op1, op2) {
+ target = query(target);
+ var targetIsDetached = !inDoc(target);
+ var op = withTransition === false || targetIsDetached ? op1 : op2;
+ var shouldCallHook = !targetIsDetached && !vm._isAttached && !inDoc(vm.$el);
+ if (vm._isFragment) {
+ mapNodeRange(vm._fragmentStart, vm._fragmentEnd, function (node) {
+ op(node, target, vm);
+ });
+ cb && cb();
+ } else {
+ op(vm.$el, target, vm, cb);
+ }
+ if (shouldCallHook) {
+ vm._callHook('attached');
+ }
+ return vm;
+ }
+
+ /**
+ * Check for selectors
+ *
+ * @param {String|Element} el
+ */
+
+ function query(el) {
+ return typeof el === 'string' ? document.querySelector(el) : el;
+ }
+
+ /**
+ * Append operation that takes a callback.
+ *
+ * @param {Node} el
+ * @param {Node} target
+ * @param {Vue} vm - unused
+ * @param {Function} [cb]
+ */
+
+ function append(el, target, vm, cb) {
+ target.appendChild(el);
+ if (cb) cb();
+ }
+
+ /**
+ * InsertBefore operation that takes a callback.
+ *
+ * @param {Node} el
+ * @param {Node} target
+ * @param {Vue} vm - unused
+ * @param {Function} [cb]
+ */
+
+ function beforeWithCb(el, target, vm, cb) {
+ before(el, target);
+ if (cb) cb();
+ }
+
+ /**
+ * Remove operation that takes a callback.
+ *
+ * @param {Node} el
+ * @param {Vue} vm - unused
+ * @param {Function} [cb]
+ */
+
+ function removeWithCb(el, vm, cb) {
+ remove(el);
+ if (cb) cb();
+ }
+ }
+
+ function eventsAPI (Vue) {
+ /**
+ * Listen on the given `event` with `fn`.
+ *
+ * @param {String} event
+ * @param {Function} fn
+ */
+
+ Vue.prototype.$on = function (event, fn) {
+ (this._events[event] || (this._events[event] = [])).push(fn);
+ modifyListenerCount(this, event, 1);
+ return this;
+ };
+
+ /**
+ * Adds an `event` listener that will be invoked a single
+ * time then automatically removed.
+ *
+ * @param {String} event
+ * @param {Function} fn
+ */
+
+ Vue.prototype.$once = function (event, fn) {
+ var self = this;
+ function on() {
+ self.$off(event, on);
+ fn.apply(this, arguments);
+ }
+ on.fn = fn;
+ this.$on(event, on);
+ return this;
+ };
+
+ /**
+ * Remove the given callback for `event` or all
+ * registered callbacks.
+ *
+ * @param {String} event
+ * @param {Function} fn
+ */
+
+ Vue.prototype.$off = function (event, fn) {
+ var cbs;
+ // all
+ if (!arguments.length) {
+ if (this.$parent) {
+ for (event in this._events) {
+ cbs = this._events[event];
+ if (cbs) {
+ modifyListenerCount(this, event, -cbs.length);
+ }
+ }
+ }
+ this._events = {};
+ return this;
+ }
+ // specific event
+ cbs = this._events[event];
+ if (!cbs) {
+ return this;
+ }
+ if (arguments.length === 1) {
+ modifyListenerCount(this, event, -cbs.length);
+ this._events[event] = null;
+ return this;
+ }
+ // specific handler
+ var cb;
+ var i = cbs.length;
+ while (i--) {
+ cb = cbs[i];
+ if (cb === fn || cb.fn === fn) {
+ modifyListenerCount(this, event, -1);
+ cbs.splice(i, 1);
+ break;
+ }
+ }
+ return this;
+ };
+
+ /**
+ * Trigger an event on self.
+ *
+ * @param {String|Object} event
+ * @return {Boolean} shouldPropagate
+ */
+
+ Vue.prototype.$emit = function (event) {
+ var isSource = typeof event === 'string';
+ event = isSource ? event : event.name;
+ var cbs = this._events[event];
+ var shouldPropagate = isSource || !cbs;
+ if (cbs) {
+ cbs = cbs.length > 1 ? toArray(cbs) : cbs;
+ // this is a somewhat hacky solution to the question raised
+ // in #2102: for an inline component listener like <comp @test="doThis">,
+ // the propagation handling is somewhat broken. Therefore we
+ // need to treat these inline callbacks differently.
+ var hasParentCbs = isSource && cbs.some(function (cb) {
+ return cb._fromParent;
+ });
+ if (hasParentCbs) {
+ shouldPropagate = false;
+ }
+ var args = toArray(arguments, 1);
+ for (var i = 0, l = cbs.length; i < l; i++) {
+ var cb = cbs[i];
+ var res = cb.apply(this, args);
+ if (res === true && (!hasParentCbs || cb._fromParent)) {
+ shouldPropagate = true;
+ }
+ }
+ }
+ return shouldPropagate;
+ };
+
+ /**
+ * Recursively broadcast an event to all children instances.
+ *
+ * @param {String|Object} event
+ * @param {...*} additional arguments
+ */
+
+ Vue.prototype.$broadcast = function (event) {
+ var isSource = typeof event === 'string';
+ event = isSource ? event : event.name;
+ // if no child has registered for this event,
+ // then there's no need to broadcast.
+ if (!this._eventsCount[event]) return;
+ var children = this.$children;
+ var args = toArray(arguments);
+ if (isSource) {
+ // use object event to indicate non-source emit
+ // on children
+ args[0] = { name: event, source: this };
+ }
+ for (var i = 0, l = children.length; i < l; i++) {
+ var child = children[i];
+ var shouldPropagate = child.$emit.apply(child, args);
+ if (shouldPropagate) {
+ child.$broadcast.apply(child, args);
+ }
+ }
+ return this;
+ };
+
+ /**
+ * Recursively propagate an event up the parent chain.
+ *
+ * @param {String} event
+ * @param {...*} additional arguments
+ */
+
+ Vue.prototype.$dispatch = function (event) {
+ var shouldPropagate = this.$emit.apply(this, arguments);
+ if (!shouldPropagate) return;
+ var parent = this.$parent;
+ var args = toArray(arguments);
+ // use object event to indicate non-source emit
+ // on parents
+ args[0] = { name: event, source: this };
+ while (parent) {
+ shouldPropagate = parent.$emit.apply(parent, args);
+ parent = shouldPropagate ? parent.$parent : null;
+ }
+ return this;
+ };
+
+ /**
+ * Modify the listener counts on all parents.
+ * This bookkeeping allows $broadcast to return early when
+ * no child has listened to a certain event.
+ *
+ * @param {Vue} vm
+ * @param {String} event
+ * @param {Number} count
+ */
+
+ var hookRE = /^hook:/;
+ function modifyListenerCount(vm, event, count) {
+ var parent = vm.$parent;
+ // hooks do not get broadcasted so no need
+ // to do bookkeeping for them
+ if (!parent || !count || hookRE.test(event)) return;
+ while (parent) {
+ parent._eventsCount[event] = (parent._eventsCount[event] || 0) + count;
+ parent = parent.$parent;
+ }
+ }
+ }
+
+ function lifecycleAPI (Vue) {
+ /**
+ * Set instance target element and kick off the compilation
+ * process. The passed in `el` can be a selector string, an
+ * existing Element, or a DocumentFragment (for block
+ * instances).
+ *
+ * @param {Element|DocumentFragment|string} el
+ * @public
+ */
+
+ Vue.prototype.$mount = function (el) {
+ if (this._isCompiled) {
+ 'development' !== 'production' && warn('$mount() should be called only once.', this);
+ return;
+ }
+ el = query(el);
+ if (!el) {
+ el = document.createElement('div');
+ }
+ this._compile(el);
+ this._initDOMHooks();
+ if (inDoc(this.$el)) {
+ this._callHook('attached');
+ ready.call(this);
+ } else {
+ this.$once('hook:attached', ready);
+ }
+ return this;
+ };
+
+ /**
+ * Mark an instance as ready.
+ */
+
+ function ready() {
+ this._isAttached = true;
+ this._isReady = true;
+ this._callHook('ready');
+ }
+
+ /**
+ * Teardown the instance, simply delegate to the internal
+ * _destroy.
+ *
+ * @param {Boolean} remove
+ * @param {Boolean} deferCleanup
+ */
+
+ Vue.prototype.$destroy = function (remove, deferCleanup) {
+ this._destroy(remove, deferCleanup);
+ };
+
+ /**
+ * Partially compile a piece of DOM and return a
+ * decompile function.
+ *
+ * @param {Element|DocumentFragment} el
+ * @param {Vue} [host]
+ * @param {Object} [scope]
+ * @param {Fragment} [frag]
+ * @return {Function}
+ */
+
+ Vue.prototype.$compile = function (el, host, scope, frag) {
+ return compile(el, this.$options, true)(this, el, host, scope, frag);
+ };
+ }
+
+ /**
+ * The exposed Vue constructor.
+ *
+ * API conventions:
+ * - public API methods/properties are prefixed with `$`
+ * - internal methods/properties are prefixed with `_`
+ * - non-prefixed properties are assumed to be proxied user
+ * data.
+ *
+ * @constructor
+ * @param {Object} [options]
+ * @public
+ */
+
+ function Vue(options) {
+ this._init(options);
+ }
+
+ // install internals
+ initMixin(Vue);
+ stateMixin(Vue);
+ eventsMixin(Vue);
+ lifecycleMixin(Vue);
+ miscMixin(Vue);
+
+ // install instance APIs
+ dataAPI(Vue);
+ domAPI(Vue);
+ eventsAPI(Vue);
+ lifecycleAPI(Vue);
+
+ var slot = {
+
+ priority: SLOT,
+ params: ['name'],
+
+ bind: function bind() {
+ // this was resolved during component transclusion
+ var name = this.params.name || 'default';
+ var content = this.vm._slotContents && this.vm._slotContents[name];
+ if (!content || !content.hasChildNodes()) {
+ this.fallback();
+ } else {
+ this.compile(content.cloneNode(true), this.vm._context, this.vm);
+ }
+ },
+
+ compile: function compile(content, context, host) {
+ if (content && context) {
+ if (this.el.hasChildNodes() && content.childNodes.length === 1 && content.childNodes[0].nodeType === 1 && content.childNodes[0].hasAttribute('v-if')) {
+ // if the inserted slot has v-if
+ // inject fallback content as the v-else
+ var elseBlock = document.createElement('template');
+ elseBlock.setAttribute('v-else', '');
+ elseBlock.innerHTML = this.el.innerHTML;
+ // the else block should be compiled in child scope
+ elseBlock._context = this.vm;
+ content.appendChild(elseBlock);
+ }
+ var scope = host ? host._scope : this._scope;
+ this.unlink = context.$compile(content, host, scope, this._frag);
+ }
+ if (content) {
+ replace(this.el, content);
+ } else {
+ remove(this.el);
+ }
+ },
+
+ fallback: function fallback() {
+ this.compile(extractContent(this.el, true), this.vm);
+ },
+
+ unbind: function unbind() {
+ if (this.unlink) {
+ this.unlink();
+ }
+ }
+ };
+
+ var partial = {
+
+ priority: PARTIAL,
+
+ params: ['name'],
+
+ // watch changes to name for dynamic partials
+ paramWatchers: {
+ name: function name(value) {
+ vIf.remove.call(this);
+ if (value) {
+ this.insert(value);
+ }
+ }
+ },
+
+ bind: function bind() {
+ this.anchor = createAnchor('v-partial');
+ replace(this.el, this.anchor);
+ this.insert(this.params.name);
+ },
+
+ insert: function insert(id) {
+ var partial = resolveAsset(this.vm.$options, 'partials', id, true);
+ if (partial) {
+ this.factory = new FragmentFactory(this.vm, partial);
+ vIf.insert.call(this);
+ }
+ },
+
+ unbind: function unbind() {
+ if (this.frag) {
+ this.frag.destroy();
+ }
+ }
+ };
+
+ var elementDirectives = {
+ slot: slot,
+ partial: partial
+ };
+
+ var convertArray = vFor._postProcess;
+
+ /**
+ * Limit filter for arrays
+ *
+ * @param {Number} n
+ * @param {Number} offset (Decimal expected)
+ */
+
+ function limitBy(arr, n, offset) {
+ offset = offset ? parseInt(offset, 10) : 0;
+ n = toNumber(n);
+ return typeof n === 'number' ? arr.slice(offset, offset + n) : arr;
+ }
+
+ /**
+ * Filter filter for arrays
+ *
+ * @param {String} search
+ * @param {String} [delimiter]
+ * @param {String} ...dataKeys
+ */
+
+ function filterBy(arr, search, delimiter) {
+ arr = convertArray(arr);
+ if (search == null) {
+ return arr;
+ }
+ if (typeof search === 'function') {
+ return arr.filter(search);
+ }
+ // cast to lowercase string
+ search = ('' + search).toLowerCase();
+ // allow optional `in` delimiter
+ // because why not
+ var n = delimiter === 'in' ? 3 : 2;
+ // extract and flatten keys
+ var keys = Array.prototype.concat.apply([], toArray(arguments, n));
+ var res = [];
+ var item, key, val, j;
+ for (var i = 0, l = arr.length; i < l; i++) {
+ item = arr[i];
+ val = item && item.$value || item;
+ j = keys.length;
+ if (j) {
+ while (j--) {
+ key = keys[j];
+ if (key === '$key' && contains(item.$key, search) || contains(getPath(val, key), search)) {
+ res.push(item);
+ break;
+ }
+ }
+ } else if (contains(item, search)) {
+ res.push(item);
+ }
+ }
+ return res;
+ }
+
+ /**
+ * Filter filter for arrays
+ *
+ * @param {String|Array<String>|Function} ...sortKeys
+ * @param {Number} [order]
+ */
+
+ function orderBy(arr) {
+ var comparator = null;
+ var sortKeys = undefined;
+ arr = convertArray(arr);
+
+ // determine order (last argument)
+ var args = toArray(arguments, 1);
+ var order = args[args.length - 1];
+ if (typeof order === 'number') {
+ order = order < 0 ? -1 : 1;
+ args = args.length > 1 ? args.slice(0, -1) : args;
+ } else {
+ order = 1;
+ }
+
+ // determine sortKeys & comparator
+ var firstArg = args[0];
+ if (!firstArg) {
+ return arr;
+ } else if (typeof firstArg === 'function') {
+ // custom comparator
+ comparator = function (a, b) {
+ return firstArg(a, b) * order;
+ };
+ } else {
+ // string keys. flatten first
+ sortKeys = Array.prototype.concat.apply([], args);
+ comparator = function (a, b, i) {
+ i = i || 0;
+ return i >= sortKeys.length - 1 ? baseCompare(a, b, i) : baseCompare(a, b, i) || comparator(a, b, i + 1);
+ };
+ }
+
+ function baseCompare(a, b, sortKeyIndex) {
+ var sortKey = sortKeys[sortKeyIndex];
+ if (sortKey) {
+ if (sortKey !== '$key') {
+ if (isObject(a) && '$value' in a) a = a.$value;
+ if (isObject(b) && '$value' in b) b = b.$value;
+ }
+ a = isObject(a) ? getPath(a, sortKey) : a;
+ b = isObject(b) ? getPath(b, sortKey) : b;
+ }
+ return a === b ? 0 : a > b ? order : -order;
+ }
+
+ // sort on a copy to avoid mutating original array
+ return arr.slice().sort(comparator);
+ }
+
+ /**
+ * String contain helper
+ *
+ * @param {*} val
+ * @param {String} search
+ */
+
+ function contains(val, search) {
+ var i;
+ if (isPlainObject(val)) {
+ var keys = Object.keys(val);
+ i = keys.length;
+ while (i--) {
+ if (contains(val[keys[i]], search)) {
+ return true;
+ }
+ }
+ } else if (isArray(val)) {
+ i = val.length;
+ while (i--) {
+ if (contains(val[i], search)) {
+ return true;
+ }
+ }
+ } else if (val != null) {
+ return val.toString().toLowerCase().indexOf(search) > -1;
+ }
+ }
+
+ var digitsRE = /(\d{3})(?=\d)/g;
+
+ // asset collections must be a plain object.
+ var filters = {
+
+ orderBy: orderBy,
+ filterBy: filterBy,
+ limitBy: limitBy,
+
+ /**
+ * Stringify value.
+ *
+ * @param {Number} indent
+ */
+
+ json: {
+ read: function read(value, indent) {
+ return typeof value === 'string' ? value : JSON.stringify(value, null, arguments.length > 1 ? indent : 2);
+ },
+ write: function write(value) {
+ try {
+ return JSON.parse(value);
+ } catch (e) {
+ return value;
+ }
+ }
+ },
+
+ /**
+ * 'abc' => 'Abc'
+ */
+
+ capitalize: function capitalize(value) {
+ if (!value && value !== 0) return '';
+ value = value.toString();
+ return value.charAt(0).toUpperCase() + value.slice(1);
+ },
+
+ /**
+ * 'abc' => 'ABC'
+ */
+
+ uppercase: function uppercase(value) {
+ return value || value === 0 ? value.toString().toUpperCase() : '';
+ },
+
+ /**
+ * 'AbC' => 'abc'
+ */
+
+ lowercase: function lowercase(value) {
+ return value || value === 0 ? value.toString().toLowerCase() : '';
+ },
+
+ /**
+ * 12345 => $12,345.00
+ *
+ * @param {String} sign
+ * @param {Number} decimals Decimal places
+ */
+
+ currency: function currency(value, _currency, decimals) {
+ value = parseFloat(value);
+ if (!isFinite(value) || !value && value !== 0) return '';
+ _currency = _currency != null ? _currency : '$';
+ decimals = decimals != null ? decimals : 2;
+ var stringified = Math.abs(value).toFixed(decimals);
+ var _int = decimals ? stringified.slice(0, -1 - decimals) : stringified;
+ var i = _int.length % 3;
+ var head = i > 0 ? _int.slice(0, i) + (_int.length > 3 ? ',' : '') : '';
+ var _float = decimals ? stringified.slice(-1 - decimals) : '';
+ var sign = value < 0 ? '-' : '';
+ return sign + _currency + head + _int.slice(i).replace(digitsRE, '$1,') + _float;
+ },
+
+ /**
+ * 'item' => 'items'
+ *
+ * @params
+ * an array of strings corresponding to
+ * the single, double, triple ... forms of the word to
+ * be pluralized. When the number to be pluralized
+ * exceeds the length of the args, it will use the last
+ * entry in the array.
+ *
+ * e.g. ['single', 'double', 'triple', 'multiple']
+ */
+
+ pluralize: function pluralize(value) {
+ var args = toArray(arguments, 1);
+ var length = args.length;
+ if (length > 1) {
+ var index = value % 10 - 1;
+ return index in args ? args[index] : args[length - 1];
+ } else {
+ return args[0] + (value === 1 ? '' : 's');
+ }
+ },
+
+ /**
+ * Debounce a handler function.
+ *
+ * @param {Function} handler
+ * @param {Number} delay = 300
+ * @return {Function}
+ */
+
+ debounce: function debounce(handler, delay) {
+ if (!handler) return;
+ if (!delay) {
+ delay = 300;
+ }
+ return _debounce(handler, delay);
+ }
+ };
+
+ function installGlobalAPI (Vue) {
+ /**
+ * Vue and every constructor that extends Vue has an
+ * associated options object, which can be accessed during
+ * compilation steps as `this.constructor.options`.
+ *
+ * These can be seen as the default options of every
+ * Vue instance.
+ */
+
+ Vue.options = {
+ directives: directives,
+ elementDirectives: elementDirectives,
+ filters: filters,
+ transitions: {},
+ components: {},
+ partials: {},
+ replace: true
+ };
+
+ /**
+ * Expose useful internals
+ */
+
+ Vue.util = util;
+ Vue.config = config;
+ Vue.set = set;
+ Vue['delete'] = del;
+ Vue.nextTick = nextTick;
+
+ /**
+ * The following are exposed for advanced usage / plugins
+ */
+
+ Vue.compiler = compiler;
+ Vue.FragmentFactory = FragmentFactory;
+ Vue.internalDirectives = internalDirectives;
+ Vue.parsers = {
+ path: path,
+ text: text,
+ template: template,
+ directive: directive,
+ expression: expression
+ };
+
+ /**
+ * Each instance constructor, including Vue, has a unique
+ * cid. This enables us to create wrapped "child
+ * constructors" for prototypal inheritance and cache them.
+ */
+
+ Vue.cid = 0;
+ var cid = 1;
+
+ /**
+ * Class inheritance
+ *
+ * @param {Object} extendOptions
+ */
+
+ Vue.extend = function (extendOptions) {
+ extendOptions = extendOptions || {};
+ var Super = this;
+ var isFirstExtend = Super.cid === 0;
+ if (isFirstExtend && extendOptions._Ctor) {
+ return extendOptions._Ctor;
+ }
+ var name = extendOptions.name || Super.options.name;
+ if ('development' !== 'production') {
+ if (!/^[a-zA-Z][\w-]*$/.test(name)) {
+ warn('Invalid component name: "' + name + '". Component names ' + 'can only contain alphanumeric characaters and the hyphen.');
+ name = null;
+ }
+ }
+ var Sub = createClass(name || 'VueComponent');
+ Sub.prototype = Object.create(Super.prototype);
+ Sub.prototype.constructor = Sub;
+ Sub.cid = cid++;
+ Sub.options = mergeOptions(Super.options, extendOptions);
+ Sub['super'] = Super;
+ // allow further extension
+ Sub.extend = Super.extend;
+ // create asset registers, so extended classes
+ // can have their private assets too.
+ config._assetTypes.forEach(function (type) {
+ Sub[type] = Super[type];
+ });
+ // enable recursive self-lookup
+ if (name) {
+ Sub.options.components[name] = Sub;
+ }
+ // cache constructor
+ if (isFirstExtend) {
+ extendOptions._Ctor = Sub;
+ }
+ return Sub;
+ };
+
+ /**
+ * A function that returns a sub-class constructor with the
+ * given name. This gives us much nicer output when
+ * logging instances in the console.
+ *
+ * @param {String} name
+ * @return {Function}
+ */
+
+ function createClass(name) {
+ /* eslint-disable no-new-func */
+ return new Function('return function ' + classify(name) + ' (options) { this._init(options) }')();
+ /* eslint-enable no-new-func */
+ }
+
+ /**
+ * Plugin system
+ *
+ * @param {Object} plugin
+ */
+
+ Vue.use = function (plugin) {
+ /* istanbul ignore if */
+ if (plugin.installed) {
+ return;
+ }
+ // additional parameters
+ var args = toArray(arguments, 1);
+ args.unshift(this);
+ if (typeof plugin.install === 'function') {
+ plugin.install.apply(plugin, args);
+ } else {
+ plugin.apply(null, args);
+ }
+ plugin.installed = true;
+ return this;
+ };
+
+ /**
+ * Apply a global mixin by merging it into the default
+ * options.
+ */
+
+ Vue.mixin = function (mixin) {
+ Vue.options = mergeOptions(Vue.options, mixin);
+ };
+
+ /**
+ * Create asset registration methods with the following
+ * signature:
+ *
+ * @param {String} id
+ * @param {*} definition
+ */
+
+ config._assetTypes.forEach(function (type) {
+ Vue[type] = function (id, definition) {
+ if (!definition) {
+ return this.options[type + 's'][id];
+ } else {
+ /* istanbul ignore if */
+ if ('development' !== 'production') {
+ if (type === 'component' && (commonTagRE.test(id) || reservedTagRE.test(id))) {
+ warn('Do not use built-in or reserved HTML elements as component ' + 'id: ' + id);
+ }
+ }
+ if (type === 'component' && isPlainObject(definition)) {
+ if (!definition.name) {
+ definition.name = id;
+ }
+ definition = Vue.extend(definition);
+ }
+ this.options[type + 's'][id] = definition;
+ return definition;
+ }
+ };
+ });
+
+ // expose internal transition API
+ extend(Vue.transition, transition);
+ }
+
+ installGlobalAPI(Vue);
+
+ Vue.version = '1.0.26';
+
+ // devtools global hook
+ /* istanbul ignore next */
+ setTimeout(function () {
+ if (config.devtools) {
+ if (devtools) {
+ devtools.emit('init', Vue);
+ } else if ('development' !== 'production' && inBrowser && /Chrome\/\d+/.test(window.navigator.userAgent)) {
+ console.log('Download the Vue Devtools for a better development experience:\n' + 'https://github.com/vuejs/vue-devtools');
+ }
+ }
+ }, 0);
+
+ return Vue;
+
+})); \ No newline at end of file
diff --git a/vendor/assets/javascripts/vue.js.erb b/vendor/assets/javascripts/vue.js.erb
new file mode 100644
index 00000000000..008beb10f4d
--- /dev/null
+++ b/vendor/assets/javascripts/vue.js.erb
@@ -0,0 +1,2 @@
+<% type = Rails.env.development? ? 'full' : 'min' %>
+<%= File.read(Rails.root.join("vendor/assets/javascripts/vue.#{type}.js")) %>
diff --git a/vendor/assets/javascripts/vue.min.js b/vendor/assets/javascripts/vue.min.js
new file mode 100644
index 00000000000..2c9a8a0e117
--- /dev/null
+++ b/vendor/assets/javascripts/vue.min.js
@@ -0,0 +1,9 @@
+/*!
+ * Vue.js v1.0.26
+ * (c) 2016 Evan You
+ * Released under the MIT License.
+ */
+!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.Vue=e()}(this,function(){"use strict";function t(e,n,r){if(i(e,n))return void(e[n]=r);if(e._isVue)return void t(e._data,n,r);var s=e.__ob__;if(!s)return void(e[n]=r);if(s.convert(n,r),s.dep.notify(),s.vms)for(var o=s.vms.length;o--;){var a=s.vms[o];a._proxy(n),a._digest()}return r}function e(t,e){if(i(t,e)){delete t[e];var n=t.__ob__;if(!n)return void(t._isVue&&(delete t._data[e],t._digest()));if(n.dep.notify(),n.vms)for(var r=n.vms.length;r--;){var s=n.vms[r];s._unproxy(e),s._digest()}}}function i(t,e){return Oi.call(t,e)}function n(t){return Ti.test(t)}function r(t){var e=(t+"").charCodeAt(0);return 36===e||95===e}function s(t){return null==t?"":t.toString()}function o(t){if("string"!=typeof t)return t;var e=Number(t);return isNaN(e)?t:e}function a(t){return"true"===t?!0:"false"===t?!1:t}function h(t){var e=t.charCodeAt(0),i=t.charCodeAt(t.length-1);return e!==i||34!==e&&39!==e?t:t.slice(1,-1)}function l(t){return t.replace(Ni,c)}function c(t,e){return e?e.toUpperCase():""}function u(t){return t.replace(ji,"$1-$2").toLowerCase()}function f(t){return t.replace(Ei,c)}function p(t,e){return function(i){var n=arguments.length;return n?n>1?t.apply(e,arguments):t.call(e,i):t.call(e)}}function d(t,e){e=e||0;for(var i=t.length-e,n=new Array(i);i--;)n[i]=t[i+e];return n}function v(t,e){for(var i=Object.keys(e),n=i.length;n--;)t[i[n]]=e[i[n]];return t}function m(t){return null!==t&&"object"==typeof t}function g(t){return Si.call(t)===Fi}function _(t,e,i,n){Object.defineProperty(t,e,{value:i,enumerable:!!n,writable:!0,configurable:!0})}function y(t,e){var i,n,r,s,o,a=function h(){var a=Date.now()-s;e>a&&a>=0?i=setTimeout(h,e-a):(i=null,o=t.apply(r,n),i||(r=n=null))};return function(){return r=this,n=arguments,s=Date.now(),i||(i=setTimeout(a,e)),o}}function b(t,e){for(var i=t.length;i--;)if(t[i]===e)return i;return-1}function w(t){var e=function i(){return i.cancelled?void 0:t.apply(this,arguments)};return e.cancel=function(){e.cancelled=!0},e}function C(t,e){return t==e||(m(t)&&m(e)?JSON.stringify(t)===JSON.stringify(e):!1)}function $(t){this.size=0,this.limit=t,this.head=this.tail=void 0,this._keymap=Object.create(null)}function k(){var t,e=en.slice(hn,on).trim();if(e){t={};var i=e.match(vn);t.name=i[0],i.length>1&&(t.args=i.slice(1).map(x))}t&&(nn.filters=nn.filters||[]).push(t),hn=on+1}function x(t){if(mn.test(t))return{value:o(t),dynamic:!1};var e=h(t),i=e===t;return{value:i?t:e,dynamic:i}}function A(t){var e=dn.get(t);if(e)return e;for(en=t,ln=cn=!1,un=fn=pn=0,hn=0,nn={},on=0,an=en.length;an>on;on++)if(sn=rn,rn=en.charCodeAt(on),ln)39===rn&&92!==sn&&(ln=!ln);else if(cn)34===rn&&92!==sn&&(cn=!cn);else if(124===rn&&124!==en.charCodeAt(on+1)&&124!==en.charCodeAt(on-1))null==nn.expression?(hn=on+1,nn.expression=en.slice(0,on).trim()):k();else switch(rn){case 34:cn=!0;break;case 39:ln=!0;break;case 40:pn++;break;case 41:pn--;break;case 91:fn++;break;case 93:fn--;break;case 123:un++;break;case 125:un--}return null==nn.expression?nn.expression=en.slice(0,on).trim():0!==hn&&k(),dn.put(t,nn),nn}function O(t){return t.replace(_n,"\\$&")}function T(){var t=O(An.delimiters[0]),e=O(An.delimiters[1]),i=O(An.unsafeDelimiters[0]),n=O(An.unsafeDelimiters[1]);bn=new RegExp(i+"((?:.|\\n)+?)"+n+"|"+t+"((?:.|\\n)+?)"+e,"g"),wn=new RegExp("^"+i+"((?:.|\\n)+?)"+n+"$"),yn=new $(1e3)}function N(t){yn||T();var e=yn.get(t);if(e)return e;if(!bn.test(t))return null;for(var i,n,r,s,o,a,h=[],l=bn.lastIndex=0;i=bn.exec(t);)n=i.index,n>l&&h.push({value:t.slice(l,n)}),r=wn.test(i[0]),s=r?i[1]:i[2],o=s.charCodeAt(0),a=42===o,s=a?s.slice(1):s,h.push({tag:!0,value:s.trim(),html:r,oneTime:a}),l=n+i[0].length;return l<t.length&&h.push({value:t.slice(l)}),yn.put(t,h),h}function j(t,e){return t.length>1?t.map(function(t){return E(t,e)}).join("+"):E(t[0],e,!0)}function E(t,e,i){return t.tag?t.oneTime&&e?'"'+e.$eval(t.value)+'"':S(t.value,i):'"'+t.value+'"'}function S(t,e){if(Cn.test(t)){var i=A(t);return i.filters?"this._applyFilters("+i.expression+",null,"+JSON.stringify(i.filters)+",false)":"("+t+")"}return e?t:"("+t+")"}function F(t,e,i,n){R(t,1,function(){e.appendChild(t)},i,n)}function D(t,e,i,n){R(t,1,function(){B(t,e)},i,n)}function P(t,e,i){R(t,-1,function(){z(t)},e,i)}function R(t,e,i,n,r){var s=t.__v_trans;if(!s||!s.hooks&&!qi||!n._isCompiled||n.$parent&&!n.$parent._isCompiled)return i(),void(r&&r());var o=e>0?"enter":"leave";s[o](i,r)}function L(t){if("string"==typeof t){t=document.querySelector(t)}return t}function H(t){if(!t)return!1;var e=t.ownerDocument.documentElement,i=t.parentNode;return e===t||e===i||!(!i||1!==i.nodeType||!e.contains(i))}function I(t,e){var i=t.getAttribute(e);return null!==i&&t.removeAttribute(e),i}function M(t,e){var i=I(t,":"+e);return null===i&&(i=I(t,"v-bind:"+e)),i}function V(t,e){return t.hasAttribute(e)||t.hasAttribute(":"+e)||t.hasAttribute("v-bind:"+e)}function B(t,e){e.parentNode.insertBefore(t,e)}function W(t,e){e.nextSibling?B(t,e.nextSibling):e.parentNode.appendChild(t)}function z(t){t.parentNode.removeChild(t)}function U(t,e){e.firstChild?B(t,e.firstChild):e.appendChild(t)}function J(t,e){var i=t.parentNode;i&&i.replaceChild(e,t)}function q(t,e,i,n){t.addEventListener(e,i,n)}function Q(t,e,i){t.removeEventListener(e,i)}function G(t){var e=t.className;return"object"==typeof e&&(e=e.baseVal||""),e}function Z(t,e){Mi&&!/svg$/.test(t.namespaceURI)?t.className=e:t.setAttribute("class",e)}function X(t,e){if(t.classList)t.classList.add(e);else{var i=" "+G(t)+" ";i.indexOf(" "+e+" ")<0&&Z(t,(i+e).trim())}}function Y(t,e){if(t.classList)t.classList.remove(e);else{for(var i=" "+G(t)+" ",n=" "+e+" ";i.indexOf(n)>=0;)i=i.replace(n," ");Z(t,i.trim())}t.className||t.removeAttribute("class")}function K(t,e){var i,n;if(it(t)&&at(t.content)&&(t=t.content),t.hasChildNodes())for(tt(t),n=e?document.createDocumentFragment():document.createElement("div");i=t.firstChild;)n.appendChild(i);return n}function tt(t){for(var e;e=t.firstChild,et(e);)t.removeChild(e);for(;e=t.lastChild,et(e);)t.removeChild(e)}function et(t){return t&&(3===t.nodeType&&!t.data.trim()||8===t.nodeType)}function it(t){return t.tagName&&"template"===t.tagName.toLowerCase()}function nt(t,e){var i=An.debug?document.createComment(t):document.createTextNode(e?" ":"");return i.__v_anchor=!0,i}function rt(t){if(t.hasAttributes())for(var e=t.attributes,i=0,n=e.length;n>i;i++){var r=e[i].name;if(Nn.test(r))return l(r.replace(Nn,""))}}function st(t,e,i){for(var n;t!==e;)n=t.nextSibling,i(t),t=n;i(e)}function ot(t,e,i,n,r){function s(){if(a++,o&&a>=h.length){for(var t=0;t<h.length;t++)n.appendChild(h[t]);r&&r()}}var o=!1,a=0,h=[];st(t,e,function(t){t===e&&(o=!0),h.push(t),P(t,i,s)})}function at(t){return t&&11===t.nodeType}function ht(t){if(t.outerHTML)return t.outerHTML;var e=document.createElement("div");return e.appendChild(t.cloneNode(!0)),e.innerHTML}function lt(t,e){var i=t.tagName.toLowerCase(),n=t.hasAttributes();if(jn.test(i)||En.test(i)){if(n)return ct(t,e)}else{if(gt(e,"components",i))return{id:i};var r=n&&ct(t,e);if(r)return r}}function ct(t,e){var i=t.getAttribute("is");if(null!=i){if(gt(e,"components",i))return t.removeAttribute("is"),{id:i}}else if(i=M(t,"is"),null!=i)return{id:i,dynamic:!0}}function ut(e,n){var r,s,o;for(r in n)s=e[r],o=n[r],i(e,r)?m(s)&&m(o)&&ut(s,o):t(e,r,o);return e}function ft(t,e){var i=Object.create(t||null);return e?v(i,vt(e)):i}function pt(t){if(t.components)for(var e,i=t.components=vt(t.components),n=Object.keys(i),r=0,s=n.length;s>r;r++){var o=n[r];jn.test(o)||En.test(o)||(e=i[o],g(e)&&(i[o]=wi.extend(e)))}}function dt(t){var e,i,n=t.props;if(Di(n))for(t.props={},e=n.length;e--;)i=n[e],"string"==typeof i?t.props[i]=null:i.name&&(t.props[i.name]=i);else if(g(n)){var r=Object.keys(n);for(e=r.length;e--;)i=n[r[e]],"function"==typeof i&&(n[r[e]]={type:i})}}function vt(t){if(Di(t)){for(var e,i={},n=t.length;n--;){e=t[n];var r="function"==typeof e?e.options&&e.options.name||e.id:e.name||e.id;r&&(i[r]=e)}return i}return t}function mt(t,e,n){function r(i){var r=Sn[i]||Fn;o[i]=r(t[i],e[i],n,i)}pt(e),dt(e);var s,o={};if(e["extends"]&&(t="function"==typeof e["extends"]?mt(t,e["extends"].options,n):mt(t,e["extends"],n)),e.mixins)for(var a=0,h=e.mixins.length;h>a;a++){var l=e.mixins[a],c=l.prototype instanceof wi?l.options:l;t=mt(t,c,n)}for(s in t)r(s);for(s in e)i(t,s)||r(s);return o}function gt(t,e,i,n){if("string"==typeof i){var r,s=t[e],o=s[i]||s[r=l(i)]||s[r.charAt(0).toUpperCase()+r.slice(1)];return o}}function _t(){this.id=Dn++,this.subs=[]}function yt(t){Hn=!1,t(),Hn=!0}function bt(t){if(this.value=t,this.dep=new _t,_(t,"__ob__",this),Di(t)){var e=Pi?wt:Ct;e(t,Rn,Ln),this.observeArray(t)}else this.walk(t)}function wt(t,e){t.__proto__=e}function Ct(t,e,i){for(var n=0,r=i.length;r>n;n++){var s=i[n];_(t,s,e[s])}}function $t(t,e){if(t&&"object"==typeof t){var n;return i(t,"__ob__")&&t.__ob__ instanceof bt?n=t.__ob__:Hn&&(Di(t)||g(t))&&Object.isExtensible(t)&&!t._isVue&&(n=new bt(t)),n&&e&&n.addVm(e),n}}function kt(t,e,i){var n=new _t,r=Object.getOwnPropertyDescriptor(t,e);if(!r||r.configurable!==!1){var s=r&&r.get,o=r&&r.set,a=$t(i);Object.defineProperty(t,e,{enumerable:!0,configurable:!0,get:function(){var e=s?s.call(t):i;if(_t.target&&(n.depend(),a&&a.dep.depend(),Di(e)))for(var r,o=0,h=e.length;h>o;o++)r=e[o],r&&r.__ob__&&r.__ob__.dep.depend();return e},set:function(e){var r=s?s.call(t):i;e!==r&&(o?o.call(t,e):i=e,a=$t(e),n.notify())}})}}function xt(t){t.prototype._init=function(t){t=t||{},this.$el=null,this.$parent=t.parent,this.$root=this.$parent?this.$parent.$root:this,this.$children=[],this.$refs={},this.$els={},this._watchers=[],this._directives=[],this._uid=Mn++,this._isVue=!0,this._events={},this._eventsCount={},this._isFragment=!1,this._fragment=this._fragmentStart=this._fragmentEnd=null,this._isCompiled=this._isDestroyed=this._isReady=this._isAttached=this._isBeingDestroyed=this._vForRemoving=!1,this._unlinkFn=null,this._context=t._context||this.$parent,this._scope=t._scope,this._frag=t._frag,this._frag&&this._frag.children.push(this),this.$parent&&this.$parent.$children.push(this),t=this.$options=mt(this.constructor.options,t,this),this._updateRef(),this._data={},this._callHook("init"),this._initState(),this._initEvents(),this._callHook("created"),t.el&&this.$mount(t.el)}}function At(t){if(void 0===t)return"eof";var e=t.charCodeAt(0);switch(e){case 91:case 93:case 46:case 34:case 39:case 48:return t;case 95:case 36:return"ident";case 32:case 9:case 10:case 13:case 160:case 65279:case 8232:case 8233:return"ws"}return e>=97&&122>=e||e>=65&&90>=e?"ident":e>=49&&57>=e?"number":"else"}function Ot(t){var e=t.trim();return"0"===t.charAt(0)&&isNaN(t)?!1:n(e)?h(e):"*"+e}function Tt(t){function e(){var e=t[c+1];return u===Xn&&"'"===e||u===Yn&&'"'===e?(c++,n="\\"+e,p[Bn](),!0):void 0}var i,n,r,s,o,a,h,l=[],c=-1,u=Jn,f=0,p=[];for(p[Wn]=function(){void 0!==r&&(l.push(r),r=void 0)},p[Bn]=function(){void 0===r?r=n:r+=n},p[zn]=function(){p[Bn](),f++},p[Un]=function(){if(f>0)f--,u=Zn,p[Bn]();else{if(f=0,r=Ot(r),r===!1)return!1;p[Wn]()}};null!=u;)if(c++,i=t[c],"\\"!==i||!e()){if(s=At(i),h=er[u],o=h[s]||h["else"]||tr,o===tr)return;if(u=o[0],a=p[o[1]],a&&(n=o[2],n=void 0===n?i:n,a()===!1))return;if(u===Kn)return l.raw=t,l}}function Nt(t){var e=Vn.get(t);return e||(e=Tt(t),e&&Vn.put(t,e)),e}function jt(t,e){return It(e).get(t)}function Et(e,i,n){var r=e;if("string"==typeof i&&(i=Tt(i)),!i||!m(e))return!1;for(var s,o,a=0,h=i.length;h>a;a++)s=e,o=i[a],"*"===o.charAt(0)&&(o=It(o.slice(1)).get.call(r,r)),h-1>a?(e=e[o],m(e)||(e={},t(s,o,e))):Di(e)?e.$set(o,n):o in e?e[o]=n:t(e,o,n);return!0}function St(){}function Ft(t,e){var i=vr.length;return vr[i]=e?t.replace(lr,"\\n"):t,'"'+i+'"'}function Dt(t){var e=t.charAt(0),i=t.slice(1);return sr.test(i)?t:(i=i.indexOf('"')>-1?i.replace(ur,Pt):i,e+"scope."+i)}function Pt(t,e){return vr[e]}function Rt(t){ar.test(t),vr.length=0;var e=t.replace(cr,Ft).replace(hr,"");return e=(" "+e).replace(pr,Dt).replace(ur,Pt),Lt(e)}function Lt(t){try{return new Function("scope","return "+t+";")}catch(e){return St}}function Ht(t){var e=Nt(t);return e?function(t,i){Et(t,e,i)}:void 0}function It(t,e){t=t.trim();var i=nr.get(t);if(i)return e&&!i.set&&(i.set=Ht(i.exp)),i;var n={exp:t};return n.get=Mt(t)&&t.indexOf("[")<0?Lt("scope."+t):Rt(t),e&&(n.set=Ht(t)),nr.put(t,n),n}function Mt(t){return fr.test(t)&&!dr.test(t)&&"Math."!==t.slice(0,5)}function Vt(){gr.length=0,_r.length=0,yr={},br={},wr=!1}function Bt(){for(var t=!0;t;)t=!1,Wt(gr),Wt(_r),gr.length?t=!0:(Li&&An.devtools&&Li.emit("flush"),Vt())}function Wt(t){for(var e=0;e<t.length;e++){var i=t[e],n=i.id;yr[n]=null,i.run()}t.length=0}function zt(t){var e=t.id;if(null==yr[e]){var i=t.user?_r:gr;yr[e]=i.length,i.push(t),wr||(wr=!0,Yi(Bt))}}function Ut(t,e,i,n){n&&v(this,n);var r="function"==typeof e;if(this.vm=t,t._watchers.push(this),this.expression=e,this.cb=i,this.id=++Cr,this.active=!0,this.dirty=this.lazy,this.deps=[],this.newDeps=[],this.depIds=new Ki,this.newDepIds=new Ki,this.prevError=null,r)this.getter=e,this.setter=void 0;else{var s=It(e,this.twoWay);this.getter=s.get,this.setter=s.set}this.value=this.lazy?void 0:this.get(),this.queued=this.shallow=!1}function Jt(t,e){var i=void 0,n=void 0;e||(e=$r,e.clear());var r=Di(t),s=m(t);if((r||s)&&Object.isExtensible(t)){if(t.__ob__){var o=t.__ob__.dep.id;if(e.has(o))return;e.add(o)}if(r)for(i=t.length;i--;)Jt(t[i],e);else if(s)for(n=Object.keys(t),i=n.length;i--;)Jt(t[n[i]],e)}}function qt(t){return it(t)&&at(t.content)}function Qt(t,e){var i=e?t:t.trim(),n=xr.get(i);if(n)return n;var r=document.createDocumentFragment(),s=t.match(Tr),o=Nr.test(t),a=jr.test(t);if(s||o||a){var h=s&&s[1],l=Or[h]||Or.efault,c=l[0],u=l[1],f=l[2],p=document.createElement("div");for(p.innerHTML=u+t+f;c--;)p=p.lastChild;for(var d;d=p.firstChild;)r.appendChild(d)}else r.appendChild(document.createTextNode(t));return e||tt(r),xr.put(i,r),r}function Gt(t){if(qt(t))return Qt(t.innerHTML);if("SCRIPT"===t.tagName)return Qt(t.textContent);for(var e,i=Zt(t),n=document.createDocumentFragment();e=i.firstChild;)n.appendChild(e);return tt(n),n}function Zt(t){if(!t.querySelectorAll)return t.cloneNode();var e,i,n,r=t.cloneNode(!0);if(Er){var s=r;if(qt(t)&&(t=t.content,s=r.content),i=t.querySelectorAll("template"),i.length)for(n=s.querySelectorAll("template"),e=n.length;e--;)n[e].parentNode.replaceChild(Zt(i[e]),n[e])}if(Sr)if("TEXTAREA"===t.tagName)r.value=t.value;else if(i=t.querySelectorAll("textarea"),i.length)for(n=r.querySelectorAll("textarea"),e=n.length;e--;)n[e].value=i[e].value;return r}function Xt(t,e,i){var n,r;return at(t)?(tt(t),e?Zt(t):t):("string"==typeof t?i||"#"!==t.charAt(0)?r=Qt(t,i):(r=Ar.get(t),r||(n=document.getElementById(t.slice(1)),n&&(r=Gt(n),Ar.put(t,r)))):t.nodeType&&(r=Gt(t)),r&&e?Zt(r):r)}function Yt(t,e,i,n,r,s){this.children=[],this.childFrags=[],this.vm=e,this.scope=r,this.inserted=!1,this.parentFrag=s,s&&s.childFrags.push(this),this.unlink=t(e,i,n,r,this);var o=this.single=1===i.childNodes.length&&!i.childNodes[0].__v_anchor;o?(this.node=i.childNodes[0],this.before=Kt,this.remove=te):(this.node=nt("fragment-start"),this.end=nt("fragment-end"),this.frag=i,U(this.node,i),i.appendChild(this.end),this.before=ee,this.remove=ie),this.node.__v_frag=this}function Kt(t,e){this.inserted=!0;var i=e!==!1?D:B;i(this.node,t,this.vm),H(this.node)&&this.callHook(ne)}function te(){this.inserted=!1;var t=H(this.node),e=this;this.beforeRemove(),P(this.node,this.vm,function(){t&&e.callHook(re),e.destroy()})}function ee(t,e){this.inserted=!0;var i=this.vm,n=e!==!1?D:B;st(this.node,this.end,function(e){n(e,t,i)}),H(this.node)&&this.callHook(ne)}function ie(){this.inserted=!1;var t=this,e=H(this.node);this.beforeRemove(),ot(this.node,this.end,this.vm,this.frag,function(){e&&t.callHook(re),t.destroy()})}function ne(t){!t._isAttached&&H(t.$el)&&t._callHook("attached")}function re(t){t._isAttached&&!H(t.$el)&&t._callHook("detached")}function se(t,e){this.vm=t;var i,n="string"==typeof e;n||it(e)&&!e.hasAttribute("v-if")?i=Xt(e,!0):(i=document.createDocumentFragment(),i.appendChild(e)),this.template=i;var r,s=t.constructor.cid;if(s>0){var o=s+(n?e:ht(e));r=Pr.get(o),r||(r=De(i,t.$options,!0),Pr.put(o,r))}else r=De(i,t.$options,!0);this.linker=r}function oe(t,e,i){var n=t.node.previousSibling;if(n){for(t=n.__v_frag;!(t&&t.forId===i&&t.inserted||n===e);){if(n=n.previousSibling,!n)return;t=n.__v_frag}return t}}function ae(t){var e=t.node;if(t.end)for(;!e.__vue__&&e!==t.end&&e.nextSibling;)e=e.nextSibling;return e.__vue__}function he(t){for(var e=-1,i=new Array(Math.floor(t));++e<t;)i[e]=e;return i}function le(t,e,i,n){return n?"$index"===n?t:n.charAt(0).match(/\w/)?jt(i,n):i[n]:e||i}function ce(t,e,i){for(var n,r,s,o=e?[]:null,a=0,h=t.options.length;h>a;a++)if(n=t.options[a],s=i?n.hasAttribute("selected"):n.selected){if(r=n.hasOwnProperty("_value")?n._value:n.value,!e)return r;o.push(r)}return o}function ue(t,e){for(var i=t.length;i--;)if(C(t[i],e))return i;return-1}function fe(t,e){var i=e.map(function(t){var e=t.charCodeAt(0);return e>47&&58>e?parseInt(t,10):1===t.length&&(e=t.toUpperCase().charCodeAt(0),e>64&&91>e)?e:is[t]});return i=[].concat.apply([],i),function(e){return i.indexOf(e.keyCode)>-1?t.call(this,e):void 0}}function pe(t){return function(e){return e.stopPropagation(),t.call(this,e)}}function de(t){return function(e){return e.preventDefault(),t.call(this,e)}}function ve(t){return function(e){return e.target===e.currentTarget?t.call(this,e):void 0}}function me(t){if(as[t])return as[t];var e=ge(t);return as[t]=as[e]=e,e}function ge(t){t=u(t);var e=l(t),i=e.charAt(0).toUpperCase()+e.slice(1);hs||(hs=document.createElement("div"));var n,r=rs.length;if("filter"!==e&&e in hs.style)return{kebab:t,camel:e};for(;r--;)if(n=ss[r]+i,n in hs.style)return{kebab:rs[r]+t,camel:n}}function _e(t){var e=[];if(Di(t))for(var i=0,n=t.length;n>i;i++){var r=t[i];if(r)if("string"==typeof r)e.push(r);else for(var s in r)r[s]&&e.push(s)}else if(m(t))for(var o in t)t[o]&&e.push(o);return e}function ye(t,e,i){if(e=e.trim(),-1===e.indexOf(" "))return void i(t,e);for(var n=e.split(/\s+/),r=0,s=n.length;s>r;r++)i(t,n[r])}function be(t,e,i){function n(){++s>=r?i():t[s].call(e,n)}var r=t.length,s=0;t[0].call(e,n)}function we(t,e,i){for(var r,s,o,a,h,c,f,p=[],d=Object.keys(e),v=d.length;v--;)s=d[v],r=e[s]||ks,h=l(s),xs.test(h)&&(f={name:s,path:h,options:r,mode:$s.ONE_WAY,raw:null},o=u(s),null===(a=M(t,o))&&(null!==(a=M(t,o+".sync"))?f.mode=$s.TWO_WAY:null!==(a=M(t,o+".once"))&&(f.mode=$s.ONE_TIME)),null!==a?(f.raw=a,c=A(a),a=c.expression,f.filters=c.filters,n(a)&&!c.filters?f.optimizedLiteral=!0:f.dynamic=!0,f.parentPath=a):null!==(a=I(t,o))&&(f.raw=a),p.push(f));return Ce(p)}function Ce(t){return function(e,n){e._props={};for(var r,s,l,c,f,p=e.$options.propsData,d=t.length;d--;)if(r=t[d],f=r.raw,s=r.path,l=r.options,e._props[s]=r,p&&i(p,s)&&ke(e,r,p[s]),null===f)ke(e,r,void 0);else if(r.dynamic)r.mode===$s.ONE_TIME?(c=(n||e._context||e).$get(r.parentPath),ke(e,r,c)):e._context?e._bindDir({name:"prop",def:Os,prop:r},null,null,n):ke(e,r,e.$get(r.parentPath));else if(r.optimizedLiteral){var v=h(f);c=v===f?a(o(f)):v,ke(e,r,c)}else c=l.type!==Boolean||""!==f&&f!==u(r.name)?f:!0,ke(e,r,c)}}function $e(t,e,i,n){var r=e.dynamic&&Mt(e.parentPath),s=i;void 0===s&&(s=Ae(t,e)),s=Te(e,s,t);var o=s!==i;Oe(e,s,t)||(s=void 0),r&&!o?yt(function(){n(s)}):n(s)}function ke(t,e,i){$e(t,e,i,function(i){kt(t,e.path,i)})}function xe(t,e,i){$e(t,e,i,function(i){t[e.path]=i})}function Ae(t,e){var n=e.options;if(!i(n,"default"))return n.type===Boolean?!1:void 0;var r=n["default"];return m(r),"function"==typeof r&&n.type!==Function?r.call(t):r}function Oe(t,e,i){if(!t.options.required&&(null===t.raw||null==e))return!0;var n=t.options,r=n.type,s=!r,o=[];if(r){Di(r)||(r=[r]);for(var a=0;a<r.length&&!s;a++){var h=Ne(e,r[a]);o.push(h.expectedType),s=h.valid}}if(!s)return!1;var l=n.validator;return!l||l(e)}function Te(t,e,i){var n=t.options.coerce;return n&&"function"==typeof n?n(e):e}function Ne(t,e){var i,n;return e===String?(n="string",i=typeof t===n):e===Number?(n="number",i=typeof t===n):e===Boolean?(n="boolean",i=typeof t===n):e===Function?(n="function",i=typeof t===n):e===Object?(n="object",i=g(t)):e===Array?(n="array",i=Di(t)):i=t instanceof e,{valid:i,expectedType:n}}function je(t){Ts.push(t),Ns||(Ns=!0,Yi(Ee))}function Ee(){for(var t=document.documentElement.offsetHeight,e=0;e<Ts.length;e++)Ts[e]();return Ts=[],Ns=!1,t}function Se(t,e,i,n){this.id=e,this.el=t,this.enterClass=i&&i.enterClass||e+"-enter",this.leaveClass=i&&i.leaveClass||e+"-leave",this.hooks=i,this.vm=n,this.pendingCssEvent=this.pendingCssCb=this.cancel=this.pendingJsCb=this.op=this.cb=null,this.justEntered=!1,this.entered=this.left=!1,this.typeCache={},this.type=i&&i.type;var r=this;["enterNextTick","enterDone","leaveNextTick","leaveDone"].forEach(function(t){r[t]=p(r[t],r)})}function Fe(t){if(/svg$/.test(t.namespaceURI)){var e=t.getBoundingClientRect();return!(e.width||e.height)}return!(t.offsetWidth||t.offsetHeight||t.getClientRects().length)}function De(t,e,i){var n=i||!e._asComponent?Ve(t,e):null,r=n&&n.terminal||ri(t)||!t.hasChildNodes()?null:qe(t.childNodes,e);return function(t,e,i,s,o){var a=d(e.childNodes),h=Pe(function(){n&&n(t,e,i,s,o),r&&r(t,a,i,s,o)},t);return Le(t,h)}}function Pe(t,e){e._directives=[];var i=e._directives.length;t();var n=e._directives.slice(i);n.sort(Re);for(var r=0,s=n.length;s>r;r++)n[r]._bind();return n}function Re(t,e){return t=t.descriptor.def.priority||zs,e=e.descriptor.def.priority||zs,t>e?-1:t===e?0:1}function Le(t,e,i,n){function r(r){He(t,e,r),i&&n&&He(i,n)}return r.dirs=e,r}function He(t,e,i){for(var n=e.length;n--;)e[n]._teardown()}function Ie(t,e,i,n){var r=we(e,i,t),s=Pe(function(){r(t,n)},t);return Le(t,s)}function Me(t,e,i){var n,r,s=e._containerAttrs,o=e._replacerAttrs;return 11!==t.nodeType&&(e._asComponent?(s&&i&&(n=ti(s,i)),o&&(r=ti(o,e))):r=ti(t.attributes,e)),e._containerAttrs=e._replacerAttrs=null,function(t,e,i){var s,o=t._context;o&&n&&(s=Pe(function(){n(o,e,null,i)},o));var a=Pe(function(){r&&r(t,e)},t);return Le(t,a,o,s)}}function Ve(t,e){var i=t.nodeType;return 1!==i||ri(t)?3===i&&t.data.trim()?We(t,e):null:Be(t,e)}function Be(t,e){if("TEXTAREA"===t.tagName){var i=N(t.value);i&&(t.setAttribute(":value",j(i)),t.value="")}var n,r=t.hasAttributes(),s=r&&d(t.attributes);return r&&(n=Xe(t,s,e)),n||(n=Ge(t,e)),n||(n=Ze(t,e)),!n&&r&&(n=ti(s,e)),n}function We(t,e){if(t._skip)return ze;var i=N(t.wholeText);if(!i)return null;for(var n=t.nextSibling;n&&3===n.nodeType;)n._skip=!0,n=n.nextSibling;for(var r,s,o=document.createDocumentFragment(),a=0,h=i.length;h>a;a++)s=i[a],r=s.tag?Ue(s,e):document.createTextNode(s.value),o.appendChild(r);return Je(i,o,e)}function ze(t,e){z(e)}function Ue(t,e){function i(e){if(!t.descriptor){var i=A(t.value);t.descriptor={name:e,def:bs[e],expression:i.expression,filters:i.filters}}}var n;return t.oneTime?n=document.createTextNode(t.value):t.html?(n=document.createComment("v-html"),i("html")):(n=document.createTextNode(" "),i("text")),n}function Je(t,e){return function(i,n,r,o){for(var a,h,l,c=e.cloneNode(!0),u=d(c.childNodes),f=0,p=t.length;p>f;f++)a=t[f],h=a.value,a.tag&&(l=u[f],a.oneTime?(h=(o||i).$eval(h),a.html?J(l,Xt(h,!0)):l.data=s(h)):i._bindDir(a.descriptor,l,r,o));J(n,c)}}function qe(t,e){for(var i,n,r,s=[],o=0,a=t.length;a>o;o++)r=t[o],i=Ve(r,e),n=i&&i.terminal||"SCRIPT"===r.tagName||!r.hasChildNodes()?null:qe(r.childNodes,e),s.push(i,n);return s.length?Qe(s):null}function Qe(t){return function(e,i,n,r,s){for(var o,a,h,l=0,c=0,u=t.length;u>l;c++){o=i[c],a=t[l++],h=t[l++];var f=d(o.childNodes);a&&a(e,o,n,r,s),h&&h(e,f,n,r,s)}}}function Ge(t,e){var i=t.tagName.toLowerCase();if(!jn.test(i)){var n=gt(e,"elementDirectives",i);return n?Ke(t,i,"",e,n):void 0}}function Ze(t,e){var i=lt(t,e);if(i){var n=rt(t),r={name:"component",ref:n,expression:i.id,def:Hs.component,modifiers:{literal:!i.dynamic}},s=function(t,e,i,s,o){n&&kt((s||t).$refs,n,null),t._bindDir(r,e,i,s,o)};return s.terminal=!0,s}}function Xe(t,e,i){if(null!==I(t,"v-pre"))return Ye;if(t.hasAttribute("v-else")){var n=t.previousElementSibling;if(n&&n.hasAttribute("v-if"))return Ye}for(var r,s,o,a,h,l,c,u,f,p,d=0,v=e.length;v>d;d++)r=e[d],s=r.name.replace(Bs,""),(h=s.match(Vs))&&(f=gt(i,"directives",h[1]),f&&f.terminal&&(!p||(f.priority||Us)>p.priority)&&(p=f,c=r.name,a=ei(r.name),o=r.value,l=h[1],u=h[2]));return p?Ke(t,l,o,i,p,c,u,a):void 0}function Ye(){}function Ke(t,e,i,n,r,s,o,a){var h=A(i),l={name:e,arg:o,expression:h.expression,filters:h.filters,raw:i,attr:s,modifiers:a,def:r};"for"!==e&&"router-view"!==e||(l.ref=rt(t));var c=function(t,e,i,n,r){l.ref&&kt((n||t).$refs,l.ref,null),t._bindDir(l,e,i,n,r)};return c.terminal=!0,c}function ti(t,e){function i(t,e,i){var n=i&&ni(i),r=!n&&A(s);v.push({name:t,attr:o,raw:a,def:e,arg:l,modifiers:c,expression:r&&r.expression,filters:r&&r.filters,interp:i,hasOneTime:n})}for(var n,r,s,o,a,h,l,c,u,f,p,d=t.length,v=[];d--;)if(n=t[d],r=o=n.name,s=a=n.value,f=N(s),l=null,c=ei(r),r=r.replace(Bs,""),f)s=j(f),l=r,i("bind",bs.bind,f);else if(Ws.test(r))c.literal=!Is.test(r),i("transition",Hs.transition);else if(Ms.test(r))l=r.replace(Ms,""),i("on",bs.on);else if(Is.test(r))h=r.replace(Is,""),"style"===h||"class"===h?i(h,Hs[h]):(l=h,i("bind",bs.bind));else if(p=r.match(Vs)){if(h=p[1],l=p[2],"else"===h)continue;u=gt(e,"directives",h,!0),u&&i(h,u)}return v.length?ii(v):void 0}function ei(t){var e=Object.create(null),i=t.match(Bs);if(i)for(var n=i.length;n--;)e[i[n].slice(1)]=!0;return e}function ii(t){return function(e,i,n,r,s){for(var o=t.length;o--;)e._bindDir(t[o],i,n,r,s)}}function ni(t){for(var e=t.length;e--;)if(t[e].oneTime)return!0}function ri(t){return"SCRIPT"===t.tagName&&(!t.hasAttribute("type")||"text/javascript"===t.getAttribute("type"))}function si(t,e){return e&&(e._containerAttrs=ai(t)),it(t)&&(t=Xt(t)),e&&(e._asComponent&&!e.template&&(e.template="<slot></slot>"),e.template&&(e._content=K(t),t=oi(t,e))),at(t)&&(U(nt("v-start",!0),t),t.appendChild(nt("v-end",!0))),t}function oi(t,e){var i=e.template,n=Xt(i,!0);if(n){var r=n.firstChild,s=r.tagName&&r.tagName.toLowerCase();return e.replace?(t===document.body,n.childNodes.length>1||1!==r.nodeType||"component"===s||gt(e,"components",s)||V(r,"is")||gt(e,"elementDirectives",s)||r.hasAttribute("v-for")||r.hasAttribute("v-if")?n:(e._replacerAttrs=ai(r),hi(t,r),r)):(t.appendChild(n),t)}}function ai(t){return 1===t.nodeType&&t.hasAttributes()?d(t.attributes):void 0}function hi(t,e){for(var i,n,r=t.attributes,s=r.length;s--;)i=r[s].name,n=r[s].value,e.hasAttribute(i)||Js.test(i)?"class"===i&&!N(n)&&(n=n.trim())&&n.split(/\s+/).forEach(function(t){X(e,t)}):e.setAttribute(i,n)}function li(t,e){if(e){for(var i,n,r=t._slotContents=Object.create(null),s=0,o=e.children.length;o>s;s++)i=e.children[s],(n=i.getAttribute("slot"))&&(r[n]||(r[n]=[])).push(i);for(n in r)r[n]=ci(r[n],e);if(e.hasChildNodes()){var a=e.childNodes;if(1===a.length&&3===a[0].nodeType&&!a[0].data.trim())return;r["default"]=ci(e.childNodes,e)}}}function ci(t,e){var i=document.createDocumentFragment();t=d(t);for(var n=0,r=t.length;r>n;n++){var s=t[n];!it(s)||s.hasAttribute("v-if")||s.hasAttribute("v-for")||(e.removeChild(s),s=Xt(s,!0)),i.appendChild(s)}return i}function ui(t){function e(){}function n(t,e){var i=new Ut(e,t,null,{lazy:!0});return function(){return i.dirty&&i.evaluate(),_t.target&&i.depend(),i.value}}Object.defineProperty(t.prototype,"$data",{get:function(){return this._data},set:function(t){t!==this._data&&this._setData(t)}}),t.prototype._initState=function(){this._initProps(),this._initMeta(),this._initMethods(),this._initData(),this._initComputed()},t.prototype._initProps=function(){var t=this.$options,e=t.el,i=t.props;e=t.el=L(e),this._propsUnlinkFn=e&&1===e.nodeType&&i?Ie(this,e,i,this._scope):null},t.prototype._initData=function(){var t=this.$options.data,e=this._data=t?t():{};g(e)||(e={});var n,r,s=this._props,o=Object.keys(e);for(n=o.length;n--;)r=o[n],s&&i(s,r)||this._proxy(r);$t(e,this)},t.prototype._setData=function(t){t=t||{};var e=this._data;this._data=t;var n,r,s;for(n=Object.keys(e),s=n.length;s--;)r=n[s],r in t||this._unproxy(r);for(n=Object.keys(t),s=n.length;s--;)r=n[s],i(this,r)||this._proxy(r);e.__ob__.removeVm(this),$t(t,this),this._digest()},t.prototype._proxy=function(t){if(!r(t)){var e=this;Object.defineProperty(e,t,{configurable:!0,enumerable:!0,get:function(){return e._data[t]},set:function(i){e._data[t]=i}})}},t.prototype._unproxy=function(t){r(t)||delete this[t]},t.prototype._digest=function(){for(var t=0,e=this._watchers.length;e>t;t++)this._watchers[t].update(!0)},t.prototype._initComputed=function(){var t=this.$options.computed;if(t)for(var i in t){var r=t[i],s={enumerable:!0,configurable:!0};"function"==typeof r?(s.get=n(r,this),s.set=e):(s.get=r.get?r.cache!==!1?n(r.get,this):p(r.get,this):e,s.set=r.set?p(r.set,this):e),Object.defineProperty(this,i,s)}},t.prototype._initMethods=function(){var t=this.$options.methods;if(t)for(var e in t)this[e]=p(t[e],this)},t.prototype._initMeta=function(){var t=this.$options._meta;if(t)for(var e in t)kt(this,e,t[e])}}function fi(t){function e(t,e){for(var i,n,r,s=e.attributes,o=0,a=s.length;a>o;o++)i=s[o].name,Qs.test(i)&&(i=i.replace(Qs,""),n=s[o].value,Mt(n)&&(n+=".apply(this, $arguments)"),r=(t._scope||t._context).$eval(n,!0),r._fromParent=!0,t.$on(i.replace(Qs),r))}function i(t,e,i){if(i){var r,s,o,a;for(s in i)if(r=i[s],Di(r))for(o=0,a=r.length;a>o;o++)n(t,e,s,r[o]);else n(t,e,s,r)}}function n(t,e,i,r,s){var o=typeof r;if("function"===o)t[e](i,r,s);else if("string"===o){var a=t.$options.methods,h=a&&a[r];h&&t[e](i,h,s)}else r&&"object"===o&&n(t,e,i,r.handler,r)}function r(){this._isAttached||(this._isAttached=!0,this.$children.forEach(s))}function s(t){!t._isAttached&&H(t.$el)&&t._callHook("attached")}function o(){this._isAttached&&(this._isAttached=!1,this.$children.forEach(a))}function a(t){t._isAttached&&!H(t.$el)&&t._callHook("detached")}t.prototype._initEvents=function(){var t=this.$options;t._asComponent&&e(this,t.el),i(this,"$on",t.events),i(this,"$watch",t.watch)},t.prototype._initDOMHooks=function(){this.$on("hook:attached",r),this.$on("hook:detached",o)},t.prototype._callHook=function(t){this.$emit("pre-hook:"+t);var e=this.$options[t];if(e)for(var i=0,n=e.length;n>i;i++)e[i].call(this);this.$emit("hook:"+t)}}function pi(){}function di(t,e,i,n,r,s){this.vm=e,this.el=i,this.descriptor=t,this.name=t.name,this.expression=t.expression,this.arg=t.arg,this.modifiers=t.modifiers,this.filters=t.filters,this.literal=this.modifiers&&this.modifiers.literal,this._locked=!1,this._bound=!1,this._listeners=null,this._host=n,this._scope=r,this._frag=s}function vi(t){t.prototype._updateRef=function(t){var e=this.$options._ref;if(e){var i=(this._scope||this._context).$refs;t?i[e]===this&&(i[e]=null):i[e]=this}},t.prototype._compile=function(t){var e=this.$options,i=t;if(t=si(t,e),this._initElement(t),1!==t.nodeType||null===I(t,"v-pre")){var n=this._context&&this._context.$options,r=Me(t,e,n);li(this,e._content);var s,o=this.constructor;e._linkerCachable&&(s=o.linker,s||(s=o.linker=De(t,e)));var a=r(this,t,this._scope),h=s?s(this,t):De(t,e)(this,t);this._unlinkFn=function(){a(),h(!0)},e.replace&&J(i,t),this._isCompiled=!0,this._callHook("compiled")}},t.prototype._initElement=function(t){at(t)?(this._isFragment=!0,this.$el=this._fragmentStart=t.firstChild,this._fragmentEnd=t.lastChild,3===this._fragmentStart.nodeType&&(this._fragmentStart.data=this._fragmentEnd.data=""),this._fragment=t):this.$el=t,this.$el.__vue__=this,this._callHook("beforeCompile")},t.prototype._bindDir=function(t,e,i,n,r){this._directives.push(new di(t,this,e,i,n,r))},t.prototype._destroy=function(t,e){if(this._isBeingDestroyed)return void(e||this._cleanup());var i,n,r=this,s=function(){!i||n||e||r._cleanup()};t&&this.$el&&(n=!0,this.$remove(function(){
+n=!1,s()})),this._callHook("beforeDestroy"),this._isBeingDestroyed=!0;var o,a=this.$parent;for(a&&!a._isBeingDestroyed&&(a.$children.$remove(this),this._updateRef(!0)),o=this.$children.length;o--;)this.$children[o].$destroy();for(this._propsUnlinkFn&&this._propsUnlinkFn(),this._unlinkFn&&this._unlinkFn(),o=this._watchers.length;o--;)this._watchers[o].teardown();this.$el&&(this.$el.__vue__=null),i=!0,s()},t.prototype._cleanup=function(){this._isDestroyed||(this._frag&&this._frag.children.$remove(this),this._data&&this._data.__ob__&&this._data.__ob__.removeVm(this),this.$el=this.$parent=this.$root=this.$children=this._watchers=this._context=this._scope=this._directives=null,this._isDestroyed=!0,this._callHook("destroyed"),this.$off())}}function mi(t){t.prototype._applyFilters=function(t,e,i,n){var r,s,o,a,h,l,c,u,f;for(l=0,c=i.length;c>l;l++)if(r=i[n?c-l-1:l],s=gt(this.$options,"filters",r.name,!0),s&&(s=n?s.write:s.read||s,"function"==typeof s)){if(o=n?[t,e]:[t],h=n?2:1,r.args)for(u=0,f=r.args.length;f>u;u++)a=r.args[u],o[u+h]=a.dynamic?this.$get(a.value):a.value;t=s.apply(this,o)}return t},t.prototype._resolveComponent=function(e,i){var n;if(n="function"==typeof e?e:gt(this.$options,"components",e,!0))if(n.options)i(n);else if(n.resolved)i(n.resolved);else if(n.requested)n.pendingCallbacks.push(i);else{n.requested=!0;var r=n.pendingCallbacks=[i];n.call(this,function(e){g(e)&&(e=t.extend(e)),n.resolved=e;for(var i=0,s=r.length;s>i;i++)r[i](e)},function(t){})}}}function gi(t){function i(t){return JSON.parse(JSON.stringify(t))}t.prototype.$get=function(t,e){var i=It(t);if(i){if(e){var n=this;return function(){n.$arguments=d(arguments);var t=i.get.call(n,n);return n.$arguments=null,t}}try{return i.get.call(this,this)}catch(r){}}},t.prototype.$set=function(t,e){var i=It(t,!0);i&&i.set&&i.set.call(this,this,e)},t.prototype.$delete=function(t){e(this._data,t)},t.prototype.$watch=function(t,e,i){var n,r=this;"string"==typeof t&&(n=A(t),t=n.expression);var s=new Ut(r,t,e,{deep:i&&i.deep,sync:i&&i.sync,filters:n&&n.filters,user:!i||i.user!==!1});return i&&i.immediate&&e.call(r,s.value),function(){s.teardown()}},t.prototype.$eval=function(t,e){if(Gs.test(t)){var i=A(t),n=this.$get(i.expression,e);return i.filters?this._applyFilters(n,null,i.filters):n}return this.$get(t,e)},t.prototype.$interpolate=function(t){var e=N(t),i=this;return e?1===e.length?i.$eval(e[0].value)+"":e.map(function(t){return t.tag?i.$eval(t.value):t.value}).join(""):t},t.prototype.$log=function(t){var e=t?jt(this._data,t):this._data;if(e&&(e=i(e)),!t){var n;for(n in this.$options.computed)e[n]=i(this[n]);if(this._props)for(n in this._props)e[n]=i(this[n])}console.log(e)}}function _i(t){function e(t,e,n,r,s,o){e=i(e);var a=!H(e),h=r===!1||a?s:o,l=!a&&!t._isAttached&&!H(t.$el);return t._isFragment?(st(t._fragmentStart,t._fragmentEnd,function(i){h(i,e,t)}),n&&n()):h(t.$el,e,t,n),l&&t._callHook("attached"),t}function i(t){return"string"==typeof t?document.querySelector(t):t}function n(t,e,i,n){e.appendChild(t),n&&n()}function r(t,e,i,n){B(t,e),n&&n()}function s(t,e,i){z(t),i&&i()}t.prototype.$nextTick=function(t){Yi(t,this)},t.prototype.$appendTo=function(t,i,r){return e(this,t,i,r,n,F)},t.prototype.$prependTo=function(t,e,n){return t=i(t),t.hasChildNodes()?this.$before(t.firstChild,e,n):this.$appendTo(t,e,n),this},t.prototype.$before=function(t,i,n){return e(this,t,i,n,r,D)},t.prototype.$after=function(t,e,n){return t=i(t),t.nextSibling?this.$before(t.nextSibling,e,n):this.$appendTo(t.parentNode,e,n),this},t.prototype.$remove=function(t,e){if(!this.$el.parentNode)return t&&t();var i=this._isAttached&&H(this.$el);i||(e=!1);var n=this,r=function(){i&&n._callHook("detached"),t&&t()};if(this._isFragment)ot(this._fragmentStart,this._fragmentEnd,this,this._fragment,r);else{var o=e===!1?s:P;o(this.$el,this,r)}return this}}function yi(t){function e(t,e,n){var r=t.$parent;if(r&&n&&!i.test(e))for(;r;)r._eventsCount[e]=(r._eventsCount[e]||0)+n,r=r.$parent}t.prototype.$on=function(t,i){return(this._events[t]||(this._events[t]=[])).push(i),e(this,t,1),this},t.prototype.$once=function(t,e){function i(){n.$off(t,i),e.apply(this,arguments)}var n=this;return i.fn=e,this.$on(t,i),this},t.prototype.$off=function(t,i){var n;if(!arguments.length){if(this.$parent)for(t in this._events)n=this._events[t],n&&e(this,t,-n.length);return this._events={},this}if(n=this._events[t],!n)return this;if(1===arguments.length)return e(this,t,-n.length),this._events[t]=null,this;for(var r,s=n.length;s--;)if(r=n[s],r===i||r.fn===i){e(this,t,-1),n.splice(s,1);break}return this},t.prototype.$emit=function(t){var e="string"==typeof t;t=e?t:t.name;var i=this._events[t],n=e||!i;if(i){i=i.length>1?d(i):i;var r=e&&i.some(function(t){return t._fromParent});r&&(n=!1);for(var s=d(arguments,1),o=0,a=i.length;a>o;o++){var h=i[o],l=h.apply(this,s);l!==!0||r&&!h._fromParent||(n=!0)}}return n},t.prototype.$broadcast=function(t){var e="string"==typeof t;if(t=e?t:t.name,this._eventsCount[t]){var i=this.$children,n=d(arguments);e&&(n[0]={name:t,source:this});for(var r=0,s=i.length;s>r;r++){var o=i[r],a=o.$emit.apply(o,n);a&&o.$broadcast.apply(o,n)}return this}},t.prototype.$dispatch=function(t){var e=this.$emit.apply(this,arguments);if(e){var i=this.$parent,n=d(arguments);for(n[0]={name:t,source:this};i;)e=i.$emit.apply(i,n),i=e?i.$parent:null;return this}};var i=/^hook:/}function bi(t){function e(){this._isAttached=!0,this._isReady=!0,this._callHook("ready")}t.prototype.$mount=function(t){return this._isCompiled?void 0:(t=L(t),t||(t=document.createElement("div")),this._compile(t),this._initDOMHooks(),H(this.$el)?(this._callHook("attached"),e.call(this)):this.$once("hook:attached",e),this)},t.prototype.$destroy=function(t,e){this._destroy(t,e)},t.prototype.$compile=function(t,e,i,n){return De(t,this.$options,!0)(this,t,e,i,n)}}function wi(t){this._init(t)}function Ci(t,e,i){return i=i?parseInt(i,10):0,e=o(e),"number"==typeof e?t.slice(i,i+e):t}function $i(t,e,i){if(t=Ks(t),null==e)return t;if("function"==typeof e)return t.filter(e);e=(""+e).toLowerCase();for(var n,r,s,o,a="in"===i?3:2,h=Array.prototype.concat.apply([],d(arguments,a)),l=[],c=0,u=t.length;u>c;c++)if(n=t[c],s=n&&n.$value||n,o=h.length){for(;o--;)if(r=h[o],"$key"===r&&xi(n.$key,e)||xi(jt(s,r),e)){l.push(n);break}}else xi(n,e)&&l.push(n);return l}function ki(t){function e(t,e,i){var r=n[i];return r&&("$key"!==r&&(m(t)&&"$value"in t&&(t=t.$value),m(e)&&"$value"in e&&(e=e.$value)),t=m(t)?jt(t,r):t,e=m(e)?jt(e,r):e),t===e?0:t>e?s:-s}var i=null,n=void 0;t=Ks(t);var r=d(arguments,1),s=r[r.length-1];"number"==typeof s?(s=0>s?-1:1,r=r.length>1?r.slice(0,-1):r):s=1;var o=r[0];return o?("function"==typeof o?i=function(t,e){return o(t,e)*s}:(n=Array.prototype.concat.apply([],r),i=function(t,r,s){return s=s||0,s>=n.length-1?e(t,r,s):e(t,r,s)||i(t,r,s+1)}),t.slice().sort(i)):t}function xi(t,e){var i;if(g(t)){var n=Object.keys(t);for(i=n.length;i--;)if(xi(t[n[i]],e))return!0}else if(Di(t)){for(i=t.length;i--;)if(xi(t[i],e))return!0}else if(null!=t)return t.toString().toLowerCase().indexOf(e)>-1}function Ai(i){function n(t){return new Function("return function "+f(t)+" (options) { this._init(options) }")()}i.options={directives:bs,elementDirectives:Ys,filters:eo,transitions:{},components:{},partials:{},replace:!0},i.util=In,i.config=An,i.set=t,i["delete"]=e,i.nextTick=Yi,i.compiler=qs,i.FragmentFactory=se,i.internalDirectives=Hs,i.parsers={path:ir,text:$n,template:Fr,directive:gn,expression:mr},i.cid=0;var r=1;i.extend=function(t){t=t||{};var e=this,i=0===e.cid;if(i&&t._Ctor)return t._Ctor;var s=t.name||e.options.name,o=n(s||"VueComponent");return o.prototype=Object.create(e.prototype),o.prototype.constructor=o,o.cid=r++,o.options=mt(e.options,t),o["super"]=e,o.extend=e.extend,An._assetTypes.forEach(function(t){o[t]=e[t]}),s&&(o.options.components[s]=o),i&&(t._Ctor=o),o},i.use=function(t){if(!t.installed){var e=d(arguments,1);return e.unshift(this),"function"==typeof t.install?t.install.apply(t,e):t.apply(null,e),t.installed=!0,this}},i.mixin=function(t){i.options=mt(i.options,t)},An._assetTypes.forEach(function(t){i[t]=function(e,n){return n?("component"===t&&g(n)&&(n.name||(n.name=e),n=i.extend(n)),this.options[t+"s"][e]=n,n):this.options[t+"s"][e]}}),v(i.transition,Tn)}var Oi=Object.prototype.hasOwnProperty,Ti=/^\s?(true|false|-?[\d\.]+|'[^']*'|"[^"]*")\s?$/,Ni=/-(\w)/g,ji=/([a-z\d])([A-Z])/g,Ei=/(?:^|[-_\/])(\w)/g,Si=Object.prototype.toString,Fi="[object Object]",Di=Array.isArray,Pi="__proto__"in{},Ri="undefined"!=typeof window&&"[object Object]"!==Object.prototype.toString.call(window),Li=Ri&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__,Hi=Ri&&window.navigator.userAgent.toLowerCase(),Ii=Hi&&Hi.indexOf("trident")>0,Mi=Hi&&Hi.indexOf("msie 9.0")>0,Vi=Hi&&Hi.indexOf("android")>0,Bi=Hi&&/(iphone|ipad|ipod|ios)/i.test(Hi),Wi=Bi&&Hi.match(/os ([\d_]+)/),zi=Wi&&Wi[1].split("_"),Ui=zi&&Number(zi[0])>=9&&Number(zi[1])>=3&&!window.indexedDB,Ji=void 0,qi=void 0,Qi=void 0,Gi=void 0;if(Ri&&!Mi){var Zi=void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend,Xi=void 0===window.onanimationend&&void 0!==window.onwebkitanimationend;Ji=Zi?"WebkitTransition":"transition",qi=Zi?"webkitTransitionEnd":"transitionend",Qi=Xi?"WebkitAnimation":"animation",Gi=Xi?"webkitAnimationEnd":"animationend"}var Yi=function(){function t(){n=!1;var t=i.slice(0);i=[];for(var e=0;e<t.length;e++)t[e]()}var e,i=[],n=!1;if("undefined"==typeof MutationObserver||Ui){var r=Ri?window:"undefined"!=typeof global?global:{};e=r.setImmediate||setTimeout}else{var s=1,o=new MutationObserver(t),a=document.createTextNode(s);o.observe(a,{characterData:!0}),e=function(){s=(s+1)%2,a.data=s}}return function(r,s){var o=s?function(){r.call(s)}:r;i.push(o),n||(n=!0,e(t,0))}}(),Ki=void 0;"undefined"!=typeof Set&&Set.toString().match(/native code/)?Ki=Set:(Ki=function(){this.set=Object.create(null)},Ki.prototype.has=function(t){return void 0!==this.set[t]},Ki.prototype.add=function(t){this.set[t]=1},Ki.prototype.clear=function(){this.set=Object.create(null)});var tn=$.prototype;tn.put=function(t,e){var i,n=this.get(t,!0);return n||(this.size===this.limit&&(i=this.shift()),n={key:t},this._keymap[t]=n,this.tail?(this.tail.newer=n,n.older=this.tail):this.head=n,this.tail=n,this.size++),n.value=e,i},tn.shift=function(){var t=this.head;return t&&(this.head=this.head.newer,this.head.older=void 0,t.newer=t.older=void 0,this._keymap[t.key]=void 0,this.size--),t},tn.get=function(t,e){var i=this._keymap[t];if(void 0!==i)return i===this.tail?e?i:i.value:(i.newer&&(i===this.head&&(this.head=i.newer),i.newer.older=i.older),i.older&&(i.older.newer=i.newer),i.newer=void 0,i.older=this.tail,this.tail&&(this.tail.newer=i),this.tail=i,e?i:i.value)};var en,nn,rn,sn,on,an,hn,ln,cn,un,fn,pn,dn=new $(1e3),vn=/[^\s'"]+|'[^']*'|"[^"]*"/g,mn=/^in$|^-?\d+/,gn=Object.freeze({parseDirective:A}),_n=/[-.*+?^${}()|[\]\/\\]/g,yn=void 0,bn=void 0,wn=void 0,Cn=/[^|]\|[^|]/,$n=Object.freeze({compileRegex:T,parseText:N,tokensToExp:j}),kn=["{{","}}"],xn=["{{{","}}}"],An=Object.defineProperties({debug:!1,silent:!1,async:!0,warnExpressionErrors:!0,devtools:!1,_delimitersChanged:!0,_assetTypes:["component","directive","elementDirective","filter","transition","partial"],_propBindingModes:{ONE_WAY:0,TWO_WAY:1,ONE_TIME:2},_maxUpdateCount:100},{delimiters:{get:function(){return kn},set:function(t){kn=t,T()},configurable:!0,enumerable:!0},unsafeDelimiters:{get:function(){return xn},set:function(t){xn=t,T()},configurable:!0,enumerable:!0}}),On=void 0,Tn=Object.freeze({appendWithTransition:F,beforeWithTransition:D,removeWithTransition:P,applyTransition:R}),Nn=/^v-ref:/,jn=/^(div|p|span|img|a|b|i|br|ul|ol|li|h1|h2|h3|h4|h5|h6|code|pre|table|th|td|tr|form|label|input|select|option|nav|article|section|header|footer)$/i,En=/^(slot|partial|component)$/i,Sn=An.optionMergeStrategies=Object.create(null);Sn.data=function(t,e,i){return i?t||e?function(){var n="function"==typeof e?e.call(i):e,r="function"==typeof t?t.call(i):void 0;return n?ut(n,r):r}:void 0:e?"function"!=typeof e?t:t?function(){return ut(e.call(this),t.call(this))}:e:t},Sn.el=function(t,e,i){if(i||!e||"function"==typeof e){var n=e||t;return i&&"function"==typeof n?n.call(i):n}},Sn.init=Sn.created=Sn.ready=Sn.attached=Sn.detached=Sn.beforeCompile=Sn.compiled=Sn.beforeDestroy=Sn.destroyed=Sn.activate=function(t,e){return e?t?t.concat(e):Di(e)?e:[e]:t},An._assetTypes.forEach(function(t){Sn[t+"s"]=ft}),Sn.watch=Sn.events=function(t,e){if(!e)return t;if(!t)return e;var i={};v(i,t);for(var n in e){var r=i[n],s=e[n];r&&!Di(r)&&(r=[r]),i[n]=r?r.concat(s):[s]}return i},Sn.props=Sn.methods=Sn.computed=function(t,e){if(!e)return t;if(!t)return e;var i=Object.create(null);return v(i,t),v(i,e),i};var Fn=function(t,e){return void 0===e?t:e},Dn=0;_t.target=null,_t.prototype.addSub=function(t){this.subs.push(t)},_t.prototype.removeSub=function(t){this.subs.$remove(t)},_t.prototype.depend=function(){_t.target.addDep(this)},_t.prototype.notify=function(){for(var t=d(this.subs),e=0,i=t.length;i>e;e++)t[e].update()};var Pn=Array.prototype,Rn=Object.create(Pn);["push","pop","shift","unshift","splice","sort","reverse"].forEach(function(t){var e=Pn[t];_(Rn,t,function(){for(var i=arguments.length,n=new Array(i);i--;)n[i]=arguments[i];var r,s=e.apply(this,n),o=this.__ob__;switch(t){case"push":r=n;break;case"unshift":r=n;break;case"splice":r=n.slice(2)}return r&&o.observeArray(r),o.dep.notify(),s})}),_(Pn,"$set",function(t,e){return t>=this.length&&(this.length=Number(t)+1),this.splice(t,1,e)[0]}),_(Pn,"$remove",function(t){if(this.length){var e=b(this,t);return e>-1?this.splice(e,1):void 0}});var Ln=Object.getOwnPropertyNames(Rn),Hn=!0;bt.prototype.walk=function(t){for(var e=Object.keys(t),i=0,n=e.length;n>i;i++)this.convert(e[i],t[e[i]])},bt.prototype.observeArray=function(t){for(var e=0,i=t.length;i>e;e++)$t(t[e])},bt.prototype.convert=function(t,e){kt(this.value,t,e)},bt.prototype.addVm=function(t){(this.vms||(this.vms=[])).push(t)},bt.prototype.removeVm=function(t){this.vms.$remove(t)};var In=Object.freeze({defineReactive:kt,set:t,del:e,hasOwn:i,isLiteral:n,isReserved:r,_toString:s,toNumber:o,toBoolean:a,stripQuotes:h,camelize:l,hyphenate:u,classify:f,bind:p,toArray:d,extend:v,isObject:m,isPlainObject:g,def:_,debounce:y,indexOf:b,cancellable:w,looseEqual:C,isArray:Di,hasProto:Pi,inBrowser:Ri,devtools:Li,isIE:Ii,isIE9:Mi,isAndroid:Vi,isIos:Bi,iosVersionMatch:Wi,iosVersion:zi,hasMutationObserverBug:Ui,get transitionProp(){return Ji},get transitionEndEvent(){return qi},get animationProp(){return Qi},get animationEndEvent(){return Gi},nextTick:Yi,get _Set(){return Ki},query:L,inDoc:H,getAttr:I,getBindAttr:M,hasBindAttr:V,before:B,after:W,remove:z,prepend:U,replace:J,on:q,off:Q,setClass:Z,addClass:X,removeClass:Y,extractContent:K,trimNode:tt,isTemplate:it,createAnchor:nt,findRef:rt,mapNodeRange:st,removeNodeRange:ot,isFragment:at,getOuterHTML:ht,mergeOptions:mt,resolveAsset:gt,checkComponentAttr:lt,commonTagRE:jn,reservedTagRE:En,warn:On}),Mn=0,Vn=new $(1e3),Bn=0,Wn=1,zn=2,Un=3,Jn=0,qn=1,Qn=2,Gn=3,Zn=4,Xn=5,Yn=6,Kn=7,tr=8,er=[];er[Jn]={ws:[Jn],ident:[Gn,Bn],"[":[Zn],eof:[Kn]},er[qn]={ws:[qn],".":[Qn],"[":[Zn],eof:[Kn]},er[Qn]={ws:[Qn],ident:[Gn,Bn]},er[Gn]={ident:[Gn,Bn],0:[Gn,Bn],number:[Gn,Bn],ws:[qn,Wn],".":[Qn,Wn],"[":[Zn,Wn],eof:[Kn,Wn]},er[Zn]={"'":[Xn,Bn],'"':[Yn,Bn],"[":[Zn,zn],"]":[qn,Un],eof:tr,"else":[Zn,Bn]},er[Xn]={"'":[Zn,Bn],eof:tr,"else":[Xn,Bn]},er[Yn]={'"':[Zn,Bn],eof:tr,"else":[Yn,Bn]};var ir=Object.freeze({parsePath:Nt,getPath:jt,setPath:Et}),nr=new $(1e3),rr="Math,Date,this,true,false,null,undefined,Infinity,NaN,isNaN,isFinite,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,parseInt,parseFloat",sr=new RegExp("^("+rr.replace(/,/g,"\\b|")+"\\b)"),or="break,case,class,catch,const,continue,debugger,default,delete,do,else,export,extends,finally,for,function,if,import,in,instanceof,let,return,super,switch,throw,try,var,while,with,yield,enum,await,implements,package,protected,static,interface,private,public",ar=new RegExp("^("+or.replace(/,/g,"\\b|")+"\\b)"),hr=/\s/g,lr=/\n/g,cr=/[\{,]\s*[\w\$_]+\s*:|('(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`)|new |typeof |void /g,ur=/"(\d+)"/g,fr=/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['.*?'\]|\[".*?"\]|\[\d+\]|\[[A-Za-z_$][\w$]*\])*$/,pr=/[^\w$\.](?:[A-Za-z_$][\w$]*)/g,dr=/^(?:true|false|null|undefined|Infinity|NaN)$/,vr=[],mr=Object.freeze({parseExpression:It,isSimplePath:Mt}),gr=[],_r=[],yr={},br={},wr=!1,Cr=0;Ut.prototype.get=function(){this.beforeGet();var t,e=this.scope||this.vm;try{t=this.getter.call(e,e)}catch(i){}return this.deep&&Jt(t),this.preProcess&&(t=this.preProcess(t)),this.filters&&(t=e._applyFilters(t,null,this.filters,!1)),this.postProcess&&(t=this.postProcess(t)),this.afterGet(),t},Ut.prototype.set=function(t){var e=this.scope||this.vm;this.filters&&(t=e._applyFilters(t,this.value,this.filters,!0));try{this.setter.call(e,e,t)}catch(i){}var n=e.$forContext;if(n&&n.alias===this.expression){if(n.filters)return;n._withLock(function(){e.$key?n.rawValue[e.$key]=t:n.rawValue.$set(e.$index,t)})}},Ut.prototype.beforeGet=function(){_t.target=this},Ut.prototype.addDep=function(t){var e=t.id;this.newDepIds.has(e)||(this.newDepIds.add(e),this.newDeps.push(t),this.depIds.has(e)||t.addSub(this))},Ut.prototype.afterGet=function(){_t.target=null;for(var t=this.deps.length;t--;){var e=this.deps[t];this.newDepIds.has(e.id)||e.removeSub(this)}var i=this.depIds;this.depIds=this.newDepIds,this.newDepIds=i,this.newDepIds.clear(),i=this.deps,this.deps=this.newDeps,this.newDeps=i,this.newDeps.length=0},Ut.prototype.update=function(t){this.lazy?this.dirty=!0:this.sync||!An.async?this.run():(this.shallow=this.queued?t?this.shallow:!1:!!t,this.queued=!0,zt(this))},Ut.prototype.run=function(){if(this.active){var t=this.get();if(t!==this.value||(m(t)||this.deep)&&!this.shallow){var e=this.value;this.value=t;this.prevError;this.cb.call(this.vm,t,e)}this.queued=this.shallow=!1}},Ut.prototype.evaluate=function(){var t=_t.target;this.value=this.get(),this.dirty=!1,_t.target=t},Ut.prototype.depend=function(){for(var t=this.deps.length;t--;)this.deps[t].depend()},Ut.prototype.teardown=function(){if(this.active){this.vm._isBeingDestroyed||this.vm._vForRemoving||this.vm._watchers.$remove(this);for(var t=this.deps.length;t--;)this.deps[t].removeSub(this);this.active=!1,this.vm=this.cb=this.value=null}};var $r=new Ki,kr={bind:function(){this.attr=3===this.el.nodeType?"data":"textContent"},update:function(t){this.el[this.attr]=s(t)}},xr=new $(1e3),Ar=new $(1e3),Or={efault:[0,"",""],legend:[1,"<fieldset>","</fieldset>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]};Or.td=Or.th=[3,"<table><tbody><tr>","</tr></tbody></table>"],Or.option=Or.optgroup=[1,'<select multiple="multiple">',"</select>"],Or.thead=Or.tbody=Or.colgroup=Or.caption=Or.tfoot=[1,"<table>","</table>"],Or.g=Or.defs=Or.symbol=Or.use=Or.image=Or.text=Or.circle=Or.ellipse=Or.line=Or.path=Or.polygon=Or.polyline=Or.rect=[1,'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events"version="1.1">',"</svg>"];var Tr=/<([\w:-]+)/,Nr=/&#?\w+?;/,jr=/<!--/,Er=function(){if(Ri){var t=document.createElement("div");return t.innerHTML="<template>1</template>",!t.cloneNode(!0).firstChild.innerHTML}return!1}(),Sr=function(){if(Ri){var t=document.createElement("textarea");return t.placeholder="t","t"===t.cloneNode(!0).value}return!1}(),Fr=Object.freeze({cloneNode:Zt,parseTemplate:Xt}),Dr={bind:function(){8===this.el.nodeType&&(this.nodes=[],this.anchor=nt("v-html"),J(this.el,this.anchor))},update:function(t){t=s(t),this.nodes?this.swap(t):this.el.innerHTML=t},swap:function(t){for(var e=this.nodes.length;e--;)z(this.nodes[e]);var i=Xt(t,!0,!0);this.nodes=d(i.childNodes),B(i,this.anchor)}};Yt.prototype.callHook=function(t){var e,i;for(e=0,i=this.childFrags.length;i>e;e++)this.childFrags[e].callHook(t);for(e=0,i=this.children.length;i>e;e++)t(this.children[e])},Yt.prototype.beforeRemove=function(){var t,e;for(t=0,e=this.childFrags.length;e>t;t++)this.childFrags[t].beforeRemove(!1);for(t=0,e=this.children.length;e>t;t++)this.children[t].$destroy(!1,!0);var i=this.unlink.dirs;for(t=0,e=i.length;e>t;t++)i[t]._watcher&&i[t]._watcher.teardown()},Yt.prototype.destroy=function(){this.parentFrag&&this.parentFrag.childFrags.$remove(this),this.node.__v_frag=null,this.unlink()};var Pr=new $(5e3);se.prototype.create=function(t,e,i){var n=Zt(this.template);return new Yt(this.linker,this.vm,n,t,e,i)};var Rr=700,Lr=800,Hr=850,Ir=1100,Mr=1500,Vr=1500,Br=1750,Wr=2100,zr=2200,Ur=2300,Jr=0,qr={priority:zr,terminal:!0,params:["track-by","stagger","enter-stagger","leave-stagger"],bind:function(){var t=this.expression.match(/(.*) (?:in|of) (.*)/);if(t){var e=t[1].match(/\((.*),(.*)\)/);e?(this.iterator=e[1].trim(),this.alias=e[2].trim()):this.alias=t[1].trim(),this.expression=t[2]}if(this.alias){this.id="__v-for__"+ ++Jr;var i=this.el.tagName;this.isOption=("OPTION"===i||"OPTGROUP"===i)&&"SELECT"===this.el.parentNode.tagName,this.start=nt("v-for-start"),this.end=nt("v-for-end"),J(this.el,this.end),B(this.start,this.end),this.cache=Object.create(null),this.factory=new se(this.vm,this.el)}},update:function(t){this.diff(t),this.updateRef(),this.updateModel()},diff:function(t){var e,n,r,s,o,a,h=t[0],l=this.fromObject=m(h)&&i(h,"$key")&&i(h,"$value"),c=this.params.trackBy,u=this.frags,f=this.frags=new Array(t.length),p=this.alias,d=this.iterator,v=this.start,g=this.end,_=H(v),y=!u;for(e=0,n=t.length;n>e;e++)h=t[e],s=l?h.$key:null,o=l?h.$value:h,a=!m(o),r=!y&&this.getCachedFrag(o,e,s),r?(r.reused=!0,r.scope.$index=e,s&&(r.scope.$key=s),d&&(r.scope[d]=null!==s?s:e),(c||l||a)&&yt(function(){r.scope[p]=o})):(r=this.create(o,p,e,s),r.fresh=!y),f[e]=r,y&&r.before(g);if(!y){var b=0,w=u.length-f.length;for(this.vm._vForRemoving=!0,e=0,n=u.length;n>e;e++)r=u[e],r.reused||(this.deleteCachedFrag(r),this.remove(r,b++,w,_));this.vm._vForRemoving=!1,b&&(this.vm._watchers=this.vm._watchers.filter(function(t){return t.active}));var C,$,k,x=0;for(e=0,n=f.length;n>e;e++)r=f[e],C=f[e-1],$=C?C.staggerCb?C.staggerAnchor:C.end||C.node:v,r.reused&&!r.staggerCb?(k=oe(r,v,this.id),k===C||k&&oe(k,v,this.id)===C||this.move(r,$)):this.insert(r,x++,$,_),r.reused=r.fresh=!1}},create:function(t,e,i,n){var r=this._host,s=this._scope||this.vm,o=Object.create(s);o.$refs=Object.create(s.$refs),o.$els=Object.create(s.$els),o.$parent=s,o.$forContext=this,yt(function(){kt(o,e,t)}),kt(o,"$index",i),n?kt(o,"$key",n):o.$key&&_(o,"$key",null),this.iterator&&kt(o,this.iterator,null!==n?n:i);var a=this.factory.create(r,o,this._frag);return a.forId=this.id,this.cacheFrag(t,a,i,n),a},updateRef:function(){var t=this.descriptor.ref;if(t){var e,i=(this._scope||this.vm).$refs;this.fromObject?(e={},this.frags.forEach(function(t){e[t.scope.$key]=ae(t)})):e=this.frags.map(ae),i[t]=e}},updateModel:function(){if(this.isOption){var t=this.start.parentNode,e=t&&t.__v_model;e&&e.forceUpdate()}},insert:function(t,e,i,n){t.staggerCb&&(t.staggerCb.cancel(),t.staggerCb=null);var r=this.getStagger(t,e,null,"enter");if(n&&r){var s=t.staggerAnchor;s||(s=t.staggerAnchor=nt("stagger-anchor"),s.__v_frag=t),W(s,i);var o=t.staggerCb=w(function(){t.staggerCb=null,t.before(s),z(s)});setTimeout(o,r)}else{var a=i.nextSibling;a||(W(this.end,i),a=this.end),t.before(a)}},remove:function(t,e,i,n){if(t.staggerCb)return t.staggerCb.cancel(),void(t.staggerCb=null);var r=this.getStagger(t,e,i,"leave");if(n&&r){var s=t.staggerCb=w(function(){t.staggerCb=null,t.remove()});setTimeout(s,r)}else t.remove()},move:function(t,e){e.nextSibling||this.end.parentNode.appendChild(this.end),t.before(e.nextSibling,!1)},cacheFrag:function(t,e,n,r){var s,o=this.params.trackBy,a=this.cache,h=!m(t);r||o||h?(s=le(n,r,t,o),a[s]||(a[s]=e)):(s=this.id,i(t,s)?null===t[s]&&(t[s]=e):Object.isExtensible(t)&&_(t,s,e)),e.raw=t},getCachedFrag:function(t,e,i){var n,r=this.params.trackBy,s=!m(t);if(i||r||s){var o=le(e,i,t,r);n=this.cache[o]}else n=t[this.id];return n&&(n.reused||n.fresh),n},deleteCachedFrag:function(t){var e=t.raw,n=this.params.trackBy,r=t.scope,s=r.$index,o=i(r,"$key")&&r.$key,a=!m(e);if(n||o||a){var h=le(s,o,e,n);this.cache[h]=null}else e[this.id]=null,t.raw=null},getStagger:function(t,e,i,n){n+="Stagger";var r=t.node.__v_trans,s=r&&r.hooks,o=s&&(s[n]||s.stagger);return o?o.call(t,e,i):e*parseInt(this.params[n]||this.params.stagger,10)},_preProcess:function(t){return this.rawValue=t,t},_postProcess:function(t){if(Di(t))return t;if(g(t)){for(var e,i=Object.keys(t),n=i.length,r=new Array(n);n--;)e=i[n],r[n]={$key:e,$value:t[e]};return r}return"number"!=typeof t||isNaN(t)||(t=he(t)),t||[]},unbind:function(){if(this.descriptor.ref&&((this._scope||this.vm).$refs[this.descriptor.ref]=null),this.frags)for(var t,e=this.frags.length;e--;)t=this.frags[e],this.deleteCachedFrag(t),t.destroy()}},Qr={priority:Wr,terminal:!0,bind:function(){var t=this.el;if(t.__vue__)this.invalid=!0;else{var e=t.nextElementSibling;e&&null!==I(e,"v-else")&&(z(e),this.elseEl=e),this.anchor=nt("v-if"),J(t,this.anchor)}},update:function(t){this.invalid||(t?this.frag||this.insert():this.remove())},insert:function(){this.elseFrag&&(this.elseFrag.remove(),this.elseFrag=null),this.factory||(this.factory=new se(this.vm,this.el)),this.frag=this.factory.create(this._host,this._scope,this._frag),this.frag.before(this.anchor)},remove:function(){this.frag&&(this.frag.remove(),this.frag=null),this.elseEl&&!this.elseFrag&&(this.elseFactory||(this.elseFactory=new se(this.elseEl._context||this.vm,this.elseEl)),this.elseFrag=this.elseFactory.create(this._host,this._scope,this._frag),this.elseFrag.before(this.anchor))},unbind:function(){this.frag&&this.frag.destroy(),this.elseFrag&&this.elseFrag.destroy()}},Gr={bind:function(){var t=this.el.nextElementSibling;t&&null!==I(t,"v-else")&&(this.elseEl=t)},update:function(t){this.apply(this.el,t),this.elseEl&&this.apply(this.elseEl,!t)},apply:function(t,e){function i(){t.style.display=e?"":"none"}H(t)?R(t,e?1:-1,i,this.vm):i()}},Zr={bind:function(){var t=this,e=this.el,i="range"===e.type,n=this.params.lazy,r=this.params.number,s=this.params.debounce,a=!1;if(Vi||i||(this.on("compositionstart",function(){a=!0}),this.on("compositionend",function(){a=!1,n||t.listener()})),this.focused=!1,i||n||(this.on("focus",function(){t.focused=!0}),this.on("blur",function(){t.focused=!1,t._frag&&!t._frag.inserted||t.rawListener()})),this.listener=this.rawListener=function(){if(!a&&t._bound){var n=r||i?o(e.value):e.value;t.set(n),Yi(function(){t._bound&&!t.focused&&t.update(t._watcher.value)})}},s&&(this.listener=y(this.listener,s)),this.hasjQuery="function"==typeof jQuery,this.hasjQuery){var h=jQuery.fn.on?"on":"bind";jQuery(e)[h]("change",this.rawListener),n||jQuery(e)[h]("input",this.listener)}else this.on("change",this.rawListener),n||this.on("input",this.listener);!n&&Mi&&(this.on("cut",function(){Yi(t.listener)}),this.on("keyup",function(e){46!==e.keyCode&&8!==e.keyCode||t.listener()})),(e.hasAttribute("value")||"TEXTAREA"===e.tagName&&e.value.trim())&&(this.afterBind=this.listener)},update:function(t){t=s(t),t!==this.el.value&&(this.el.value=t)},unbind:function(){var t=this.el;if(this.hasjQuery){var e=jQuery.fn.off?"off":"unbind";jQuery(t)[e]("change",this.listener),jQuery(t)[e]("input",this.listener)}}},Xr={bind:function(){var t=this,e=this.el;this.getValue=function(){if(e.hasOwnProperty("_value"))return e._value;var i=e.value;return t.params.number&&(i=o(i)),i},this.listener=function(){t.set(t.getValue())},this.on("change",this.listener),e.hasAttribute("checked")&&(this.afterBind=this.listener)},update:function(t){this.el.checked=C(t,this.getValue())}},Yr={bind:function(){var t=this,e=this,i=this.el;this.forceUpdate=function(){e._watcher&&e.update(e._watcher.get())};var n=this.multiple=i.hasAttribute("multiple");this.listener=function(){var t=ce(i,n);t=e.params.number?Di(t)?t.map(o):o(t):t,e.set(t)},this.on("change",this.listener);var r=ce(i,n,!0);(n&&r.length||!n&&null!==r)&&(this.afterBind=this.listener),this.vm.$on("hook:attached",function(){Yi(t.forceUpdate)}),H(i)||Yi(this.forceUpdate)},update:function(t){var e=this.el;e.selectedIndex=-1;for(var i,n,r=this.multiple&&Di(t),s=e.options,o=s.length;o--;)i=s[o],n=i.hasOwnProperty("_value")?i._value:i.value,i.selected=r?ue(t,n)>-1:C(t,n)},unbind:function(){this.vm.$off("hook:attached",this.forceUpdate)}},Kr={bind:function(){function t(){var t=i.checked;return t&&i.hasOwnProperty("_trueValue")?i._trueValue:!t&&i.hasOwnProperty("_falseValue")?i._falseValue:t}var e=this,i=this.el;this.getValue=function(){return i.hasOwnProperty("_value")?i._value:e.params.number?o(i.value):i.value},this.listener=function(){var n=e._watcher.value;if(Di(n)){var r=e.getValue();i.checked?b(n,r)<0&&n.push(r):n.$remove(r)}else e.set(t())},this.on("change",this.listener),i.hasAttribute("checked")&&(this.afterBind=this.listener)},update:function(t){var e=this.el;Di(t)?e.checked=b(t,this.getValue())>-1:e.hasOwnProperty("_trueValue")?e.checked=C(t,e._trueValue):e.checked=!!t}},ts={text:Zr,radio:Xr,select:Yr,checkbox:Kr},es={priority:Lr,twoWay:!0,handlers:ts,params:["lazy","number","debounce"],bind:function(){this.checkFilters(),this.hasRead&&!this.hasWrite;var t,e=this.el,i=e.tagName;if("INPUT"===i)t=ts[e.type]||ts.text;else if("SELECT"===i)t=ts.select;else{if("TEXTAREA"!==i)return;t=ts.text}e.__v_model=this,t.bind.call(this),this.update=t.update,this._unbind=t.unbind},checkFilters:function(){var t=this.filters;if(t)for(var e=t.length;e--;){var i=gt(this.vm.$options,"filters",t[e].name);("function"==typeof i||i.read)&&(this.hasRead=!0),i.write&&(this.hasWrite=!0)}},unbind:function(){this.el.__v_model=null,this._unbind&&this._unbind()}},is={esc:27,tab:9,enter:13,space:32,"delete":[8,46],up:38,left:37,right:39,down:40},ns={priority:Rr,acceptStatement:!0,keyCodes:is,bind:function(){if("IFRAME"===this.el.tagName&&"load"!==this.arg){var t=this;this.iframeBind=function(){q(t.el.contentWindow,t.arg,t.handler,t.modifiers.capture)},this.on("load",this.iframeBind)}},update:function(t){if(this.descriptor.raw||(t=function(){}),"function"==typeof t){this.modifiers.stop&&(t=pe(t)),this.modifiers.prevent&&(t=de(t)),this.modifiers.self&&(t=ve(t));var e=Object.keys(this.modifiers).filter(function(t){return"stop"!==t&&"prevent"!==t&&"self"!==t&&"capture"!==t});e.length&&(t=fe(t,e)),this.reset(),this.handler=t,this.iframeBind?this.iframeBind():q(this.el,this.arg,this.handler,this.modifiers.capture)}},reset:function(){var t=this.iframeBind?this.el.contentWindow:this.el;this.handler&&Q(t,this.arg,this.handler)},unbind:function(){this.reset()}},rs=["-webkit-","-moz-","-ms-"],ss=["Webkit","Moz","ms"],os=/!important;?$/,as=Object.create(null),hs=null,ls={deep:!0,update:function(t){"string"==typeof t?this.el.style.cssText=t:Di(t)?this.handleObject(t.reduce(v,{})):this.handleObject(t||{})},handleObject:function(t){var e,i,n=this.cache||(this.cache={});for(e in n)e in t||(this.handleSingle(e,null),delete n[e]);for(e in t)i=t[e],i!==n[e]&&(n[e]=i,this.handleSingle(e,i))},handleSingle:function(t,e){if(t=me(t))if(null!=e&&(e+=""),e){var i=os.test(e)?"important":"";i?(e=e.replace(os,"").trim(),this.el.style.setProperty(t.kebab,e,i)):this.el.style[t.camel]=e}else this.el.style[t.camel]=""}},cs="http://www.w3.org/1999/xlink",us=/^xlink:/,fs=/^v-|^:|^@|^(?:is|transition|transition-mode|debounce|track-by|stagger|enter-stagger|leave-stagger)$/,ps=/^(?:value|checked|selected|muted)$/,ds=/^(?:draggable|contenteditable|spellcheck)$/,vs={value:"_value","true-value":"_trueValue","false-value":"_falseValue"},ms={priority:Hr,bind:function(){var t=this.arg,e=this.el.tagName;t||(this.deep=!0);var i=this.descriptor,n=i.interp;n&&(i.hasOneTime&&(this.expression=j(n,this._scope||this.vm)),(fs.test(t)||"name"===t&&("PARTIAL"===e||"SLOT"===e))&&(this.el.removeAttribute(t),this.invalid=!0))},update:function(t){
+if(!this.invalid){var e=this.arg;this.arg?this.handleSingle(e,t):this.handleObject(t||{})}},handleObject:ls.handleObject,handleSingle:function(t,e){var i=this.el,n=this.descriptor.interp;if(this.modifiers.camel&&(t=l(t)),!n&&ps.test(t)&&t in i){var r="value"===t&&null==e?"":e;i[t]!==r&&(i[t]=r)}var s=vs[t];if(!n&&s){i[s]=e;var o=i.__v_model;o&&o.listener()}return"value"===t&&"TEXTAREA"===i.tagName?void i.removeAttribute(t):void(ds.test(t)?i.setAttribute(t,e?"true":"false"):null!=e&&e!==!1?"class"===t?(i.__v_trans&&(e+=" "+i.__v_trans.id+"-transition"),Z(i,e)):us.test(t)?i.setAttributeNS(cs,t,e===!0?"":e):i.setAttribute(t,e===!0?"":e):i.removeAttribute(t))}},gs={priority:Mr,bind:function(){if(this.arg){var t=this.id=l(this.arg),e=(this._scope||this.vm).$els;i(e,t)?e[t]=this.el:kt(e,t,this.el)}},unbind:function(){var t=(this._scope||this.vm).$els;t[this.id]===this.el&&(t[this.id]=null)}},_s={bind:function(){}},ys={bind:function(){var t=this.el;this.vm.$once("pre-hook:compiled",function(){t.removeAttribute("v-cloak")})}},bs={text:kr,html:Dr,"for":qr,"if":Qr,show:Gr,model:es,on:ns,bind:ms,el:gs,ref:_s,cloak:ys},ws={deep:!0,update:function(t){t?"string"==typeof t?this.setClass(t.trim().split(/\s+/)):this.setClass(_e(t)):this.cleanup()},setClass:function(t){this.cleanup(t);for(var e=0,i=t.length;i>e;e++){var n=t[e];n&&ye(this.el,n,X)}this.prevKeys=t},cleanup:function(t){var e=this.prevKeys;if(e)for(var i=e.length;i--;){var n=e[i];(!t||t.indexOf(n)<0)&&ye(this.el,n,Y)}}},Cs={priority:Vr,params:["keep-alive","transition-mode","inline-template"],bind:function(){this.el.__vue__||(this.keepAlive=this.params.keepAlive,this.keepAlive&&(this.cache={}),this.params.inlineTemplate&&(this.inlineTemplate=K(this.el,!0)),this.pendingComponentCb=this.Component=null,this.pendingRemovals=0,this.pendingRemovalCb=null,this.anchor=nt("v-component"),J(this.el,this.anchor),this.el.removeAttribute("is"),this.el.removeAttribute(":is"),this.descriptor.ref&&this.el.removeAttribute("v-ref:"+u(this.descriptor.ref)),this.literal&&this.setComponent(this.expression))},update:function(t){this.literal||this.setComponent(t)},setComponent:function(t,e){if(this.invalidatePending(),t){var i=this;this.resolveComponent(t,function(){i.mountComponent(e)})}else this.unbuild(!0),this.remove(this.childVM,e),this.childVM=null},resolveComponent:function(t,e){var i=this;this.pendingComponentCb=w(function(n){i.ComponentName=n.options.name||("string"==typeof t?t:null),i.Component=n,e()}),this.vm._resolveComponent(t,this.pendingComponentCb)},mountComponent:function(t){this.unbuild(!0);var e=this,i=this.Component.options.activate,n=this.getCached(),r=this.build();i&&!n?(this.waitingFor=r,be(i,r,function(){e.waitingFor===r&&(e.waitingFor=null,e.transition(r,t))})):(n&&r._updateRef(),this.transition(r,t))},invalidatePending:function(){this.pendingComponentCb&&(this.pendingComponentCb.cancel(),this.pendingComponentCb=null)},build:function(t){var e=this.getCached();if(e)return e;if(this.Component){var i={name:this.ComponentName,el:Zt(this.el),template:this.inlineTemplate,parent:this._host||this.vm,_linkerCachable:!this.inlineTemplate,_ref:this.descriptor.ref,_asComponent:!0,_isRouterView:this._isRouterView,_context:this.vm,_scope:this._scope,_frag:this._frag};t&&v(i,t);var n=new this.Component(i);return this.keepAlive&&(this.cache[this.Component.cid]=n),n}},getCached:function(){return this.keepAlive&&this.cache[this.Component.cid]},unbuild:function(t){this.waitingFor&&(this.keepAlive||this.waitingFor.$destroy(),this.waitingFor=null);var e=this.childVM;return!e||this.keepAlive?void(e&&(e._inactive=!0,e._updateRef(!0))):void e.$destroy(!1,t)},remove:function(t,e){var i=this.keepAlive;if(t){this.pendingRemovals++,this.pendingRemovalCb=e;var n=this;t.$remove(function(){n.pendingRemovals--,i||t._cleanup(),!n.pendingRemovals&&n.pendingRemovalCb&&(n.pendingRemovalCb(),n.pendingRemovalCb=null)})}else e&&e()},transition:function(t,e){var i=this,n=this.childVM;switch(n&&(n._inactive=!0),t._inactive=!1,this.childVM=t,i.params.transitionMode){case"in-out":t.$before(i.anchor,function(){i.remove(n,e)});break;case"out-in":i.remove(n,function(){t.$before(i.anchor,e)});break;default:i.remove(n),t.$before(i.anchor,e)}},unbind:function(){if(this.invalidatePending(),this.unbuild(),this.cache){for(var t in this.cache)this.cache[t].$destroy();this.cache=null}}},$s=An._propBindingModes,ks={},xs=/^[$_a-zA-Z]+[\w$]*$/,As=An._propBindingModes,Os={bind:function(){var t=this.vm,e=t._context,i=this.descriptor.prop,n=i.path,r=i.parentPath,s=i.mode===As.TWO_WAY,o=this.parentWatcher=new Ut(e,r,function(e){xe(t,i,e)},{twoWay:s,filters:i.filters,scope:this._scope});if(ke(t,i,o.value),s){var a=this;t.$once("pre-hook:created",function(){a.childWatcher=new Ut(t,n,function(t){o.set(t)},{sync:!0})})}},unbind:function(){this.parentWatcher.teardown(),this.childWatcher&&this.childWatcher.teardown()}},Ts=[],Ns=!1,js="transition",Es="animation",Ss=Ji+"Duration",Fs=Qi+"Duration",Ds=Ri&&window.requestAnimationFrame,Ps=Ds?function(t){Ds(function(){Ds(t)})}:function(t){setTimeout(t,50)},Rs=Se.prototype;Rs.enter=function(t,e){this.cancelPending(),this.callHook("beforeEnter"),this.cb=e,X(this.el,this.enterClass),t(),this.entered=!1,this.callHookWithCb("enter"),this.entered||(this.cancel=this.hooks&&this.hooks.enterCancelled,je(this.enterNextTick))},Rs.enterNextTick=function(){var t=this;this.justEntered=!0,Ps(function(){t.justEntered=!1});var e=this.enterDone,i=this.getCssTransitionType(this.enterClass);this.pendingJsCb?i===js&&Y(this.el,this.enterClass):i===js?(Y(this.el,this.enterClass),this.setupCssCb(qi,e)):i===Es?this.setupCssCb(Gi,e):e()},Rs.enterDone=function(){this.entered=!0,this.cancel=this.pendingJsCb=null,Y(this.el,this.enterClass),this.callHook("afterEnter"),this.cb&&this.cb()},Rs.leave=function(t,e){this.cancelPending(),this.callHook("beforeLeave"),this.op=t,this.cb=e,X(this.el,this.leaveClass),this.left=!1,this.callHookWithCb("leave"),this.left||(this.cancel=this.hooks&&this.hooks.leaveCancelled,this.op&&!this.pendingJsCb&&(this.justEntered?this.leaveDone():je(this.leaveNextTick)))},Rs.leaveNextTick=function(){var t=this.getCssTransitionType(this.leaveClass);if(t){var e=t===js?qi:Gi;this.setupCssCb(e,this.leaveDone)}else this.leaveDone()},Rs.leaveDone=function(){this.left=!0,this.cancel=this.pendingJsCb=null,this.op(),Y(this.el,this.leaveClass),this.callHook("afterLeave"),this.cb&&this.cb(),this.op=null},Rs.cancelPending=function(){this.op=this.cb=null;var t=!1;this.pendingCssCb&&(t=!0,Q(this.el,this.pendingCssEvent,this.pendingCssCb),this.pendingCssEvent=this.pendingCssCb=null),this.pendingJsCb&&(t=!0,this.pendingJsCb.cancel(),this.pendingJsCb=null),t&&(Y(this.el,this.enterClass),Y(this.el,this.leaveClass)),this.cancel&&(this.cancel.call(this.vm,this.el),this.cancel=null)},Rs.callHook=function(t){this.hooks&&this.hooks[t]&&this.hooks[t].call(this.vm,this.el)},Rs.callHookWithCb=function(t){var e=this.hooks&&this.hooks[t];e&&(e.length>1&&(this.pendingJsCb=w(this[t+"Done"])),e.call(this.vm,this.el,this.pendingJsCb))},Rs.getCssTransitionType=function(t){if(!(!qi||document.hidden||this.hooks&&this.hooks.css===!1||Fe(this.el))){var e=this.type||this.typeCache[t];if(e)return e;var i=this.el.style,n=window.getComputedStyle(this.el),r=i[Ss]||n[Ss];if(r&&"0s"!==r)e=js;else{var s=i[Fs]||n[Fs];s&&"0s"!==s&&(e=Es)}return e&&(this.typeCache[t]=e),e}},Rs.setupCssCb=function(t,e){this.pendingCssEvent=t;var i=this,n=this.el,r=this.pendingCssCb=function(s){s.target===n&&(Q(n,t,r),i.pendingCssEvent=i.pendingCssCb=null,!i.pendingJsCb&&e&&e())};q(n,t,r)};var Ls={priority:Ir,update:function(t,e){var i=this.el,n=gt(this.vm.$options,"transitions",t);t=t||"v",e=e||"v",i.__v_trans=new Se(i,t,n,this.vm),Y(i,e+"-transition"),X(i,t+"-transition")}},Hs={style:ls,"class":ws,component:Cs,prop:Os,transition:Ls},Is=/^v-bind:|^:/,Ms=/^v-on:|^@/,Vs=/^v-([^:]+)(?:$|:(.*)$)/,Bs=/\.[^\.]+/g,Ws=/^(v-bind:|:)?transition$/,zs=1e3,Us=2e3;Ye.terminal=!0;var Js=/[^\w\-:\.]/,qs=Object.freeze({compile:De,compileAndLinkProps:Ie,compileRoot:Me,transclude:si,resolveSlots:li}),Qs=/^v-on:|^@/;di.prototype._bind=function(){var t=this.name,e=this.descriptor;if(("cloak"!==t||this.vm._isCompiled)&&this.el&&this.el.removeAttribute){var i=e.attr||"v-"+t;this.el.removeAttribute(i)}var n=e.def;if("function"==typeof n?this.update=n:v(this,n),this._setupParams(),this.bind&&this.bind(),this._bound=!0,this.literal)this.update&&this.update(e.raw);else if((this.expression||this.modifiers)&&(this.update||this.twoWay)&&!this._checkStatement()){var r=this;this.update?this._update=function(t,e){r._locked||r.update(t,e)}:this._update=pi;var s=this._preProcess?p(this._preProcess,this):null,o=this._postProcess?p(this._postProcess,this):null,a=this._watcher=new Ut(this.vm,this.expression,this._update,{filters:this.filters,twoWay:this.twoWay,deep:this.deep,preProcess:s,postProcess:o,scope:this._scope});this.afterBind?this.afterBind():this.update&&this.update(a.value)}},di.prototype._setupParams=function(){if(this.params){var t=this.params;this.params=Object.create(null);for(var e,i,n,r=t.length;r--;)e=u(t[r]),n=l(e),i=M(this.el,e),null!=i?this._setupParamWatcher(n,i):(i=I(this.el,e),null!=i&&(this.params[n]=""===i?!0:i))}},di.prototype._setupParamWatcher=function(t,e){var i=this,n=!1,r=(this._scope||this.vm).$watch(e,function(e,r){if(i.params[t]=e,n){var s=i.paramWatchers&&i.paramWatchers[t];s&&s.call(i,e,r)}else n=!0},{immediate:!0,user:!1});(this._paramUnwatchFns||(this._paramUnwatchFns=[])).push(r)},di.prototype._checkStatement=function(){var t=this.expression;if(t&&this.acceptStatement&&!Mt(t)){var e=It(t).get,i=this._scope||this.vm,n=function(t){i.$event=t,e.call(i,i),i.$event=null};return this.filters&&(n=i._applyFilters(n,null,this.filters)),this.update(n),!0}},di.prototype.set=function(t){this.twoWay&&this._withLock(function(){this._watcher.set(t)})},di.prototype._withLock=function(t){var e=this;e._locked=!0,t.call(e),Yi(function(){e._locked=!1})},di.prototype.on=function(t,e,i){q(this.el,t,e,i),(this._listeners||(this._listeners=[])).push([t,e])},di.prototype._teardown=function(){if(this._bound){this._bound=!1,this.unbind&&this.unbind(),this._watcher&&this._watcher.teardown();var t,e=this._listeners;if(e)for(t=e.length;t--;)Q(this.el,e[t][0],e[t][1]);var i=this._paramUnwatchFns;if(i)for(t=i.length;t--;)i[t]();this.vm=this.el=this._watcher=this._listeners=null}};var Gs=/[^|]\|[^|]/;xt(wi),ui(wi),fi(wi),vi(wi),mi(wi),gi(wi),_i(wi),yi(wi),bi(wi);var Zs={priority:Ur,params:["name"],bind:function(){var t=this.params.name||"default",e=this.vm._slotContents&&this.vm._slotContents[t];e&&e.hasChildNodes()?this.compile(e.cloneNode(!0),this.vm._context,this.vm):this.fallback()},compile:function(t,e,i){if(t&&e){if(this.el.hasChildNodes()&&1===t.childNodes.length&&1===t.childNodes[0].nodeType&&t.childNodes[0].hasAttribute("v-if")){var n=document.createElement("template");n.setAttribute("v-else",""),n.innerHTML=this.el.innerHTML,n._context=this.vm,t.appendChild(n)}var r=i?i._scope:this._scope;this.unlink=e.$compile(t,i,r,this._frag)}t?J(this.el,t):z(this.el)},fallback:function(){this.compile(K(this.el,!0),this.vm)},unbind:function(){this.unlink&&this.unlink()}},Xs={priority:Br,params:["name"],paramWatchers:{name:function(t){Qr.remove.call(this),t&&this.insert(t)}},bind:function(){this.anchor=nt("v-partial"),J(this.el,this.anchor),this.insert(this.params.name)},insert:function(t){var e=gt(this.vm.$options,"partials",t,!0);e&&(this.factory=new se(this.vm,e),Qr.insert.call(this))},unbind:function(){this.frag&&this.frag.destroy()}},Ys={slot:Zs,partial:Xs},Ks=qr._postProcess,to=/(\d{3})(?=\d)/g,eo={orderBy:ki,filterBy:$i,limitBy:Ci,json:{read:function(t,e){return"string"==typeof t?t:JSON.stringify(t,null,arguments.length>1?e:2)},write:function(t){try{return JSON.parse(t)}catch(e){return t}}},capitalize:function(t){return t||0===t?(t=t.toString(),t.charAt(0).toUpperCase()+t.slice(1)):""},uppercase:function(t){return t||0===t?t.toString().toUpperCase():""},lowercase:function(t){return t||0===t?t.toString().toLowerCase():""},currency:function(t,e,i){if(t=parseFloat(t),!isFinite(t)||!t&&0!==t)return"";e=null!=e?e:"$",i=null!=i?i:2;var n=Math.abs(t).toFixed(i),r=i?n.slice(0,-1-i):n,s=r.length%3,o=s>0?r.slice(0,s)+(r.length>3?",":""):"",a=i?n.slice(-1-i):"",h=0>t?"-":"";return h+e+o+r.slice(s).replace(to,"$1,")+a},pluralize:function(t){var e=d(arguments,1),i=e.length;if(i>1){var n=t%10-1;return n in e?e[n]:e[i-1]}return e[0]+(1===t?"":"s")},debounce:function(t,e){return t?(e||(e=300),y(t,e)):void 0}};return Ai(wi),wi.version="1.0.26",setTimeout(function(){An.devtools&&Li&&Li.emit("init",wi)},0),wi});
+//# sourceMappingURL=vue.min.js.map \ No newline at end of file