aboutsummaryrefslogtreecommitdiff
path: root/node_modules/vue/src/platforms/web/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/vue/src/platforms/web/runtime')
-rw-r--r--node_modules/vue/src/platforms/web/runtime/class-util.js61
-rw-r--r--node_modules/vue/src/platforms/web/runtime/components/index.js7
-rw-r--r--node_modules/vue/src/platforms/web/runtime/components/transition-group.js180
-rw-r--r--node_modules/vue/src/platforms/web/runtime/components/transition.js194
-rw-r--r--node_modules/vue/src/platforms/web/runtime/directives/index.js7
-rw-r--r--node_modules/vue/src/platforms/web/runtime/directives/model.js147
-rw-r--r--node_modules/vue/src/platforms/web/runtime/directives/show.js60
-rw-r--r--node_modules/vue/src/platforms/web/runtime/index.js77
-rw-r--r--node_modules/vue/src/platforms/web/runtime/modules/attrs.js118
-rw-r--r--node_modules/vue/src/platforms/web/runtime/modules/class.js48
-rw-r--r--node_modules/vue/src/platforms/web/runtime/modules/dom-props.js95
-rw-r--r--node_modules/vue/src/platforms/web/runtime/modules/events.js87
-rw-r--r--node_modules/vue/src/platforms/web/runtime/modules/index.js15
-rw-r--r--node_modules/vue/src/platforms/web/runtime/modules/style.js93
-rw-r--r--node_modules/vue/src/platforms/web/runtime/modules/transition.js343
-rw-r--r--node_modules/vue/src/platforms/web/runtime/node-ops.js59
-rw-r--r--node_modules/vue/src/platforms/web/runtime/patch.js12
-rw-r--r--node_modules/vue/src/platforms/web/runtime/transition-util.js185
18 files changed, 1788 insertions, 0 deletions
diff --git a/node_modules/vue/src/platforms/web/runtime/class-util.js b/node_modules/vue/src/platforms/web/runtime/class-util.js
new file mode 100644
index 00000000..709526c2
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/class-util.js
@@ -0,0 +1,61 @@
+/* @flow */
+
+/**
+ * Add class with compatibility for SVG since classList is not supported on
+ * SVG elements in IE
+ */
+export function addClass (el: HTMLElement, cls: ?string) {
+ /* istanbul ignore if */
+ if (!cls || !(cls = cls.trim())) {
+ return
+ }
+
+ /* istanbul ignore else */
+ if (el.classList) {
+ if (cls.indexOf(' ') > -1) {
+ cls.split(/\s+/).forEach(c => el.classList.add(c))
+ } else {
+ el.classList.add(cls)
+ }
+ } else {
+ const cur = ` ${el.getAttribute('class') || ''} `
+ if (cur.indexOf(' ' + cls + ' ') < 0) {
+ el.setAttribute('class', (cur + cls).trim())
+ }
+ }
+}
+
+/**
+ * Remove class with compatibility for SVG since classList is not supported on
+ * SVG elements in IE
+ */
+export function removeClass (el: HTMLElement, cls: ?string) {
+ /* istanbul ignore if */
+ if (!cls || !(cls = cls.trim())) {
+ return
+ }
+
+ /* istanbul ignore else */
+ if (el.classList) {
+ if (cls.indexOf(' ') > -1) {
+ cls.split(/\s+/).forEach(c => el.classList.remove(c))
+ } else {
+ el.classList.remove(cls)
+ }
+ if (!el.classList.length) {
+ el.removeAttribute('class')
+ }
+ } else {
+ let cur = ` ${el.getAttribute('class') || ''} `
+ const tar = ' ' + cls + ' '
+ while (cur.indexOf(tar) >= 0) {
+ cur = cur.replace(tar, ' ')
+ }
+ cur = cur.trim()
+ if (cur) {
+ el.setAttribute('class', cur)
+ } else {
+ el.removeAttribute('class')
+ }
+ }
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/components/index.js b/node_modules/vue/src/platforms/web/runtime/components/index.js
new file mode 100644
index 00000000..6bfe5780
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/components/index.js
@@ -0,0 +1,7 @@
+import Transition from './transition'
+import TransitionGroup from './transition-group'
+
+export default {
+ Transition,
+ TransitionGroup
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/components/transition-group.js b/node_modules/vue/src/platforms/web/runtime/components/transition-group.js
new file mode 100644
index 00000000..219ff01c
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/components/transition-group.js
@@ -0,0 +1,180 @@
+/* @flow */
+
+// Provides transition support for list items.
+// supports move transitions using the FLIP technique.
+
+// Because the vdom's children update algorithm is "unstable" - i.e.
+// it doesn't guarantee the relative positioning of removed elements,
+// we force transition-group to update its children into two passes:
+// in the first pass, we remove all nodes that need to be removed,
+// triggering their leaving transition; in the second pass, we insert/move
+// into the final desired state. This way in the second pass removed
+// nodes will remain where they should be.
+
+import { warn, extend } from 'core/util/index'
+import { addClass, removeClass } from '../class-util'
+import { transitionProps, extractTransitionData } from './transition'
+
+import {
+ hasTransition,
+ getTransitionInfo,
+ transitionEndEvent,
+ addTransitionClass,
+ removeTransitionClass
+} from '../transition-util'
+
+const props = extend({
+ tag: String,
+ moveClass: String
+}, transitionProps)
+
+delete props.mode
+
+export default {
+ props,
+
+ render (h: Function) {
+ const tag: string = this.tag || this.$vnode.data.tag || 'span'
+ const map: Object = Object.create(null)
+ const prevChildren: Array<VNode> = this.prevChildren = this.children
+ const rawChildren: Array<VNode> = this.$slots.default || []
+ const children: Array<VNode> = this.children = []
+ const transitionData: Object = extractTransitionData(this)
+
+ for (let i = 0; i < rawChildren.length; i++) {
+ const c: VNode = rawChildren[i]
+ if (c.tag) {
+ if (c.key != null && String(c.key).indexOf('__vlist') !== 0) {
+ children.push(c)
+ map[c.key] = c
+ ;(c.data || (c.data = {})).transition = transitionData
+ } else if (process.env.NODE_ENV !== 'production') {
+ const opts: ?VNodeComponentOptions = c.componentOptions
+ const name: string = opts ? (opts.Ctor.options.name || opts.tag || '') : c.tag
+ warn(`<transition-group> children must be keyed: <${name}>`)
+ }
+ }
+ }
+
+ if (prevChildren) {
+ const kept: Array<VNode> = []
+ const removed: Array<VNode> = []
+ for (let i = 0; i < prevChildren.length; i++) {
+ const c: VNode = prevChildren[i]
+ c.data.transition = transitionData
+ c.data.pos = c.elm.getBoundingClientRect()
+ if (map[c.key]) {
+ kept.push(c)
+ } else {
+ removed.push(c)
+ }
+ }
+ this.kept = h(tag, null, kept)
+ this.removed = removed
+ }
+
+ return h(tag, null, children)
+ },
+
+ beforeUpdate () {
+ // force removing pass
+ this.__patch__(
+ this._vnode,
+ this.kept,
+ false, // hydrating
+ true // removeOnly (!important, avoids unnecessary moves)
+ )
+ this._vnode = this.kept
+ },
+
+ updated () {
+ const children: Array<VNode> = this.prevChildren
+ const moveClass: string = this.moveClass || ((this.name || 'v') + '-move')
+ if (!children.length || !this.hasMove(children[0].elm, moveClass)) {
+ return
+ }
+
+ // we divide the work into three loops to avoid mixing DOM reads and writes
+ // in each iteration - which helps prevent layout thrashing.
+ children.forEach(callPendingCbs)
+ children.forEach(recordPosition)
+ children.forEach(applyTranslation)
+
+ // force reflow to put everything in position
+ // assign to this to avoid being removed in tree-shaking
+ // $flow-disable-line
+ this._reflow = document.body.offsetHeight
+
+ children.forEach((c: VNode) => {
+ if (c.data.moved) {
+ var el: any = c.elm
+ var s: any = el.style
+ addTransitionClass(el, moveClass)
+ s.transform = s.WebkitTransform = s.transitionDuration = ''
+ el.addEventListener(transitionEndEvent, el._moveCb = function cb (e) {
+ if (!e || /transform$/.test(e.propertyName)) {
+ el.removeEventListener(transitionEndEvent, cb)
+ el._moveCb = null
+ removeTransitionClass(el, moveClass)
+ }
+ })
+ }
+ })
+ },
+
+ methods: {
+ hasMove (el: any, moveClass: string): boolean {
+ /* istanbul ignore if */
+ if (!hasTransition) {
+ return false
+ }
+ /* istanbul ignore if */
+ if (this._hasMove) {
+ return this._hasMove
+ }
+ // Detect whether an element with the move class applied has
+ // CSS transitions. Since the element may be inside an entering
+ // transition at this very moment, we make a clone of it and remove
+ // all other transition classes applied to ensure only the move class
+ // is applied.
+ const clone: HTMLElement = el.cloneNode()
+ if (el._transitionClasses) {
+ el._transitionClasses.forEach((cls: string) => { removeClass(clone, cls) })
+ }
+ addClass(clone, moveClass)
+ clone.style.display = 'none'
+ this.$el.appendChild(clone)
+ const info: Object = getTransitionInfo(clone)
+ this.$el.removeChild(clone)
+ return (this._hasMove = info.hasTransform)
+ }
+ }
+}
+
+function callPendingCbs (c: VNode) {
+ /* istanbul ignore if */
+ if (c.elm._moveCb) {
+ c.elm._moveCb()
+ }
+ /* istanbul ignore if */
+ if (c.elm._enterCb) {
+ c.elm._enterCb()
+ }
+}
+
+function recordPosition (c: VNode) {
+ c.data.newPos = c.elm.getBoundingClientRect()
+}
+
+function applyTranslation (c: VNode) {
+ const oldPos = c.data.pos
+ const newPos = c.data.newPos
+ const dx = oldPos.left - newPos.left
+ const dy = oldPos.top - newPos.top
+ if (dx || dy) {
+ c.data.moved = true
+ const s = c.elm.style
+ s.transform = s.WebkitTransform = `translate(${dx}px,${dy}px)`
+ s.transitionDuration = '0s'
+ }
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/components/transition.js b/node_modules/vue/src/platforms/web/runtime/components/transition.js
new file mode 100644
index 00000000..6111d8cb
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/components/transition.js
@@ -0,0 +1,194 @@
+/* @flow */
+
+// Provides transition support for a single element/component.
+// supports transition mode (out-in / in-out)
+
+import { warn } from 'core/util/index'
+import { camelize, extend, isPrimitive } from 'shared/util'
+import {
+ mergeVNodeHook,
+ isAsyncPlaceholder,
+ getFirstComponentChild
+} from 'core/vdom/helpers/index'
+
+export const transitionProps = {
+ name: String,
+ appear: Boolean,
+ css: Boolean,
+ mode: String,
+ type: String,
+ enterClass: String,
+ leaveClass: String,
+ enterToClass: String,
+ leaveToClass: String,
+ enterActiveClass: String,
+ leaveActiveClass: String,
+ appearClass: String,
+ appearActiveClass: String,
+ appearToClass: String,
+ duration: [Number, String, Object]
+}
+
+// in case the child is also an abstract component, e.g. <keep-alive>
+// we want to recursively retrieve the real component to be rendered
+function getRealChild (vnode: ?VNode): ?VNode {
+ const compOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions
+ if (compOptions && compOptions.Ctor.options.abstract) {
+ return getRealChild(getFirstComponentChild(compOptions.children))
+ } else {
+ return vnode
+ }
+}
+
+export function extractTransitionData (comp: Component): Object {
+ const data = {}
+ const options: ComponentOptions = comp.$options
+ // props
+ for (const key in options.propsData) {
+ data[key] = comp[key]
+ }
+ // events.
+ // extract listeners and pass them directly to the transition methods
+ const listeners: ?Object = options._parentListeners
+ for (const key in listeners) {
+ data[camelize(key)] = listeners[key]
+ }
+ return data
+}
+
+function placeholder (h: Function, rawChild: VNode): ?VNode {
+ if (/\d-keep-alive$/.test(rawChild.tag)) {
+ return h('keep-alive', {
+ props: rawChild.componentOptions.propsData
+ })
+ }
+}
+
+function hasParentTransition (vnode: VNode): ?boolean {
+ while ((vnode = vnode.parent)) {
+ if (vnode.data.transition) {
+ return true
+ }
+ }
+}
+
+function isSameChild (child: VNode, oldChild: VNode): boolean {
+ return oldChild.key === child.key && oldChild.tag === child.tag
+}
+
+export default {
+ name: 'transition',
+ props: transitionProps,
+ abstract: true,
+
+ render (h: Function) {
+ let children: any = this.$slots.default
+ if (!children) {
+ return
+ }
+
+ // filter out text nodes (possible whitespaces)
+ children = children.filter((c: VNode) => c.tag || isAsyncPlaceholder(c))
+ /* istanbul ignore if */
+ if (!children.length) {
+ return
+ }
+
+ // warn multiple elements
+ if (process.env.NODE_ENV !== 'production' && children.length > 1) {
+ warn(
+ '<transition> can only be used on a single element. Use ' +
+ '<transition-group> for lists.',
+ this.$parent
+ )
+ }
+
+ const mode: string = this.mode
+
+ // warn invalid mode
+ if (process.env.NODE_ENV !== 'production' &&
+ mode && mode !== 'in-out' && mode !== 'out-in'
+ ) {
+ warn(
+ 'invalid <transition> mode: ' + mode,
+ this.$parent
+ )
+ }
+
+ const rawChild: VNode = children[0]
+
+ // if this is a component root node and the component's
+ // parent container node also has transition, skip.
+ if (hasParentTransition(this.$vnode)) {
+ return rawChild
+ }
+
+ // apply transition data to child
+ // use getRealChild() to ignore abstract components e.g. keep-alive
+ const child: ?VNode = getRealChild(rawChild)
+ /* istanbul ignore if */
+ if (!child) {
+ return rawChild
+ }
+
+ if (this._leaving) {
+ return placeholder(h, rawChild)
+ }
+
+ // ensure a key that is unique to the vnode type and to this transition
+ // component instance. This key will be used to remove pending leaving nodes
+ // during entering.
+ const id: string = `__transition-${this._uid}-`
+ child.key = child.key == null
+ ? child.isComment
+ ? id + 'comment'
+ : id + child.tag
+ : isPrimitive(child.key)
+ ? (String(child.key).indexOf(id) === 0 ? child.key : id + child.key)
+ : child.key
+
+ const data: Object = (child.data || (child.data = {})).transition = extractTransitionData(this)
+ const oldRawChild: VNode = this._vnode
+ const oldChild: VNode = getRealChild(oldRawChild)
+
+ // mark v-show
+ // so that the transition module can hand over the control to the directive
+ if (child.data.directives && child.data.directives.some(d => d.name === 'show')) {
+ child.data.show = true
+ }
+
+ if (
+ oldChild &&
+ oldChild.data &&
+ !isSameChild(child, oldChild) &&
+ !isAsyncPlaceholder(oldChild) &&
+ // #6687 component root is a comment node
+ !(oldChild.componentInstance && oldChild.componentInstance._vnode.isComment)
+ ) {
+ // replace old child transition data with fresh one
+ // important for dynamic transitions!
+ const oldData: Object = oldChild.data.transition = extend({}, data)
+ // handle transition mode
+ if (mode === 'out-in') {
+ // return placeholder node and queue update when leave finishes
+ this._leaving = true
+ mergeVNodeHook(oldData, 'afterLeave', () => {
+ this._leaving = false
+ this.$forceUpdate()
+ })
+ return placeholder(h, rawChild)
+ } else if (mode === 'in-out') {
+ if (isAsyncPlaceholder(child)) {
+ return oldRawChild
+ }
+ let delayedLeave
+ const performLeave = () => { delayedLeave() }
+ mergeVNodeHook(data, 'afterEnter', performLeave)
+ mergeVNodeHook(data, 'enterCancelled', performLeave)
+ mergeVNodeHook(oldData, 'delayLeave', leave => { delayedLeave = leave })
+ }
+ }
+
+ return rawChild
+ }
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/directives/index.js b/node_modules/vue/src/platforms/web/runtime/directives/index.js
new file mode 100644
index 00000000..b673f11a
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/directives/index.js
@@ -0,0 +1,7 @@
+import model from './model'
+import show from './show'
+
+export default {
+ model,
+ show
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/directives/model.js b/node_modules/vue/src/platforms/web/runtime/directives/model.js
new file mode 100644
index 00000000..cba8ded0
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/directives/model.js
@@ -0,0 +1,147 @@
+/**
+ * Not type checking this file because flow doesn't like attaching
+ * properties to Elements.
+ */
+
+import { isTextInputType } from 'web/util/element'
+import { looseEqual, looseIndexOf } from 'shared/util'
+import { mergeVNodeHook } from 'core/vdom/helpers/index'
+import { warn, isIE9, isIE, isEdge } from 'core/util/index'
+
+/* istanbul ignore if */
+if (isIE9) {
+ // http://www.matts411.com/post/internet-explorer-9-oninput/
+ document.addEventListener('selectionchange', () => {
+ const el = document.activeElement
+ if (el && el.vmodel) {
+ trigger(el, 'input')
+ }
+ })
+}
+
+const directive = {
+ inserted (el, binding, vnode, oldVnode) {
+ if (vnode.tag === 'select') {
+ // #6903
+ if (oldVnode.elm && !oldVnode.elm._vOptions) {
+ mergeVNodeHook(vnode, 'postpatch', () => {
+ directive.componentUpdated(el, binding, vnode)
+ })
+ } else {
+ setSelected(el, binding, vnode.context)
+ }
+ el._vOptions = [].map.call(el.options, getValue)
+ } else if (vnode.tag === 'textarea' || isTextInputType(el.type)) {
+ el._vModifiers = binding.modifiers
+ if (!binding.modifiers.lazy) {
+ el.addEventListener('compositionstart', onCompositionStart)
+ el.addEventListener('compositionend', onCompositionEnd)
+ // Safari < 10.2 & UIWebView doesn't fire compositionend when
+ // switching focus before confirming composition choice
+ // this also fixes the issue where some browsers e.g. iOS Chrome
+ // fires "change" instead of "input" on autocomplete.
+ el.addEventListener('change', onCompositionEnd)
+ /* istanbul ignore if */
+ if (isIE9) {
+ el.vmodel = true
+ }
+ }
+ }
+ },
+
+ componentUpdated (el, binding, vnode) {
+ if (vnode.tag === 'select') {
+ setSelected(el, binding, vnode.context)
+ // in case the options rendered by v-for have changed,
+ // it's possible that the value is out-of-sync with the rendered options.
+ // detect such cases and filter out values that no longer has a matching
+ // option in the DOM.
+ const prevOptions = el._vOptions
+ const curOptions = el._vOptions = [].map.call(el.options, getValue)
+ if (curOptions.some((o, i) => !looseEqual(o, prevOptions[i]))) {
+ // trigger change event if
+ // no matching option found for at least one value
+ const needReset = el.multiple
+ ? binding.value.some(v => hasNoMatchingOption(v, curOptions))
+ : binding.value !== binding.oldValue && hasNoMatchingOption(binding.value, curOptions)
+ if (needReset) {
+ trigger(el, 'change')
+ }
+ }
+ }
+ }
+}
+
+function setSelected (el, binding, vm) {
+ actuallySetSelected(el, binding, vm)
+ /* istanbul ignore if */
+ if (isIE || isEdge) {
+ setTimeout(() => {
+ actuallySetSelected(el, binding, vm)
+ }, 0)
+ }
+}
+
+function actuallySetSelected (el, binding, vm) {
+ const value = binding.value
+ const isMultiple = el.multiple
+ if (isMultiple && !Array.isArray(value)) {
+ process.env.NODE_ENV !== 'production' && warn(
+ `<select multiple v-model="${binding.expression}"> ` +
+ `expects an Array value for its binding, but got ${
+ Object.prototype.toString.call(value).slice(8, -1)
+ }`,
+ vm
+ )
+ return
+ }
+ let selected, option
+ for (let i = 0, l = el.options.length; i < l; i++) {
+ option = el.options[i]
+ if (isMultiple) {
+ selected = looseIndexOf(value, getValue(option)) > -1
+ if (option.selected !== selected) {
+ option.selected = selected
+ }
+ } else {
+ if (looseEqual(getValue(option), value)) {
+ if (el.selectedIndex !== i) {
+ el.selectedIndex = i
+ }
+ return
+ }
+ }
+ }
+ if (!isMultiple) {
+ el.selectedIndex = -1
+ }
+}
+
+function hasNoMatchingOption (value, options) {
+ return options.every(o => !looseEqual(o, value))
+}
+
+function getValue (option) {
+ return '_value' in option
+ ? option._value
+ : option.value
+}
+
+function onCompositionStart (e) {
+ e.target.composing = true
+}
+
+function onCompositionEnd (e) {
+ // prevent triggering an input event for no reason
+ if (!e.target.composing) return
+ e.target.composing = false
+ trigger(e.target, 'input')
+}
+
+function trigger (el, type) {
+ const e = document.createEvent('HTMLEvents')
+ e.initEvent(type, true, true)
+ el.dispatchEvent(e)
+}
+
+export default directive
diff --git a/node_modules/vue/src/platforms/web/runtime/directives/show.js b/node_modules/vue/src/platforms/web/runtime/directives/show.js
new file mode 100644
index 00000000..17fb5dec
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/directives/show.js
@@ -0,0 +1,60 @@
+/* @flow */
+
+import { enter, leave } from '../modules/transition'
+
+// recursively search for possible transition defined inside the component root
+function locateNode (vnode: VNode): VNodeWithData {
+ return vnode.componentInstance && (!vnode.data || !vnode.data.transition)
+ ? locateNode(vnode.componentInstance._vnode)
+ : vnode
+}
+
+export default {
+ bind (el: any, { value }: VNodeDirective, vnode: VNodeWithData) {
+ vnode = locateNode(vnode)
+ const transition = vnode.data && vnode.data.transition
+ const originalDisplay = el.__vOriginalDisplay =
+ el.style.display === 'none' ? '' : el.style.display
+ if (value && transition) {
+ vnode.data.show = true
+ enter(vnode, () => {
+ el.style.display = originalDisplay
+ })
+ } else {
+ el.style.display = value ? originalDisplay : 'none'
+ }
+ },
+
+ update (el: any, { value, oldValue }: VNodeDirective, vnode: VNodeWithData) {
+ /* istanbul ignore if */
+ if (!value === !oldValue) return
+ vnode = locateNode(vnode)
+ const transition = vnode.data && vnode.data.transition
+ if (transition) {
+ vnode.data.show = true
+ if (value) {
+ enter(vnode, () => {
+ el.style.display = el.__vOriginalDisplay
+ })
+ } else {
+ leave(vnode, () => {
+ el.style.display = 'none'
+ })
+ }
+ } else {
+ el.style.display = value ? el.__vOriginalDisplay : 'none'
+ }
+ },
+
+ unbind (
+ el: any,
+ binding: VNodeDirective,
+ vnode: VNodeWithData,
+ oldVnode: VNodeWithData,
+ isDestroy: boolean
+ ) {
+ if (!isDestroy) {
+ el.style.display = el.__vOriginalDisplay
+ }
+ }
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/index.js b/node_modules/vue/src/platforms/web/runtime/index.js
new file mode 100644
index 00000000..1283f521
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/index.js
@@ -0,0 +1,77 @@
+/* @flow */
+
+import Vue from 'core/index'
+import config from 'core/config'
+import { extend, noop } from 'shared/util'
+import { mountComponent } from 'core/instance/lifecycle'
+import { devtools, inBrowser, isChrome } from 'core/util/index'
+
+import {
+ query,
+ mustUseProp,
+ isReservedTag,
+ isReservedAttr,
+ getTagNamespace,
+ isUnknownElement
+} from 'web/util/index'
+
+import { patch } from './patch'
+import platformDirectives from './directives/index'
+import platformComponents from './components/index'
+
+// install platform specific utils
+Vue.config.mustUseProp = mustUseProp
+Vue.config.isReservedTag = isReservedTag
+Vue.config.isReservedAttr = isReservedAttr
+Vue.config.getTagNamespace = getTagNamespace
+Vue.config.isUnknownElement = isUnknownElement
+
+// install platform runtime directives & components
+extend(Vue.options.directives, platformDirectives)
+extend(Vue.options.components, platformComponents)
+
+// install platform patch function
+Vue.prototype.__patch__ = inBrowser ? patch : noop
+
+// public mount method
+Vue.prototype.$mount = function (
+ el?: string | Element,
+ hydrating?: boolean
+): Component {
+ el = el && inBrowser ? query(el) : undefined
+ return mountComponent(this, el, hydrating)
+}
+
+// devtools global hook
+/* istanbul ignore next */
+if (inBrowser) {
+ setTimeout(() => {
+ if (config.devtools) {
+ if (devtools) {
+ devtools.emit('init', Vue)
+ } else if (
+ process.env.NODE_ENV !== 'production' &&
+ process.env.NODE_ENV !== 'test' &&
+ isChrome
+ ) {
+ console[console.info ? 'info' : 'log'](
+ 'Download the Vue Devtools extension for a better development experience:\n' +
+ 'https://github.com/vuejs/vue-devtools'
+ )
+ }
+ }
+ if (process.env.NODE_ENV !== 'production' &&
+ process.env.NODE_ENV !== 'test' &&
+ config.productionTip !== false &&
+ typeof console !== 'undefined'
+ ) {
+ console[console.info ? 'info' : 'log'](
+ `You are running Vue in development mode.\n` +
+ `Make sure to turn on production mode when deploying for production.\n` +
+ `See more tips at https://vuejs.org/guide/deployment.html`
+ )
+ }
+ }, 0)
+}
+
+export default Vue
diff --git a/node_modules/vue/src/platforms/web/runtime/modules/attrs.js b/node_modules/vue/src/platforms/web/runtime/modules/attrs.js
new file mode 100644
index 00000000..78ef28a1
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/modules/attrs.js
@@ -0,0 +1,118 @@
+/* @flow */
+
+import { isIE, isIE9, isEdge } from 'core/util/env'
+
+import {
+ extend,
+ isDef,
+ isUndef
+} from 'shared/util'
+
+import {
+ isXlink,
+ xlinkNS,
+ getXlinkProp,
+ isBooleanAttr,
+ isEnumeratedAttr,
+ isFalsyAttrValue
+} from 'web/util/index'
+
+function updateAttrs (oldVnode: VNodeWithData, vnode: VNodeWithData) {
+ const opts = vnode.componentOptions
+ if (isDef(opts) && opts.Ctor.options.inheritAttrs === false) {
+ return
+ }
+ if (isUndef(oldVnode.data.attrs) && isUndef(vnode.data.attrs)) {
+ return
+ }
+ let key, cur, old
+ const elm = vnode.elm
+ const oldAttrs = oldVnode.data.attrs || {}
+ let attrs: any = vnode.data.attrs || {}
+ // clone observed objects, as the user probably wants to mutate it
+ if (isDef(attrs.__ob__)) {
+ attrs = vnode.data.attrs = extend({}, attrs)
+ }
+
+ for (key in attrs) {
+ cur = attrs[key]
+ old = oldAttrs[key]
+ if (old !== cur) {
+ setAttr(elm, key, cur)
+ }
+ }
+ // #4391: in IE9, setting type can reset value for input[type=radio]
+ // #6666: IE/Edge forces progress value down to 1 before setting a max
+ /* istanbul ignore if */
+ if ((isIE || isEdge) && attrs.value !== oldAttrs.value) {
+ setAttr(elm, 'value', attrs.value)
+ }
+ for (key in oldAttrs) {
+ if (isUndef(attrs[key])) {
+ if (isXlink(key)) {
+ elm.removeAttributeNS(xlinkNS, getXlinkProp(key))
+ } else if (!isEnumeratedAttr(key)) {
+ elm.removeAttribute(key)
+ }
+ }
+ }
+}
+
+function setAttr (el: Element, key: string, value: any) {
+ if (el.tagName.indexOf('-') > -1) {
+ baseSetAttr(el, key, value)
+ } else if (isBooleanAttr(key)) {
+ // set attribute for blank value
+ // e.g. <option disabled>Select one</option>
+ if (isFalsyAttrValue(value)) {
+ el.removeAttribute(key)
+ } else {
+ // technically allowfullscreen is a boolean attribute for <iframe>,
+ // but Flash expects a value of "true" when used on <embed> tag
+ value = key === 'allowfullscreen' && el.tagName === 'EMBED'
+ ? 'true'
+ : key
+ el.setAttribute(key, value)
+ }
+ } else if (isEnumeratedAttr(key)) {
+ el.setAttribute(key, isFalsyAttrValue(value) || value === 'false' ? 'false' : 'true')
+ } else if (isXlink(key)) {
+ if (isFalsyAttrValue(value)) {
+ el.removeAttributeNS(xlinkNS, getXlinkProp(key))
+ } else {
+ el.setAttributeNS(xlinkNS, key, value)
+ }
+ } else {
+ baseSetAttr(el, key, value)
+ }
+}
+
+function baseSetAttr (el, key, value) {
+ if (isFalsyAttrValue(value)) {
+ el.removeAttribute(key)
+ } else {
+ // #7138: IE10 & 11 fires input event when setting placeholder on
+ // <textarea>... block the first input event and remove the blocker
+ // immediately.
+ /* istanbul ignore if */
+ if (
+ isIE && !isIE9 &&
+ el.tagName === 'TEXTAREA' &&
+ key === 'placeholder' && !el.__ieph
+ ) {
+ const blocker = e => {
+ e.stopImmediatePropagation()
+ el.removeEventListener('input', blocker)
+ }
+ el.addEventListener('input', blocker)
+ // $flow-disable-line
+ el.__ieph = true /* IE placeholder patched */
+ }
+ el.setAttribute(key, value)
+ }
+}
+
+export default {
+ create: updateAttrs,
+ update: updateAttrs
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/modules/class.js b/node_modules/vue/src/platforms/web/runtime/modules/class.js
new file mode 100644
index 00000000..29fd2c11
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/modules/class.js
@@ -0,0 +1,48 @@
+/* @flow */
+
+import {
+ isDef,
+ isUndef
+} from 'shared/util'
+
+import {
+ concat,
+ stringifyClass,
+ genClassForVnode
+} from 'web/util/index'
+
+function updateClass (oldVnode: any, vnode: any) {
+ const el = vnode.elm
+ const data: VNodeData = vnode.data
+ const oldData: VNodeData = oldVnode.data
+ if (
+ isUndef(data.staticClass) &&
+ isUndef(data.class) && (
+ isUndef(oldData) || (
+ isUndef(oldData.staticClass) &&
+ isUndef(oldData.class)
+ )
+ )
+ ) {
+ return
+ }
+
+ let cls = genClassForVnode(vnode)
+
+ // handle transition classes
+ const transitionClass = el._transitionClasses
+ if (isDef(transitionClass)) {
+ cls = concat(cls, stringifyClass(transitionClass))
+ }
+
+ // set the class
+ if (cls !== el._prevClass) {
+ el.setAttribute('class', cls)
+ el._prevClass = cls
+ }
+}
+
+export default {
+ create: updateClass,
+ update: updateClass
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/modules/dom-props.js b/node_modules/vue/src/platforms/web/runtime/modules/dom-props.js
new file mode 100644
index 00000000..f3888aed
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/modules/dom-props.js
@@ -0,0 +1,95 @@
+/* @flow */
+
+import { isDef, isUndef, extend, toNumber } from 'shared/util'
+
+function updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) {
+ if (isUndef(oldVnode.data.domProps) && isUndef(vnode.data.domProps)) {
+ return
+ }
+ let key, cur
+ const elm: any = vnode.elm
+ const oldProps = oldVnode.data.domProps || {}
+ let props = vnode.data.domProps || {}
+ // clone observed objects, as the user probably wants to mutate it
+ if (isDef(props.__ob__)) {
+ props = vnode.data.domProps = extend({}, props)
+ }
+
+ for (key in oldProps) {
+ if (isUndef(props[key])) {
+ elm[key] = ''
+ }
+ }
+ for (key in props) {
+ cur = props[key]
+ // ignore children if the node has textContent or innerHTML,
+ // as these will throw away existing DOM nodes and cause removal errors
+ // on subsequent patches (#3360)
+ if (key === 'textContent' || key === 'innerHTML') {
+ if (vnode.children) vnode.children.length = 0
+ if (cur === oldProps[key]) continue
+ // #6601 work around Chrome version <= 55 bug where single textNode
+ // replaced by innerHTML/textContent retains its parentNode property
+ if (elm.childNodes.length === 1) {
+ elm.removeChild(elm.childNodes[0])
+ }
+ }
+
+ if (key === 'value') {
+ // store value as _value as well since
+ // non-string values will be stringified
+ elm._value = cur
+ // avoid resetting cursor position when value is the same
+ const strCur = isUndef(cur) ? '' : String(cur)
+ if (shouldUpdateValue(elm, strCur)) {
+ elm.value = strCur
+ }
+ } else {
+ elm[key] = cur
+ }
+ }
+}
+
+// check platforms/web/util/attrs.js acceptValue
+type acceptValueElm = HTMLInputElement | HTMLSelectElement | HTMLOptionElement;
+
+function shouldUpdateValue (elm: acceptValueElm, checkVal: string): boolean {
+ return (!elm.composing && (
+ elm.tagName === 'OPTION' ||
+ isNotInFocusAndDirty(elm, checkVal) ||
+ isDirtyWithModifiers(elm, checkVal)
+ ))
+}
+
+function isNotInFocusAndDirty (elm: acceptValueElm, checkVal: string): boolean {
+ // return true when textbox (.number and .trim) loses focus and its value is
+ // not equal to the updated value
+ let notInFocus = true
+ // #6157
+ // work around IE bug when accessing document.activeElement in an iframe
+ try { notInFocus = document.activeElement !== elm } catch (e) {}
+ return notInFocus && elm.value !== checkVal
+}
+
+function isDirtyWithModifiers (elm: any, newVal: string): boolean {
+ const value = elm.value
+ const modifiers = elm._vModifiers // injected by v-model runtime
+ if (isDef(modifiers)) {
+ if (modifiers.lazy) {
+ // inputs with lazy should only be updated when not in focus
+ return false
+ }
+ if (modifiers.number) {
+ return toNumber(value) !== toNumber(newVal)
+ }
+ if (modifiers.trim) {
+ return value.trim() !== newVal.trim()
+ }
+ }
+ return value !== newVal
+}
+
+export default {
+ create: updateDOMProps,
+ update: updateDOMProps
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/modules/events.js b/node_modules/vue/src/platforms/web/runtime/modules/events.js
new file mode 100644
index 00000000..1e71b667
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/modules/events.js
@@ -0,0 +1,87 @@
+/* @flow */
+
+import { isDef, isUndef } from 'shared/util'
+import { updateListeners } from 'core/vdom/helpers/index'
+import { withMacroTask, isIE, supportsPassive } from 'core/util/index'
+import { RANGE_TOKEN, CHECKBOX_RADIO_TOKEN } from 'web/compiler/directives/model'
+
+// normalize v-model event tokens that can only be determined at runtime.
+// it's important to place the event as the first in the array because
+// the whole point is ensuring the v-model callback gets called before
+// user-attached handlers.
+function normalizeEvents (on) {
+ /* istanbul ignore if */
+ if (isDef(on[RANGE_TOKEN])) {
+ // IE input[type=range] only supports `change` event
+ const event = isIE ? 'change' : 'input'
+ on[event] = [].concat(on[RANGE_TOKEN], on[event] || [])
+ delete on[RANGE_TOKEN]
+ }
+ // This was originally intended to fix #4521 but no longer necessary
+ // after 2.5. Keeping it for backwards compat with generated code from < 2.4
+ /* istanbul ignore if */
+ if (isDef(on[CHECKBOX_RADIO_TOKEN])) {
+ on.change = [].concat(on[CHECKBOX_RADIO_TOKEN], on.change || [])
+ delete on[CHECKBOX_RADIO_TOKEN]
+ }
+}
+
+let target: any
+
+function createOnceHandler (handler, event, capture) {
+ const _target = target // save current target element in closure
+ return function onceHandler () {
+ const res = handler.apply(null, arguments)
+ if (res !== null) {
+ remove(event, onceHandler, capture, _target)
+ }
+ }
+}
+
+function add (
+ event: string,
+ handler: Function,
+ once: boolean,
+ capture: boolean,
+ passive: boolean
+) {
+ handler = withMacroTask(handler)
+ if (once) handler = createOnceHandler(handler, event, capture)
+ target.addEventListener(
+ event,
+ handler,
+ supportsPassive
+ ? { capture, passive }
+ : capture
+ )
+}
+
+function remove (
+ event: string,
+ handler: Function,
+ capture: boolean,
+ _target?: HTMLElement
+) {
+ (_target || target).removeEventListener(
+ event,
+ handler._withTask || handler,
+ capture
+ )
+}
+
+function updateDOMListeners (oldVnode: VNodeWithData, vnode: VNodeWithData) {
+ if (isUndef(oldVnode.data.on) && isUndef(vnode.data.on)) {
+ return
+ }
+ const on = vnode.data.on || {}
+ const oldOn = oldVnode.data.on || {}
+ target = vnode.elm
+ normalizeEvents(on)
+ updateListeners(on, oldOn, add, remove, vnode.context)
+ target = undefined
+}
+
+export default {
+ create: updateDOMListeners,
+ update: updateDOMListeners
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/modules/index.js b/node_modules/vue/src/platforms/web/runtime/modules/index.js
new file mode 100644
index 00000000..9f6ad8f9
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/modules/index.js
@@ -0,0 +1,15 @@
+import attrs from './attrs'
+import klass from './class'
+import events from './events'
+import domProps from './dom-props'
+import style from './style'
+import transition from './transition'
+
+export default [
+ attrs,
+ klass,
+ events,
+ domProps,
+ style,
+ transition
+]
diff --git a/node_modules/vue/src/platforms/web/runtime/modules/style.js b/node_modules/vue/src/platforms/web/runtime/modules/style.js
new file mode 100644
index 00000000..29e1c3c1
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/modules/style.js
@@ -0,0 +1,93 @@
+/* @flow */
+
+import { getStyle, normalizeStyleBinding } from 'web/util/style'
+import { cached, camelize, extend, isDef, isUndef } from 'shared/util'
+
+const cssVarRE = /^--/
+const importantRE = /\s*!important$/
+const setProp = (el, name, val) => {
+ /* istanbul ignore if */
+ if (cssVarRE.test(name)) {
+ el.style.setProperty(name, val)
+ } else if (importantRE.test(val)) {
+ el.style.setProperty(name, val.replace(importantRE, ''), 'important')
+ } else {
+ const normalizedName = normalize(name)
+ if (Array.isArray(val)) {
+ // Support values array created by autoprefixer, e.g.
+ // {display: ["-webkit-box", "-ms-flexbox", "flex"]}
+ // Set them one by one, and the browser will only set those it can recognize
+ for (let i = 0, len = val.length; i < len; i++) {
+ el.style[normalizedName] = val[i]
+ }
+ } else {
+ el.style[normalizedName] = val
+ }
+ }
+}
+
+const vendorNames = ['Webkit', 'Moz', 'ms']
+
+let emptyStyle
+const normalize = cached(function (prop) {
+ emptyStyle = emptyStyle || document.createElement('div').style
+ prop = camelize(prop)
+ if (prop !== 'filter' && (prop in emptyStyle)) {
+ return prop
+ }
+ const capName = prop.charAt(0).toUpperCase() + prop.slice(1)
+ for (let i = 0; i < vendorNames.length; i++) {
+ const name = vendorNames[i] + capName
+ if (name in emptyStyle) {
+ return name
+ }
+ }
+})
+
+function updateStyle (oldVnode: VNodeWithData, vnode: VNodeWithData) {
+ const data = vnode.data
+ const oldData = oldVnode.data
+
+ if (isUndef(data.staticStyle) && isUndef(data.style) &&
+ isUndef(oldData.staticStyle) && isUndef(oldData.style)
+ ) {
+ return
+ }
+
+ let cur, name
+ const el: any = vnode.elm
+ const oldStaticStyle: any = oldData.staticStyle
+ const oldStyleBinding: any = oldData.normalizedStyle || oldData.style || {}
+
+ // if static style exists, stylebinding already merged into it when doing normalizeStyleData
+ const oldStyle = oldStaticStyle || oldStyleBinding
+
+ const style = normalizeStyleBinding(vnode.data.style) || {}
+
+ // store normalized style under a different key for next diff
+ // make sure to clone it if it's reactive, since the user likely wants
+ // to mutate it.
+ vnode.data.normalizedStyle = isDef(style.__ob__)
+ ? extend({}, style)
+ : style
+
+ const newStyle = getStyle(vnode, true)
+
+ for (name in oldStyle) {
+ if (isUndef(newStyle[name])) {
+ setProp(el, name, '')
+ }
+ }
+ for (name in newStyle) {
+ cur = newStyle[name]
+ if (cur !== oldStyle[name]) {
+ // ie9 setting to null has no effect, must use empty string
+ setProp(el, name, cur == null ? '' : cur)
+ }
+ }
+}
+
+export default {
+ create: updateStyle,
+ update: updateStyle
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/modules/transition.js b/node_modules/vue/src/platforms/web/runtime/modules/transition.js
new file mode 100644
index 00000000..0796b5da
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/modules/transition.js
@@ -0,0 +1,343 @@
+/* @flow */
+
+import { inBrowser, isIE9, warn } from 'core/util/index'
+import { mergeVNodeHook } from 'core/vdom/helpers/index'
+import { activeInstance } from 'core/instance/lifecycle'
+
+import {
+ once,
+ isDef,
+ isUndef,
+ isObject,
+ toNumber
+} from 'shared/util'
+
+import {
+ nextFrame,
+ resolveTransition,
+ whenTransitionEnds,
+ addTransitionClass,
+ removeTransitionClass
+} from '../transition-util'
+
+export function enter (vnode: VNodeWithData, toggleDisplay: ?() => void) {
+ const el: any = vnode.elm
+
+ // call leave callback now
+ if (isDef(el._leaveCb)) {
+ el._leaveCb.cancelled = true
+ el._leaveCb()
+ }
+
+ const data = resolveTransition(vnode.data.transition)
+ if (isUndef(data)) {
+ return
+ }
+
+ /* istanbul ignore if */
+ if (isDef(el._enterCb) || el.nodeType !== 1) {
+ return
+ }
+
+ const {
+ css,
+ type,
+ enterClass,
+ enterToClass,
+ enterActiveClass,
+ appearClass,
+ appearToClass,
+ appearActiveClass,
+ beforeEnter,
+ enter,
+ afterEnter,
+ enterCancelled,
+ beforeAppear,
+ appear,
+ afterAppear,
+ appearCancelled,
+ duration
+ } = data
+
+ // activeInstance will always be the <transition> component managing this
+ // transition. One edge case to check is when the <transition> is placed
+ // as the root node of a child component. In that case we need to check
+ // <transition>'s parent for appear check.
+ let context = activeInstance
+ let transitionNode = activeInstance.$vnode
+ while (transitionNode && transitionNode.parent) {
+ transitionNode = transitionNode.parent
+ context = transitionNode.context
+ }
+
+ const isAppear = !context._isMounted || !vnode.isRootInsert
+
+ if (isAppear && !appear && appear !== '') {
+ return
+ }
+
+ const startClass = isAppear && appearClass
+ ? appearClass
+ : enterClass
+ const activeClass = isAppear && appearActiveClass
+ ? appearActiveClass
+ : enterActiveClass
+ const toClass = isAppear && appearToClass
+ ? appearToClass
+ : enterToClass
+
+ const beforeEnterHook = isAppear
+ ? (beforeAppear || beforeEnter)
+ : beforeEnter
+ const enterHook = isAppear
+ ? (typeof appear === 'function' ? appear : enter)
+ : enter
+ const afterEnterHook = isAppear
+ ? (afterAppear || afterEnter)
+ : afterEnter
+ const enterCancelledHook = isAppear
+ ? (appearCancelled || enterCancelled)
+ : enterCancelled
+
+ const explicitEnterDuration: any = toNumber(
+ isObject(duration)
+ ? duration.enter
+ : duration
+ )
+
+ if (process.env.NODE_ENV !== 'production' && explicitEnterDuration != null) {
+ checkDuration(explicitEnterDuration, 'enter', vnode)
+ }
+
+ const expectsCSS = css !== false && !isIE9
+ const userWantsControl = getHookArgumentsLength(enterHook)
+
+ const cb = el._enterCb = once(() => {
+ if (expectsCSS) {
+ removeTransitionClass(el, toClass)
+ removeTransitionClass(el, activeClass)
+ }
+ if (cb.cancelled) {
+ if (expectsCSS) {
+ removeTransitionClass(el, startClass)
+ }
+ enterCancelledHook && enterCancelledHook(el)
+ } else {
+ afterEnterHook && afterEnterHook(el)
+ }
+ el._enterCb = null
+ })
+
+ if (!vnode.data.show) {
+ // remove pending leave element on enter by injecting an insert hook
+ mergeVNodeHook(vnode, 'insert', () => {
+ const parent = el.parentNode
+ const pendingNode = parent && parent._pending && parent._pending[vnode.key]
+ if (pendingNode &&
+ pendingNode.tag === vnode.tag &&
+ pendingNode.elm._leaveCb
+ ) {
+ pendingNode.elm._leaveCb()
+ }
+ enterHook && enterHook(el, cb)
+ })
+ }
+
+ // start enter transition
+ beforeEnterHook && beforeEnterHook(el)
+ if (expectsCSS) {
+ addTransitionClass(el, startClass)
+ addTransitionClass(el, activeClass)
+ nextFrame(() => {
+ removeTransitionClass(el, startClass)
+ if (!cb.cancelled) {
+ addTransitionClass(el, toClass)
+ if (!userWantsControl) {
+ if (isValidDuration(explicitEnterDuration)) {
+ setTimeout(cb, explicitEnterDuration)
+ } else {
+ whenTransitionEnds(el, type, cb)
+ }
+ }
+ }
+ })
+ }
+
+ if (vnode.data.show) {
+ toggleDisplay && toggleDisplay()
+ enterHook && enterHook(el, cb)
+ }
+
+ if (!expectsCSS && !userWantsControl) {
+ cb()
+ }
+}
+
+export function leave (vnode: VNodeWithData, rm: Function) {
+ const el: any = vnode.elm
+
+ // call enter callback now
+ if (isDef(el._enterCb)) {
+ el._enterCb.cancelled = true
+ el._enterCb()
+ }
+
+ const data = resolveTransition(vnode.data.transition)
+ if (isUndef(data) || el.nodeType !== 1) {
+ return rm()
+ }
+
+ /* istanbul ignore if */
+ if (isDef(el._leaveCb)) {
+ return
+ }
+
+ const {
+ css,
+ type,
+ leaveClass,
+ leaveToClass,
+ leaveActiveClass,
+ beforeLeave,
+ leave,
+ afterLeave,
+ leaveCancelled,
+ delayLeave,
+ duration
+ } = data
+
+ const expectsCSS = css !== false && !isIE9
+ const userWantsControl = getHookArgumentsLength(leave)
+
+ const explicitLeaveDuration: any = toNumber(
+ isObject(duration)
+ ? duration.leave
+ : duration
+ )
+
+ if (process.env.NODE_ENV !== 'production' && isDef(explicitLeaveDuration)) {
+ checkDuration(explicitLeaveDuration, 'leave', vnode)
+ }
+
+ const cb = el._leaveCb = once(() => {
+ if (el.parentNode && el.parentNode._pending) {
+ el.parentNode._pending[vnode.key] = null
+ }
+ if (expectsCSS) {
+ removeTransitionClass(el, leaveToClass)
+ removeTransitionClass(el, leaveActiveClass)
+ }
+ if (cb.cancelled) {
+ if (expectsCSS) {
+ removeTransitionClass(el, leaveClass)
+ }
+ leaveCancelled && leaveCancelled(el)
+ } else {
+ rm()
+ afterLeave && afterLeave(el)
+ }
+ el._leaveCb = null
+ })
+
+ if (delayLeave) {
+ delayLeave(performLeave)
+ } else {
+ performLeave()
+ }
+
+ function performLeave () {
+ // the delayed leave may have already been cancelled
+ if (cb.cancelled) {
+ return
+ }
+ // record leaving element
+ if (!vnode.data.show) {
+ (el.parentNode._pending || (el.parentNode._pending = {}))[(vnode.key: any)] = vnode
+ }
+ beforeLeave && beforeLeave(el)
+ if (expectsCSS) {
+ addTransitionClass(el, leaveClass)
+ addTransitionClass(el, leaveActiveClass)
+ nextFrame(() => {
+ removeTransitionClass(el, leaveClass)
+ if (!cb.cancelled) {
+ addTransitionClass(el, leaveToClass)
+ if (!userWantsControl) {
+ if (isValidDuration(explicitLeaveDuration)) {
+ setTimeout(cb, explicitLeaveDuration)
+ } else {
+ whenTransitionEnds(el, type, cb)
+ }
+ }
+ }
+ })
+ }
+ leave && leave(el, cb)
+ if (!expectsCSS && !userWantsControl) {
+ cb()
+ }
+ }
+}
+
+// only used in dev mode
+function checkDuration (val, name, vnode) {
+ if (typeof val !== 'number') {
+ warn(
+ `<transition> explicit ${name} duration is not a valid number - ` +
+ `got ${JSON.stringify(val)}.`,
+ vnode.context
+ )
+ } else if (isNaN(val)) {
+ warn(
+ `<transition> explicit ${name} duration is NaN - ` +
+ 'the duration expression might be incorrect.',
+ vnode.context
+ )
+ }
+}
+
+function isValidDuration (val) {
+ return typeof val === 'number' && !isNaN(val)
+}
+
+/**
+ * Normalize a transition hook's argument length. The hook may be:
+ * - a merged hook (invoker) with the original in .fns
+ * - a wrapped component method (check ._length)
+ * - a plain function (.length)
+ */
+function getHookArgumentsLength (fn: Function): boolean {
+ if (isUndef(fn)) {
+ return false
+ }
+ const invokerFns = fn.fns
+ if (isDef(invokerFns)) {
+ // invoker
+ return getHookArgumentsLength(
+ Array.isArray(invokerFns)
+ ? invokerFns[0]
+ : invokerFns
+ )
+ } else {
+ return (fn._length || fn.length) > 1
+ }
+}
+
+function _enter (_: any, vnode: VNodeWithData) {
+ if (vnode.data.show !== true) {
+ enter(vnode)
+ }
+}
+
+export default inBrowser ? {
+ create: _enter,
+ activate: _enter,
+ remove (vnode: VNode, rm: Function) {
+ /* istanbul ignore else */
+ if (vnode.data.show !== true) {
+ leave(vnode, rm)
+ } else {
+ rm()
+ }
+ }
+} : {}
diff --git a/node_modules/vue/src/platforms/web/runtime/node-ops.js b/node_modules/vue/src/platforms/web/runtime/node-ops.js
new file mode 100644
index 00000000..3a2978a7
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/node-ops.js
@@ -0,0 +1,59 @@
+/* @flow */
+
+import { namespaceMap } from 'web/util/index'
+
+export function createElement (tagName: string, vnode: VNode): Element {
+ const elm = document.createElement(tagName)
+ if (tagName !== 'select') {
+ return elm
+ }
+ // false or null will remove the attribute but undefined will not
+ if (vnode.data && vnode.data.attrs && vnode.data.attrs.multiple !== undefined) {
+ elm.setAttribute('multiple', 'multiple')
+ }
+ return elm
+}
+
+export function createElementNS (namespace: string, tagName: string): Element {
+ return document.createElementNS(namespaceMap[namespace], tagName)
+}
+
+export function createTextNode (text: string): Text {
+ return document.createTextNode(text)
+}
+
+export function createComment (text: string): Comment {
+ return document.createComment(text)
+}
+
+export function insertBefore (parentNode: Node, newNode: Node, referenceNode: Node) {
+ parentNode.insertBefore(newNode, referenceNode)
+}
+
+export function removeChild (node: Node, child: Node) {
+ node.removeChild(child)
+}
+
+export function appendChild (node: Node, child: Node) {
+ node.appendChild(child)
+}
+
+export function parentNode (node: Node): ?Node {
+ return node.parentNode
+}
+
+export function nextSibling (node: Node): ?Node {
+ return node.nextSibling
+}
+
+export function tagName (node: Element): string {
+ return node.tagName
+}
+
+export function setTextContent (node: Node, text: string) {
+ node.textContent = text
+}
+
+export function setStyleScope (node: Element, scopeId: string) {
+ node.setAttribute(scopeId, '')
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/patch.js b/node_modules/vue/src/platforms/web/runtime/patch.js
new file mode 100644
index 00000000..d982afe9
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/patch.js
@@ -0,0 +1,12 @@
+/* @flow */
+
+import * as nodeOps from 'web/runtime/node-ops'
+import { createPatchFunction } from 'core/vdom/patch'
+import baseModules from 'core/vdom/modules/index'
+import platformModules from 'web/runtime/modules/index'
+
+// the directive module should be applied last, after all
+// built-in modules have been applied.
+const modules = platformModules.concat(baseModules)
+
+export const patch: Function = createPatchFunction({ nodeOps, modules })
diff --git a/node_modules/vue/src/platforms/web/runtime/transition-util.js b/node_modules/vue/src/platforms/web/runtime/transition-util.js
new file mode 100644
index 00000000..47668f0c
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/transition-util.js
@@ -0,0 +1,185 @@
+/* @flow */
+
+import { inBrowser, isIE9 } from 'core/util/index'
+import { addClass, removeClass } from './class-util'
+import { remove, extend, cached } from 'shared/util'
+
+export function resolveTransition (def?: string | Object): ?Object {
+ if (!def) {
+ return
+ }
+ /* istanbul ignore else */
+ if (typeof def === 'object') {
+ const res = {}
+ if (def.css !== false) {
+ extend(res, autoCssTransition(def.name || 'v'))
+ }
+ extend(res, def)
+ return res
+ } else if (typeof def === 'string') {
+ return autoCssTransition(def)
+ }
+}
+
+const autoCssTransition: (name: string) => Object = cached(name => {
+ return {
+ enterClass: `${name}-enter`,
+ enterToClass: `${name}-enter-to`,
+ enterActiveClass: `${name}-enter-active`,
+ leaveClass: `${name}-leave`,
+ leaveToClass: `${name}-leave-to`,
+ leaveActiveClass: `${name}-leave-active`
+ }
+})
+
+export const hasTransition = inBrowser && !isIE9
+const TRANSITION = 'transition'
+const ANIMATION = 'animation'
+
+// Transition property/event sniffing
+export let transitionProp = 'transition'
+export let transitionEndEvent = 'transitionend'
+export let animationProp = 'animation'
+export let animationEndEvent = 'animationend'
+if (hasTransition) {
+ /* istanbul ignore if */
+ if (window.ontransitionend === undefined &&
+ window.onwebkittransitionend !== undefined
+ ) {
+ transitionProp = 'WebkitTransition'
+ transitionEndEvent = 'webkitTransitionEnd'
+ }
+ if (window.onanimationend === undefined &&
+ window.onwebkitanimationend !== undefined
+ ) {
+ animationProp = 'WebkitAnimation'
+ animationEndEvent = 'webkitAnimationEnd'
+ }
+}
+
+// binding to window is necessary to make hot reload work in IE in strict mode
+const raf = inBrowser
+ ? window.requestAnimationFrame
+ ? window.requestAnimationFrame.bind(window)
+ : setTimeout
+ : /* istanbul ignore next */ fn => fn()
+
+export function nextFrame (fn: Function) {
+ raf(() => {
+ raf(fn)
+ })
+}
+
+export function addTransitionClass (el: any, cls: string) {
+ const transitionClasses = el._transitionClasses || (el._transitionClasses = [])
+ if (transitionClasses.indexOf(cls) < 0) {
+ transitionClasses.push(cls)
+ addClass(el, cls)
+ }
+}
+
+export function removeTransitionClass (el: any, cls: string) {
+ if (el._transitionClasses) {
+ remove(el._transitionClasses, cls)
+ }
+ removeClass(el, cls)
+}
+
+export function whenTransitionEnds (
+ el: Element,
+ expectedType: ?string,
+ cb: Function
+) {
+ const { type, timeout, propCount } = getTransitionInfo(el, expectedType)
+ if (!type) return cb()
+ const event: string = type === TRANSITION ? transitionEndEvent : animationEndEvent
+ let ended = 0
+ const end = () => {
+ el.removeEventListener(event, onEnd)
+ cb()
+ }
+ const onEnd = e => {
+ if (e.target === el) {
+ if (++ended >= propCount) {
+ end()
+ }
+ }
+ }
+ setTimeout(() => {
+ if (ended < propCount) {
+ end()
+ }
+ }, timeout + 1)
+ el.addEventListener(event, onEnd)
+}
+
+const transformRE = /\b(transform|all)(,|$)/
+
+export function getTransitionInfo (el: Element, expectedType?: ?string): {
+ type: ?string;
+ propCount: number;
+ timeout: number;
+ hasTransform: boolean;
+} {
+ const styles: any = window.getComputedStyle(el)
+ const transitionDelays: Array<string> = styles[transitionProp + 'Delay'].split(', ')
+ const transitionDurations: Array<string> = styles[transitionProp + 'Duration'].split(', ')
+ const transitionTimeout: number = getTimeout(transitionDelays, transitionDurations)
+ const animationDelays: Array<string> = styles[animationProp + 'Delay'].split(', ')
+ const animationDurations: Array<string> = styles[animationProp + 'Duration'].split(', ')
+ const animationTimeout: number = getTimeout(animationDelays, animationDurations)
+
+ let type: ?string
+ let timeout = 0
+ let propCount = 0
+ /* istanbul ignore if */
+ if (expectedType === TRANSITION) {
+ if (transitionTimeout > 0) {
+ type = TRANSITION
+ timeout = transitionTimeout
+ propCount = transitionDurations.length
+ }
+ } else if (expectedType === ANIMATION) {
+ if (animationTimeout > 0) {
+ type = ANIMATION
+ timeout = animationTimeout
+ propCount = animationDurations.length
+ }
+ } else {
+ timeout = Math.max(transitionTimeout, animationTimeout)
+ type = timeout > 0
+ ? transitionTimeout > animationTimeout
+ ? TRANSITION
+ : ANIMATION
+ : null
+ propCount = type
+ ? type === TRANSITION
+ ? transitionDurations.length
+ : animationDurations.length
+ : 0
+ }
+ const hasTransform: boolean =
+ type === TRANSITION &&
+ transformRE.test(styles[transitionProp + 'Property'])
+ return {
+ type,
+ timeout,
+ propCount,
+ hasTransform
+ }
+}
+
+function getTimeout (delays: Array<string>, durations: Array<string>): number {
+ /* istanbul ignore next */
+ while (delays.length < durations.length) {
+ delays = delays.concat(delays)
+ }
+
+ return Math.max.apply(null, durations.map((d, i) => {
+ return toMs(d) + toMs(delays[i])
+ }))
+}
+
+function toMs (s: string): number {
+ return Number(s.slice(0, -1)) * 1000
+}