var PywbVue = (function (exports) { 'use strict'; const PywbMonthLabels = {1:"Jan", 2:"Feb",3:"Mar",4:"Apr",5:"May",6:"Jun",7:"Jul",8:"Aug",9:"Sep",10:"Oct",11:"Nov",12:"Dec"}; function PywbData(rawSnaps) { const allTimePeriod = new PywbPeriod({type: PywbPeriod.Type.all, id: "all"}); const snapshots = []; let lastSingle = null; rawSnaps.forEach((rawSnap, i) => { const snap = new PywbSnapshot(rawSnap, i); let year, month, day, hour, single; if (!(year = allTimePeriod.getChildById(snap.year))) { year = new PywbPeriod({type: PywbPeriod.Type.year, id: snap.year}); allTimePeriod.addChild(year); } if (!(month = year.getChildById(snap.month))) { month = new PywbPeriod({type: PywbPeriod.Type.month, id: snap.month}); year.addChild(month); } if (!(day = month.getChildById(snap.day))) { day = new PywbPeriod({type: PywbPeriod.Type.day, id: snap.day}); month.addChild(day); } const hourValue = Math.ceil((snap.hour + .0001) / (24/8)); // divide day in 4 six-hour periods (aka quarters) //const hourValue = snap.hour; if (!(hour = day.getChildById(hourValue))) { hour = new PywbPeriod({type: PywbPeriod.Type.hour, id: hourValue}); day.addChild(hour); } if (!(single = hour.getChildById(snap.id))) { single = new PywbPeriod({type: PywbPeriod.Type.snapshot, id: snap.id}); hour.addChild(single); } single.setSnapshot(snap); if (lastSingle) { lastSingle.setNextSnapshotPeriod(single); single.setPreviousSnapshotPeriod(lastSingle); } lastSingle = single; snapshots.push(snap); }); this.timeline = allTimePeriod; this.snapshots = snapshots; this.getSnapshot = function(index) { if (index < 0 || index >= this.snapshots.length) { return null; } return this.snapshots[index]; }; this.getPreviousSnapshot = function(snapshot) { const index = snapshot.index; return this.getSnapshot(index-1); }; this.getNextSnapshot = function(snapshot) { const index = snapshot.index; return this.getSnapshot(index+1); }; } /* ---------------- SNAP SHOT object ----------------- */ class PywbSnapshot { constructor(init, index) { this.index = index; this.year = parseInt(init.timestamp.substr(0, 4)); this.month = parseInt(init.timestamp.substr(4, 2)); this.day = parseInt(init.timestamp.substr(6, 2)); this.hour = parseInt(init.timestamp.substr(8, 2)); this.minute = parseInt(init.timestamp.substr(10, 2)); this.second = parseInt(init.timestamp.substr(12, 2)); this.id = parseInt(init.timestamp); this.urlkey = init.urlkey; this.url = init.url; this.mime = init.mime; this.status = init.status; this.digest = init.digest; this.redirect = init.redirect; this.robotflags = init.robotflags; this.length = init.length; this.offset = init.offset; this.filename = init.filename; this.load_url = init.load_url; this["source-col"] = init["source-col"]; this.access = init.access; } getTimeDateFormatted() { return `${this.year}-${PywbMonthLabels[this.month]}-${this.day} ${this.getTimeFormatted()}`; } getDateFormatted() { return `${this.year}-${PywbMonthLabels[this.month]}-${this.day}`; } getTimeFormatted() { return (this.hour < 13 ? this.hour : (this.hour % 12)) + ":" + ((this.minute < 10 ? "0":"")+this.minute) + ":" + ((this.second < 10 ? "0":"")+this.second) + " " + (this.hour < 12 ? "am":"pm"); } } /* ---------------- PERIOD object ----------------- */ function PywbPeriod(init) { this.type = init.type; this.id = init.id; this.childrenIds = {}; // allow for query by ID this.children = []; // allow for sequentiality / order this.maxGrandchildSnapshotCount = 0; this.snapshotCount = 0; } PywbPeriod.Type = {all: 0,year: 1,month: 2,day: 3,hour: 4,snapshot:5}; PywbPeriod.TypeLabel = ["timeline","year","month","day","hour","snapshot"]; PywbPeriod.prototype.getTypeLabel = function() { return PywbPeriod.TypeLabel[this.type]; }; PywbPeriod.GetTypeLabel = function(type) { return PywbPeriod.TypeLabel[type] ? PywbPeriod.TypeLabel[type] : ""; }; PywbPeriod.prototype.getChildById = function(id) { return this.children[this.childrenIds[id]]; }; // previous period (ONLY SET at the period level/type: snapshot) PywbPeriod.prototype.getPreviousSnapshotPeriod = () => {}; PywbPeriod.prototype.setPreviousSnapshotPeriod = function(period) { this.getPreviousSnapshotPeriod = () => period; }; // next period (ONLY SET at the period level/type: snapshot) PywbPeriod.prototype.getNextSnapshotPeriod = () => {}; PywbPeriod.prototype.setNextSnapshotPeriod = function(period) { this.getNextSnapshotPeriod = () => period; }; PywbPeriod.prototype.getFirstSnapshotPeriod = function() { return this.getFirstLastSnapshotPeriod_("first"); }; PywbPeriod.prototype.getLastSnapshotPeriod = function() { return this.getFirstLastSnapshotPeriod_("last"); }; PywbPeriod.prototype.getFirstLastSnapshotPeriod_ = function(direction) { let period = this; let iFailSafe = 100; // in case a parser has a bug and the snapshotCount is not correct; avoid infinite-loop while (period.snapshotCount && period.type !== PywbPeriod.Type.snapshot) { let i = 0; for(i=0; i < period.children.length; i++) { const ii = direction === "first" ? i : (period.children.length - 1 - i); if (period.children[ii].snapshotCount) { period = period.children[ii]; break; } } if (iFailSafe-- < 0) { break; } } if (period.type === PywbPeriod.Type.snapshot && period.snapshot) { return period; } return null; }; PywbPeriod.prototype.getPrevious = function() { const firstSnapshotPeriod = this.getFirstSnapshotPeriod(); if (!firstSnapshotPeriod) { return null; } const previousSnapshotPeriod = firstSnapshotPeriod.getPreviousSnapshotPeriod(); if (!previousSnapshotPeriod) { return null; } if (this.type === PywbPeriod.Type.snapshot) { return previousSnapshotPeriod; } let parent = previousSnapshotPeriod.parent; while(parent) { if (parent.type === this.type) { break; } parent = parent.parent; } return parent; }; PywbPeriod.prototype.getNext = function() { const lastSnapshotPeriod = this.getLastSnapshotPeriod(); if (!lastSnapshotPeriod) { return null; } const nextSnapshotPeriod = lastSnapshotPeriod.getNextSnapshotPeriod(); if (!nextSnapshotPeriod) { return null; } if (this.type === PywbPeriod.Type.snapshot) { return nextSnapshotPeriod; } let parent = nextSnapshotPeriod.parent; while(parent) { if (parent.type === this.type) { break; } parent = parent.parent; } return parent; }; PywbPeriod.prototype.parent = null; PywbPeriod.prototype.addChild = function(period) { if (this.getChildById(period.id)) { return false; } period.parent = this; this.childrenIds[period.id] = this.children.length; this.children.push(period); return true; }; PywbPeriod.prototype.getChildrenRange = function() { switch (this.type) { case PywbPeriod.Type.all: // year range: first to last year available return [this.children[0].id, this.children[this.children.length-1].id]; case PywbPeriod.Type.year: // month is simple: 1 to 12 return [1,12]; case PywbPeriod.Type.month: // days in month: 1 to last day in month const y = this.parent.id; const m = this.id; const lastDateInMonth = (new Date((new Date(y, m, 1)).getTime() - 1000)).getDate(); // 1 sec earlier return [1, lastDateInMonth]; case PywbPeriod.Type.day: // hours: 0 to 23 // return [1,4]; return [1,8]; } return null; }; PywbPeriod.prototype.fillEmptyGrancChildPeriods = function() { if (this.hasFilledEmptyGrandchildPeriods) { return; } this.children.forEach(c => { c.fillEmptyChildPeriods(); }); this.hasFilledEmptyGrandchildPeriods = true; }; PywbPeriod.prototype.fillEmptyChildPeriods = function(isFillEmptyGrandChildrenPeriods=false) { if (this.snapshotCount === 0 || this.type > PywbPeriod.Type.day) { return; } if (isFillEmptyGrandChildrenPeriods) { this.fillEmptyGrancChildPeriods(); } if (this.hasFilledEmptyChildPeriods) { return; } this.hasFilledEmptyChildPeriods = true; const idRange = this.getChildrenRange(); if (!idRange) { return; } let i = 0; for (let newId = idRange[0]; newId <= idRange[1]; newId++) { if (i < this.children.length) { // if existing and new id match, skip, item already in place // else if (this.children[i].id !== newId) { const empty = new PywbPeriod({type: this.type + 1, id: newId}); if (newId < this.children[i].id) { // insert new before existing this.children.splice(i, 0, empty); } else { // insert new after existing this.children.splice(i+1, 0, empty); } // manually push children (no need to reverse link parent //empty.parent = this; } i++; } else { const empty = new PywbPeriod({type: this.type + 1, id: newId}); this.children.push(empty); // manually push children (no need to reverse link parent //empty.parent = this; } } // re-calculate indexes for(let i=0;i p.getReadableId(hasDayCardinalSuffix)).join(" ") + " " + this.getReadableId(hasDayCardinalSuffix); }; PywbPeriod.prototype.getReadableId = function(hasDayCardinalSuffix) { switch (this.type) { case PywbPeriod.Type.all: return "All-time"; case PywbPeriod.Type.year: return this.id; case PywbPeriod.Type.month: return PywbMonthLabels[this.id]; case PywbPeriod.Type.day: let suffix = ""; if (hasDayCardinalSuffix) { const singleDigit = this.id % 10; const isTens = Math.floor(this.id / 10) === 1; const suffixes = {1:"st", 2:"nd",3:"rd"}; suffix = (isTens || !suffixes[singleDigit]) ? "th" : suffixes[singleDigit]; } return this.id + suffix; case PywbPeriod.Type.hour: return ({1:"12 am", 2: "3 am", 3: "6 am", 4: "9 am", 5: "noon", 6: "3 pm", 7: "6 pm", 8: "9 pm"})[this.id]; //return ({1:'midnight', 2: '6 am', 3: 'noon', 4: '6 pm'})[this.id]; //return (this.id < 13 ? this.id : this.id % 12) + ' ' + (this.id < 12 ? 'am':'pm'); case PywbPeriod.Type.snapshot: return this.snapshot.getTimeFormatted(); } }; // var script$4 = { props: ["period", "highlight"], data: function() { return { // TODO: remove widths (now using flex css for width calculation) subPeriodBoxWidths: {// in pixels [PywbPeriod.Type.year]: 80, // year box [PywbPeriod.Type.month]: 80, // month box in year [PywbPeriod.Type.day]: 20, // days box in month [PywbPeriod.Type.hour]: 60, // hour box in day [PywbPeriod.Type.snapshot]: 10 // snapshot box in hour/day }, // TODO: remove widths (now using flex css for width calculation) emptySubPeriodBoxWidths: {// in pixels [PywbPeriod.Type.year]: 40, // year box [PywbPeriod.Type.month]: 40, // month box in year [PywbPeriod.Type.day]: 20, // days box in month [PywbPeriod.Type.hour]: 40, // hour box in day [PywbPeriod.Type.snapshot]: 20 // snapshot box in hour/day }, highlightPeriod: null, previousPeriod: null, nextPeriod: null, isScrollZero: true, isScrollMax: true, }; }, created: function() { this.addEmptySubPeriods(); }, mounted: function() { this.$refs.periods._computedStyle = window.getComputedStyle(this.$refs.periods); this.$refs.periodScroll._computedStyle = window.getComputedStyle(this.$refs.periodScroll); this.$watch("period", this.onPeriodChanged); // TODO: remove widths (now using flex css for width calculation), so we don't need manual calc //this.adjustScrollElWidth(); this.$refs.periodScroll.addEventListener("scroll", this.updateScrollArrows); window.addEventListener("resize", this.updateScrollArrows); this.updateScrollArrows(); }, computed: { subPeriodBoxWidth: function() { return this.subPeriodBoxWidths[this.period.type+1]; // the type of the period children }, // TODO: remove widths (now using flex css for width calculation) emptySubPeriodBoxWidth: function() { return this.emptySubPeriodBoxWidths[this.period.type+1]; // the type of the period children }, // this determins which the last zoom level is before we go straight to showing snapshot isLastZoomLevel() { return this.period.type === PywbPeriod.Type.day; } }, updated() { // do something on update }, methods: { addEmptySubPeriods() { this.period.fillEmptyChildPeriods(true); }, updateScrollArrows() { this.period.scroll = this.$refs.periodScroll.scrollLeft; const maxScroll = parseInt(this.$refs.periods._computedStyle.width) - parseInt(this.$refs.periodScroll._computedStyle.width); this.isScrollZero = !this.period.scroll; // if 0, then true (we are at scroll zero) this.isScrollMax = Math.abs(maxScroll - this.period.scroll) < 5; }, restoreScroll() { this.$refs.periodScroll.scrollLeft = this.period.scroll; }, scrollNext: function () { if (this.isScrollMax) { if (this.nextPeriod) { this.$emit("goto-period", this.nextPeriod); } } else { this.$refs.periodScroll.scrollLeft += 30; } }, scrollPrev: function () { if (this.isScrollZero) { if (this.previousPeriod) { this.$emit("goto-period", this.previousPeriod); } } else { this.$refs.periodScroll.scrollLeft -= 30; } }, getTimeFormatted: function(date) { return (date.hour < 13 ? date.hour : (date.hour % 12)) + ":" + ((date.minute < 10 ? "0":"")+date.minute) + " " + (date.hour < 12 ? "am":"pm"); }, getHistoLineHeight: function(value) { const percent = Math.ceil((value/this.period.maxGrandchildSnapshotCount) * 100); return (percent ? (5 + Math.ceil(percent*.95)) : 0) + "%"; // return percent + '%'; }, changePeriod(period) { if (period.snapshotCount) { if (this.isLastZoomLevel) { if (period.type === PywbPeriod.Type.snapshot) { this.$emit("goto-period", period); } } else { this.$emit("goto-period", period); } } }, // special "change period" from histogram lines changePeriodFromHistogram(period) { if (this.isLastZoomLevel && period.type === PywbPeriod.Type.snapshot) { this.$emit("goto-period", period); } }, onPeriodChanged(newPeriod, oldPeriod) { this.addEmptySubPeriods(); this.previousPeriod = this.period.getPrevious(); this.nextPeriod = this.period.getNext(); // detect if going up level of period (new period type should be in old period parents) if (oldPeriod.type - newPeriod.type > 0) { let highlightPeriod = oldPeriod; for (let i=oldPeriod.type - newPeriod.type; i > 1; i--) { highlightPeriod = highlightPeriod.parent; } this.highlightPeriod = highlightPeriod; setTimeout((function() { this.highlightPeriod = null; }).bind(this), 2000); } setTimeout((function() { // TODO: remove widths (now using flex css for width calculation), so we don't need manual calc //this.adjustScrollElWidth(); this.restoreScroll(); this.updateScrollArrows(); }).bind(this), 1); }, // TODO: remove widths (now using flex css for width calculation), so we don't need manual calc adjustScrollElWidth() { //this.$refs.periodScroll.style.maxWidth = this.$refs.periods._computedStyle.width; } } }; function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) { if (typeof shadowMode !== 'boolean') { createInjectorSSR = createInjector; createInjector = shadowMode; shadowMode = false; } // Vue.extend constructor export interop. const options = typeof script === 'function' ? script.options : script; // render functions if (template && template.render) { options.render = template.render; options.staticRenderFns = template.staticRenderFns; options._compiled = true; // functional template if (isFunctionalTemplate) { options.functional = true; } } // scopedId if (scopeId) { options._scopeId = scopeId; } let hook; if (moduleIdentifier) { // server build hook = function (context) { // 2.3 injection context = context || // cached call (this.$vnode && this.$vnode.ssrContext) || // stateful (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext); // functional // 2.2 with runInNewContext: true if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') { context = __VUE_SSR_CONTEXT__; } // inject component styles if (style) { style.call(this, createInjectorSSR(context)); } // register component module identifier for async chunk inference if (context && context._registeredComponents) { context._registeredComponents.add(moduleIdentifier); } }; // used by ssr in case component is cached and beforeCreate // never gets called options._ssrRegister = hook; } else if (style) { hook = shadowMode ? function (context) { style.call(this, createInjectorShadow(context, this.$root.$options.shadowRoot)); } : function (context) { style.call(this, createInjector(context)); }; } if (hook) { if (options.functional) { // register for functional component in vue file const originalRender = options.render; options.render = function renderWithStyleInjection(h, context) { hook.call(context); return originalRender(h, context); }; } else { // inject component registration as beforeCreate hook const existing = options.beforeCreate; options.beforeCreate = existing ? [].concat(existing, hook) : [hook]; } } return script; } const isOldIE = typeof navigator !== 'undefined' && /msie [6-9]\\b/.test(navigator.userAgent.toLowerCase()); function createInjector(context) { return (id, style) => addStyle(id, style); } let HEAD; const styles = {}; function addStyle(id, css) { const group = isOldIE ? css.media || 'default' : id; const style = styles[group] || (styles[group] = { ids: new Set(), styles: [] }); if (!style.ids.has(id)) { style.ids.add(id); let code = css.source; if (css.map) { // https://developer.chrome.com/devtools/docs/javascript-debugging // this makes source maps inside style tags work properly in Chrome code += '\n/*# sourceURL=' + css.map.sources[0] + ' */'; // http://stackoverflow.com/a/26603875 code += '\n/*# sourceMappingURL=data:application/json;base64,' + btoa(unescape(encodeURIComponent(JSON.stringify(css.map)))) + ' */'; } if (!style.element) { style.element = document.createElement('style'); style.element.type = 'text/css'; if (css.media) style.element.setAttribute('media', css.media); if (HEAD === undefined) { HEAD = document.head || document.getElementsByTagName('head')[0]; } HEAD.appendChild(style.element); } if ('styleSheet' in style.element) { style.styles.push(code); style.element.styleSheet.cssText = style.styles .filter(Boolean) .join('\n'); } else { const index = style.ids.size - 1; const textNode = document.createTextNode(code); const nodes = style.element.childNodes; if (nodes[index]) style.element.removeChild(nodes[index]); if (nodes.length) style.element.insertBefore(textNode, nodes[index]); else style.element.appendChild(textNode); } } } /* script */ const __vue_script__$4 = script$4; /* template */ var __vue_render__$4 = function() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c("div", { staticClass: "timeline" }, [ _c( "div", { staticClass: "arrow previous", class: { disabled: _vm.isScrollZero && !_vm.previousPeriod }, on: { click: _vm.scrollPrev, dblclick: function($event) { $event.stopPropagation(); $event.preventDefault(); } } }, [_vm._v("◀")] ), _vm._v(" "), _c( "div", { ref: "periodScroll", staticClass: "scroll", class: { highlight: _vm.highlight } }, [ _c( "div", { ref: "periods", staticClass: "periods" }, _vm._l(_vm.period.children, function(subPeriod) { return _c( "div", { key: subPeriod.id, staticClass: "period", class: { empty: !subPeriod.snapshotCount, highlight: _vm.highlightPeriod === subPeriod, "last-level": _vm.isLastZoomLevel }, on: { click: function($event) { return _vm.changePeriod(subPeriod) } } }, [ _c( "div", { staticClass: "histo" }, [ !subPeriod.snapshot && !_vm.isLastZoomLevel ? _c("div", { staticClass: "count" }, [ _c("span", { staticClass: "count-inner" }, [ _vm._v(_vm._s(subPeriod.snapshotCount)) ]) ]) : _vm._e(), _vm._v(" "), _vm._l(subPeriod.children, function(histoPeriod) { return _c( "div", { key: histoPeriod.id, staticClass: "line", style: { height: _vm.getHistoLineHeight( histoPeriod.snapshotCount ) }, on: { click: function($event) { return _vm.changePeriodFromHistogram(histoPeriod) } } }, [ _vm.isLastZoomLevel ? _c("div", { staticClass: "snap-info" }, [ _vm._v( _vm._s( histoPeriod.snapshot.getTimeDateFormatted() ) ) ]) : _vm._e() ] ) }) ], 2 ), _vm._v(" "), _c("div", { staticClass: "inner" }, [ _c("div", { staticClass: "label" }, [ _vm._v(_vm._s(subPeriod.getReadableId())) ]) ]) ] ) }), 0 ) ] ), _vm._v(" "), _c( "div", { staticClass: "arrow next", class: { disabled: _vm.isScrollMax && !_vm.nextPeriod }, on: { click: _vm.scrollNext, dblclick: function($event) { $event.stopPropagation(); $event.preventDefault(); } } }, [_vm._v("▶")] ) ]) }; var __vue_staticRenderFns__$4 = []; __vue_render__$4._withStripped = true; /* style */ const __vue_inject_styles__$4 = function (inject) { if (!inject) return inject("data-v-54dd375d_0", { source: "\n.timeline {\n position: relative;\n display: flex;\n width: auto;\n height: 80px;\n margin: 5px;\n justify-content: left;\n}\n.timeline .id {\n display: inline-block;\n font-size: 30px;\n}\n.timeline .arrow {\n display: inline-block;\n width: 20px;\n font-size: 20px; /* font-size = width of arrow, as it UTF char */\n line-height: 80px;\n vertical-align: top;\n cursor: pointer;\n}\n.timeline .arrow.previous {\n}\n.timeline .arrow.next {\n}\n.timeline .arrow.disabled, .timeline .arrow.disabled:hover {\n color: lightgray;\n background-color: transparent;\n cursor: not-allowed;\n}\n.timeline .arrow:hover {\n background-color: antiquewhite;\n color: firebrick;\n}\n.timeline .scroll {\n position: relative;\n display: inline-block;\n width: 100%; /* */\n height: 100%;\n\n /* maker scrollable horizontally */\n overflow-x: scroll;\n overflow-y: hidden;\n white-space: nowrap;\n scroll-behavior: smooth;\n\n text-align: center;\n\n transition: background-color 500ms ease-in;\n}\n/* hide scroll bar */\n.timeline .scroll::-webkit-scrollbar {\n display: none;\n}\n/* highlight the scroll period: usually triggered from root app */\n.timeline .scroll.highlight {\n background-color: #fff7ce;\n}\n.timeline .scroll .periods {\n display: flex;\n justify-content: space-between;\n height: 100%;\n width: 100%;\n min-width: 600px;\n}\n.timeline .period {\n flex-grow: 1;\n position: relative;\n display: inline-block;\n height: 100%;\n /* line-height: 80px; /* use to center middle vertically */\n white-space: normal;\n vertical-align: top;\n text-align: center;\n /*background-color: #eee;*/\n /*border-right: 1px solid white; !* all other periods have right border, except first period*!*/\n cursor: pointer;\n\n transition: background-color 500ms ease-in-out;\n}\n/* 1st period period child el */\n.timeline .period:nth-child(1) {\n /*border-left: 1px solid white; !* has left border; all other periods have right border *!*/\n}\n.timeline .period:hover {\n background-color: #eeeeee;\n}\n\n/* empty period */\n.timeline .period.empty {\n color: #aaa;\n /*background-color: transparent;*/\n}\n/* highlighted period */\n.timeline .period.highlight {\n background-color: cyan;\n}\n.timeline .period .label {\n font-weight: bold;\n font-size: 14px;\n font-family: Baskerville, sans-serif;\n}\n.timeline .period .count {\n position: absolute;\n top: 0;\n left: 0;\n display: none;\n width: 100%;\n height: 100%;\n padding: 10px 0 0 0;\n text-align: center;\n font-size: 25px;\n}\n.timeline .period .count .count-inner {\n display: inline;\n width: auto;\n background-color: rgba(255,255,255,.85);\n padding: 1px;\n border-radius: 5px;\n}\n.timeline .period:hover .count {\n display: block;\n}\n.timeline .period .inner {\n display: block;\n position: absolute;\n bottom: 0;\n left: 0;\n width: 100%;\n height: 16px;\n background-color: white;\n border-top: 1px solid gray;\n}\n.timeline .period.last-level .inner {\n text-align: left;\n}\n.timeline .period .histo {\n display: flex;\n position: absolute;\n top: 1px;\n left: 0;\n width: 100%;\n height: 60px;\n align-items: flex-end;\n justify-content: space-between;\n text-align: left;\n}\n.timeline .period .histo .line {\n flex-grow: 1;\n display: inline-block;\n background-color: #a6cdf5;\n margin: 0;\n padding: 0;\n}\n\n/* Last level period histogram spaces things evenly */\n.timeline .period.last-level .histo {\n justify-content: space-around;\n}\n\n/* Last level period histogram lines do not grow, but are fixed width/margin */\n.timeline .period.last-level .histo .line {\n flex-grow: unset;\n width: 5px;\n margin-left: 2px;\n\n position: relative;\n}\n\n /* update line color on hover*/\n.timeline .period.last-level .histo .line:hover {\n background-color: #f5a6eb;\n}\n\n /*Last level period histogram line has extra info*/\n.timeline .period.last-level .histo .line .snap-info {\n position: absolute;\n z-index: 10;\n top: 30%;\n left: 120%;\n display: none;\n background-color: white;\n border: 1px solid gray;\n padding: 2px;\n white-space: nowrap; /*no wrapping allowed*/\n}\n /*show on hover*/\n.timeline .period.last-level .histo .line:hover .snap-info {\n display: block;\n}\n\n", map: {"version":3,"sources":["/Users/ilya/core/pywb/pywb/vueui/src/components/Timeline.vue"],"names":[],"mappings":";AAoLA;IACA,kBAAA;IACA,aAAA;IACA,WAAA;IACA,YAAA;IACA,WAAA;IACA,qBAAA;AACA;AAEA;IACA,qBAAA;IACA,eAAA;AACA;AACA;IACA,qBAAA;IACA,WAAA;IACA,eAAA,EAAA,+CAAA;IACA,iBAAA;IACA,mBAAA;IACA,eAAA;AACA;AACA;AACA;AACA;AACA;AACA;IACA,gBAAA;IACA,6BAAA;IACA,mBAAA;AACA;AACA;IACA,8BAAA;IACA,gBAAA;AACA;AAEA;IACA,kBAAA;IACA,qBAAA;IACA,WAAA,EAAA,IAAA;IACA,YAAA;;IAEA,kCAAA;IACA,kBAAA;IACA,kBAAA;IACA,mBAAA;IACA,uBAAA;;IAEA,kBAAA;;IAEA,0CAAA;AACA;AACA,oBAAA;AACA;IACA,aAAA;AACA;AACA,iEAAA;AACA;IACA,yBAAA;AACA;AACA;IACA,aAAA;IACA,8BAAA;IACA,YAAA;IACA,WAAA;IACA,gBAAA;AACA;AAGA;IACA,YAAA;IACA,kBAAA;IACA,qBAAA;IACA,YAAA;IACA,0DAAA;IACA,mBAAA;IACA,mBAAA;IACA,kBAAA;IACA,0BAAA;IACA,+FAAA;IACA,eAAA;;IAEA,8CAAA;AACA;AACA,+BAAA;AACA;IACA,2FAAA;AACA;AAEA;IACA,yBAAA;AACA;;AAEA,iBAAA;AACA;IACA,WAAA;IACA,iCAAA;AACA;AACA,uBAAA;AACA;IACA,sBAAA;AACA;AAEA;IACA,iBAAA;IACA,eAAA;IACA,oCAAA;AACA;AACA;IACA,kBAAA;IACA,MAAA;IACA,OAAA;IACA,aAAA;IACA,WAAA;IACA,YAAA;IACA,mBAAA;IACA,kBAAA;IACA,eAAA;AACA;AACA;IACA,eAAA;IACA,WAAA;IACA,uCAAA;IACA,YAAA;IACA,kBAAA;AACA;AACA;IACA,cAAA;AACA;AACA;IACA,cAAA;IACA,kBAAA;IACA,SAAA;IACA,OAAA;IACA,WAAA;IACA,YAAA;IACA,uBAAA;IACA,0BAAA;AACA;AACA;IACA,gBAAA;AACA;AAEA;IACA,aAAA;IACA,kBAAA;IACA,QAAA;IACA,OAAA;IACA,WAAA;IACA,YAAA;IACA,qBAAA;IACA,8BAAA;IACA,gBAAA;AACA;AAEA;IACA,YAAA;IACA,qBAAA;IACA,yBAAA;IACA,SAAA;IACA,UAAA;AACA;;AAEA,qDAAA;AACA;IACA,6BAAA;AACA;;AAEA,8EAAA;AACA;IACA,gBAAA;IACA,UAAA;IACA,gBAAA;;IAEA,kBAAA;AACA;;IAEA,8BAAA;AACA;QACA,yBAAA;AACA;;IAEA,kDAAA;AACA;QACA,kBAAA;QACA,WAAA;QACA,QAAA;QACA,UAAA;QACA,aAAA;QACA,uBAAA;QACA,sBAAA;QACA,YAAA;QACA,mBAAA,EAAA,sBAAA;AACA;QACA,gBAAA;AACA;YACA,cAAA;AACA","file":"Timeline.vue","sourcesContent":["\n\n\n\n\n\n"]}, media: undefined }); }; /* scoped */ const __vue_scope_id__$4 = undefined; /* module identifier */ const __vue_module_identifier__$4 = undefined; /* functional template */ const __vue_is_functional_template__$4 = false; /* style inject SSR */ /* style inject shadow dom */ const __vue_component__$4 = /*#__PURE__*/normalizeComponent( { render: __vue_render__$4, staticRenderFns: __vue_staticRenderFns__$4 }, __vue_inject_styles__$4, __vue_script__$4, __vue_scope_id__$4, __vue_is_functional_template__$4, __vue_module_identifier__$4, false, createInjector, undefined, undefined ); // // // // // // // // // // // // // // // // // // var script$3 = { props: { period: { required: true } }, computed: { parents: function() { return this.period.getParents(); } }, methods: { changePeriod(period) { if (period.snapshotCount) { this.$emit("goto-period", period); } }, } }; /* script */ const __vue_script__$3 = script$3; /* template */ var __vue_render__$3 = function() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c( "div", { staticClass: "summary" }, [ _vm.parents.length ? [ _c("span", { staticClass: "item" }, [ _c( "span", { staticClass: "goto", on: { click: function($event) { return _vm.changePeriod(_vm.parents[0]) } } }, [_vm._v(_vm._s(_vm.parents[0].getReadableId(true)))] ) ]), _vm._v("\n >\n "), _vm._l(_vm.parents, function(parent, i) { return i > 0 ? _c("span", { key: parent.id, staticClass: "item" }, [ _c( "span", { staticClass: "goto", on: { click: function($event) { return _vm.changePeriod(parent) } } }, [_vm._v(_vm._s(parent.getReadableId(true)))] ) ]) : _vm._e() }) ] : _vm._e(), _vm._v(" "), _c("span", { staticClass: "item" }, [ _c("span", { staticClass: "current" }, [ _vm._v(_vm._s(_vm.period.getReadableId(true))) ]), _vm._v(" "), _c("span", { staticClass: "count" }, [ _vm._v("(" + _vm._s(_vm.period.snapshotCount) + " capture"), _vm.period.snapshotCount !== 1 ? _c("span", [_vm._v("s")]) : _vm._e(), _vm._v(")") ]) ]) ], 2 ) }; var __vue_staticRenderFns__$3 = []; __vue_render__$3._withStripped = true; /* style */ const __vue_inject_styles__$3 = function (inject) { if (!inject) return inject("data-v-05529944_0", { source: "\n.summary {\n display: inline-block;\n}\n.summary .item {\n position: relative;\n display: inline;\n margin: 0 2px 0 0;\n font-size: inherit;\n}\n.summary .count {\n vertical-align: middle;\n font-size: inherit;\n}\n.summary .count .verbose {\n display: none;\n}\n.summary .count:hover .verbose {\n display: inline;\n}\n.summary .item .goto {\n margin: 1px;\n cursor: pointer;\n color: darkslateblue;\n text-decoration: underline;\n}\n.summary .item .goto:hover {\n background-color: #a6cdf5;\n}\n.summary .item.snapshot {\n display: block;\n}\n\n", map: {"version":3,"sources":["/Users/ilya/core/pywb/pywb/vueui/src/components/Summary.vue"],"names":[],"mappings":";AAyCA;IACA,qBAAA;AACA;AAEA;IACA,kBAAA;IACA,eAAA;IACA,iBAAA;IACA,kBAAA;AACA;AACA;IACA,sBAAA;IACA,kBAAA;AACA;AACA;IACA,aAAA;AACA;AACA;IACA,eAAA;AACA;AAEA;IACA,WAAA;IACA,eAAA;IACA,oBAAA;IACA,0BAAA;AACA;AACA;IACA,yBAAA;AACA;AACA;IACA,cAAA;AACA","file":"Summary.vue","sourcesContent":["\n\n\n\n"]}, media: undefined }); }; /* scoped */ const __vue_scope_id__$3 = undefined; /* module identifier */ const __vue_module_identifier__$3 = undefined; /* functional template */ const __vue_is_functional_template__$3 = false; /* style inject SSR */ /* style inject shadow dom */ const __vue_component__$3 = /*#__PURE__*/normalizeComponent( { render: __vue_render__$3, staticRenderFns: __vue_staticRenderFns__$3 }, __vue_inject_styles__$3, __vue_script__$3, __vue_scope_id__$3, __vue_is_functional_template__$3, __vue_module_identifier__$3, false, createInjector, undefined, undefined ); // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // var script$2 = { props: ["month", "year", "isCurrent"], data: function() { return { maxInDay: 0, daySize: 30, }; }, computed: { dayStyle() { const s = this.daySize; return `height: ${s}px; width: ${s}px; line-height: ${s}px`; }, days() { if (!this.month || !this.month.snapshotCount) { return []; } const days = []; // Get days in month, and days in the complete weeks before first day and after last day const [firstDay, lastDay] = this.month.getChildrenRange(); const daysBeforeFirst = (new Date(this.year.id, this.month.id-1, firstDay)).getDay(); const daysAfterLastDay = (6 - (new Date(this.year.id, this.month.id-1, lastDay)).getDay()); for(let i=0; i h3 {\n margin: 0;\n font-size: 16px;\n}\n.calendar-month > .empty {\n position: absolute;\n top: 45%;\n width: 100%;\n color: gray;\n}\n.calendar-month .day {\n position: relative;\n display: inline-block;\n margin: 0;\n text-align: center;\n}\n.calendar-month .day.empty {\n color: gray;\n}\n.calendar-month .day .count {\n display: none;\n position: absolute;\n bottom: 80%;\n left: 80%;\n line-height: 1; /* reset to normal */\n padding: 3px;\n border-radius: 10px;\n border-bottom-left-radius: 0;\n border: 1px solid gray;\n background-color: white;\n z-index: 30;\n white-space: nowrap;\n}\n.calendar-month .day:hover .count {\n display: block;\n}\n.calendar-month .day .size {\n position: absolute;\n box-sizing: border-box;\n background-color: rgba(166, 205, 245, .85);\n z-index: 10;\n}\n.calendar-month .day .day-id {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 11;\n\n display: inline-block;\n width: 100%;\n text-align: center;\n\n color: black;\n}\n.calendar-month .day:hover .size {\n border: 1px solid black;\n}\n.calendar-month .day:hover {\n cursor: zoom-in;\n}\n", map: {"version":3,"sources":["/Users/ilya/core/pywb/pywb/vueui/src/components/CalendarMonth.vue"],"names":[],"mappings":";AACA;IACA,kBAAA;IACA,qBAAA;IACA,YAAA;IACA,SAAA;IACA,aAAA;IACA,YAAA;IACA,kBAAA;IACA,mBAAA;AACA;AACA;IACA,yBAAA;IACA,mBAAA;AACA;AACA;IACA,yBAAA;IACA,kBAAA;AACA;AACA;IACA,SAAA;IACA,eAAA;AACA;AACA;IACA,kBAAA;IACA,QAAA;IACA,WAAA;IACA,WAAA;AACA;AACA;IACA,kBAAA;IACA,qBAAA;IACA,SAAA;IACA,kBAAA;AACA;AACA;IACA,WAAA;AACA;AACA;IACA,aAAA;IACA,kBAAA;IACA,WAAA;IACA,SAAA;IACA,cAAA,EAAA,oBAAA;IACA,YAAA;IACA,mBAAA;IACA,4BAAA;IACA,sBAAA;IACA,uBAAA;IACA,WAAA;IACA,mBAAA;AACA;AACA;IACA,cAAA;AACA;AACA;IACA,kBAAA;IACA,sBAAA;IACA,0CAAA;IACA,WAAA;AACA;AACA;IACA,kBAAA;IACA,MAAA;IACA,OAAA;IACA,WAAA;;IAEA,qBAAA;IACA,WAAA;IACA,kBAAA;;IAEA,YAAA;AACA;AACA;IACA,uBAAA;AACA;AACA;IACA,eAAA;AACA","file":"CalendarMonth.vue","sourcesContent":["\n\n\n\n\n\n"]}, media: undefined }); }; /* scoped */ const __vue_scope_id__$2 = undefined; /* module identifier */ const __vue_module_identifier__$2 = undefined; /* functional template */ const __vue_is_functional_template__$2 = false; /* style inject SSR */ /* style inject shadow dom */ const __vue_component__$2 = /*#__PURE__*/normalizeComponent( { render: __vue_render__$2, staticRenderFns: __vue_staticRenderFns__$2 }, __vue_inject_styles__$2, __vue_script__$2, __vue_scope_id__$2, __vue_is_functional_template__$2, __vue_module_identifier__$2, false, createInjector, undefined, undefined ); // var script$1 = { components: {CalendarMonth: __vue_component__$2}, props: ["period"], data: function() { return {}; }, computed: { year() { let year = null; if (this.period.type === PywbPeriod.Type.all) { year = this.period.children[this.period.children.length-1]; } else if (this.period.type === PywbPeriod.Type.year) { year = this.period; } else { year = this.period.getParents().filter(p => p.type === PywbPeriod.Type.year)[0]; } if (year) { year.fillEmptyChildPeriods(true); } return year; }, currentMonth() { let month = null; if (this.period.type === PywbPeriod.Type.month) { month = this.period; } else { month = this.period.getParents().filter(p => p.type === PywbPeriod.Type.month)[0]; } return month; } } }; /* script */ const __vue_script__$1 = script$1; /* template */ var __vue_render__$1 = function() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c("div", { staticClass: "full-view" }, [ _c("h2", [ _vm._v( _vm._s(_vm.year.snapshotCount) + " captures in " + _vm._s(_vm.year.id) ) ]), _vm._v(" "), _c( "div", { staticClass: "months" }, _vm._l(_vm.year.children, function(month) { return _c("CalendarMonth", { key: month.id, attrs: { month: month, year: _vm.year, "is-current": month === _vm.currentMonth }, on: { "goto-period": function($event) { return _vm.$emit("goto-period", $event) } } }) }), 1 ) ]) }; var __vue_staticRenderFns__$1 = []; __vue_render__$1._withStripped = true; /* style */ const __vue_inject_styles__$1 = function (inject) { if (!inject) return inject("data-v-cecde690_0", { source: "\n.full-view {\n position: absolute;\n top: 130px;\n left: 0;\n height: 80vh;\n width: 100%;\n background-color: white;\n}\n.full-view .months {\n display: flex;\n justify-content: center;\n flex-wrap: wrap;\n align-items: flex-start;\n}\n.full-view h2 {\n margin: 10px 0;\n font-size: 20px;\n text-align: center;\n}\n", map: {"version":3,"sources":["/Users/ilya/core/pywb/pywb/vueui/src/components/CalendarYear.vue"],"names":[],"mappings":";AACA;IACA,kBAAA;IACA,UAAA;IACA,OAAA;IACA,YAAA;IACA,WAAA;IACA,uBAAA;AACA;AACA;IACA,aAAA;IACA,uBAAA;IACA,eAAA;IACA,uBAAA;AACA;AAEA;IACA,cAAA;IACA,eAAA;IACA,kBAAA;AACA","file":"CalendarYear.vue","sourcesContent":["\n\n\n\n\n\n"]}, media: undefined }); }; /* scoped */ const __vue_scope_id__$1 = undefined; /* module identifier */ const __vue_module_identifier__$1 = undefined; /* functional template */ const __vue_is_functional_template__$1 = false; /* style inject SSR */ /* style inject shadow dom */ const __vue_component__$1 = /*#__PURE__*/normalizeComponent( { render: __vue_render__$1, staticRenderFns: __vue_staticRenderFns__$1 }, __vue_inject_styles__$1, __vue_script__$1, __vue_scope_id__$1, __vue_is_functional_template__$1, __vue_module_identifier__$1, false, createInjector, undefined, undefined ); // var script = { name: "PywbReplayApp", //el: '[data-app="webrecorder-replay-app"]', data: function() { return { snapshots: [], currentPeriod: null, currentSnapshot: null, msgs: [], showFullView: false, config: { title: "", initialView: {} }, timelineHighlight: false }; }, components: {Timeline: __vue_component__$4, TimelineSummary: __vue_component__$3, CalendarYear: __vue_component__$1}, mounted: function() { this.init(); }, methods: { gotoPeriod: function(newPeriod, initiator) { if (this.timelineHighlight) { setTimeout((() => { this.timelineHighlight=false; }).bind(this), 3000); } if (newPeriod.snapshot) { this.gotoSnapshot(newPeriod.snapshot); } else { this.currentPeriod = newPeriod; } }, gotoSnapshot(snapshot) { this.currentSnapshot = snapshot; // COMMUNICATE TO ContentFrame this.$emit("show-snapshot", snapshot); this.showFullView = false; }, init() { if (!this.config.title) { this.config.title = this.config.initialView.url; } if (this.config.initialView.timestamp === undefined) { this.showFullView = true; } else { this.showFullView = false; this.setSnapshot(this.config.initialView); } }, setSnapshot(view) { // convert to snapshot objec to support proper rendering of time/date const snapshot = new PywbSnapshot(view, 0); this.config.title = view.url; this.gotoSnapshot(snapshot); } } }; /* script */ const __vue_script__ = script; /* template */ var __vue_render__ = function() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c( "div", { staticClass: "app", attrs: { "data-app": "webrecorder-replay-app" } }, [ _c("div", { staticClass: "short-nav" }, [ _c("div", { staticClass: "first-line" }, [ _c("div", { staticClass: "logo" }, [ _c("img", { attrs: { src: _vm.config.logoImg } }) ]), _vm._v(" "), _c( "div", { staticClass: "url-and-timeline" }, [ _c( "div", { staticClass: "url" }, [ _c("strong", [_vm._v(_vm._s(_vm.config.title))]), _vm._v( " (" + _vm._s(_vm.snapshots.length) + " captures: " + _vm._s(_vm.snapshots[0].getDateFormatted()) + " - " + _vm._s( _vm.snapshots[ _vm.snapshots.length - 1 ].getDateFormatted() ) + ")" ), _c("br"), _vm._v(" "), _vm.currentPeriod ? _c("TimelineSummary", { attrs: { period: _vm.currentPeriod }, on: { "goto-period": _vm.gotoPeriod } }) : _vm._e(), _vm._v(" "), _c( "span", { staticClass: "full-view-toggle", class: { expanded: _vm.showFullView }, on: { click: function($event) { _vm.showFullView = !_vm.showFullView; } } }, [ !_vm.showFullView ? [ _c("span", { staticClass: "detail" }, [ _vm._v("show year calendar") ]) ] : [ _c("span", { staticClass: "detail" }, [ _vm._v("hide year calendar") ]) ], _vm._v(" "), _c("img", { attrs: { src: "/static/calendar-icon.png" } }) ], 2 ) ], 1 ), _vm._v(" "), _vm.currentPeriod ? _c("Timeline", { attrs: { period: _vm.currentPeriod, highlight: _vm.timelineHighlight }, on: { "goto-period": _vm.gotoPeriod } }) : _vm._e() ], 1 ) ]), _vm._v(" "), _vm.currentSnapshot && !_vm.showFullView ? _c("div", { staticClass: "second-line" }, [ _c("h2", [ _vm._v( "Showing Capture from " + _vm._s(_vm.currentSnapshot.getTimeDateFormatted()) ) ]) ]) : _vm._e() ]), _vm._v(" "), _vm.showFullView ? _c("CalendarYear", { attrs: { period: _vm.currentPeriod }, on: { "goto-period": _vm.gotoPeriod } }) : _vm._e() ], 1 ) }; var __vue_staticRenderFns__ = []; __vue_render__._withStripped = true; /* style */ const __vue_inject_styles__ = function (inject) { if (!inject) return inject("data-v-082e46ee_0", { source: "\n.app {\n border-bottom: 1px solid lightcoral;\n height: 150px;\n width: 100%;\n}\n.iframe iframe {\n width: 100%;\n height: 80vh;\n}\n.logo {\n margin-right: 30px;\n width: 180px;\n}\n.short-nav {\n width: 100%;\n position: relative;\n}\n.short-nav .first-line {\n display: flex;\n justify-content: flex-start;\n}\n.short-nav .second-line {\n display: flex;\n justify-content: flex-start;\n}\n.short-nav .logo {\n flex-shrink: initial;\n}\n.short-nav .url-and-timeline {\n flex-grow: 2;\n overflow-x: hidden;\n}\n.short-nav .url {\n text-align: left;\n margin: 0 25px;\n position: relative;\n}\n.full-view-toggle {\n position: absolute;\n top: 0;\n right: 0;\n border-radius: 5px;\n padding: 4px;\n cursor: zoom-in;\n}\n.full-view-toggle img {\n width: 17px;\n display: inline-block;\n margin-top: 2px;\n}\n.full-view-toggle:hover {\n background-color: #eeeeee;\n}\n.full-view-toggle .detail {\n display: none;\n}\n.full-view-toggle:hover .detail {\n display: inline;\n}\n.full-view-toggle.expanded {\n background-color: #eeeeee;\n cursor: zoom-out;\n}\n", map: {"version":3,"sources":["/Users/ilya/core/pywb/pywb/vueui/src/App.vue"],"names":[],"mappings":";AA2GA;EACA,mCAAA;EACA,aAAA;EACA,WAAA;AACA;AACA;EACA,WAAA;EACA,YAAA;AACA;AACA;EACA,kBAAA;EACA,YAAA;AACA;AACA;EACA,WAAA;EACA,kBAAA;AACA;AACA;EACA,aAAA;EACA,2BAAA;AACA;AACA;EACA,aAAA;EACA,2BAAA;AACA;AAEA;EACA,oBAAA;AACA;AAEA;EACA,YAAA;EACA,kBAAA;AACA;AAEA;EACA,gBAAA;EACA,cAAA;EACA,kBAAA;AACA;AAEA;EACA,kBAAA;EACA,MAAA;EACA,QAAA;EACA,kBAAA;EACA,YAAA;EACA,eAAA;AACA;AACA;EACA,WAAA;EACA,qBAAA;EACA,eAAA;AACA;AACA;EACA,yBAAA;AACA;AACA;EACA,aAAA;AACA;AACA;EACA,eAAA;AACA;AACA;EACA,yBAAA;EACA,gBAAA;AACA","file":"App.vue","sourcesContent":["\n\n\n\n\n"]}, media: undefined }); }; /* scoped */ const __vue_scope_id__ = undefined; /* module identifier */ const __vue_module_identifier__ = undefined; /* functional template */ const __vue_is_functional_template__ = false; /* style inject SSR */ /* style inject shadow dom */ const __vue_component__ = /*#__PURE__*/normalizeComponent( { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ }, __vue_inject_styles__, __vue_script__, __vue_scope_id__, __vue_is_functional_template__, __vue_module_identifier__, false, createInjector, undefined, undefined ); /*! * Vue.js v2.6.14 * (c) 2014-2021 Evan You * Released under the MIT License. */ /* */ const emptyObject = Object.freeze({}); // These helpers produce better VM code in JS engines due to their // explicitness and function inlining. function isUndef (v) { return v === undefined || v === null } function isDef (v) { return v !== undefined && v !== null } function isTrue (v) { return v === true } function isFalse (v) { return v === false } /** * Check if value is primitive. */ function isPrimitive (value) { return ( typeof value === 'string' || typeof value === 'number' || // $flow-disable-line typeof value === 'symbol' || typeof value === 'boolean' ) } /** * Quick object check - this is primarily used to tell * Objects from primitive values when we know the value * is a JSON-compliant type. */ function isObject (obj) { return obj !== null && typeof obj === 'object' } /** * Get the raw type string of a value, e.g., [object Object]. */ const _toString = Object.prototype.toString; function toRawType (value) { return _toString.call(value).slice(8, -1) } /** * Strict object type check. Only returns true * for plain JavaScript objects. */ function isPlainObject (obj) { return _toString.call(obj) === '[object Object]' } function isRegExp (v) { return _toString.call(v) === '[object RegExp]' } /** * Check if val is a valid array index. */ function isValidArrayIndex (val) { const n = parseFloat(String(val)); return n >= 0 && Math.floor(n) === n && isFinite(val) } function isPromise (val) { return ( isDef(val) && typeof val.then === 'function' && typeof val.catch === 'function' ) } /** * Convert a value to a string that is actually rendered. */ function toString (val) { return val == null ? '' : Array.isArray(val) || (isPlainObject(val) && val.toString === _toString) ? JSON.stringify(val, null, 2) : String(val) } /** * Convert an input value to a number for persistence. * If the conversion fails, return original string. */ function toNumber (val) { const n = parseFloat(val); return isNaN(n) ? val : n } /** * Make a map and return a function for checking if a key * is in that map. */ function makeMap ( str, expectsLowerCase ) { const map = Object.create(null); const list = str.split(','); for (let i = 0; i < list.length; i++) { map[list[i]] = true; } return expectsLowerCase ? val => map[val.toLowerCase()] : val => map[val] } /** * Check if a tag is a built-in tag. */ const isBuiltInTag = makeMap('slot,component', true); /** * Check if an attribute is a reserved attribute. */ const isReservedAttribute = makeMap('key,ref,slot,slot-scope,is'); /** * Remove an item from an array. */ function remove (arr, item) { if (arr.length) { const index = arr.indexOf(item); if (index > -1) { return arr.splice(index, 1) } } } /** * Check whether an object has the property. */ const hasOwnProperty = Object.prototype.hasOwnProperty; function hasOwn (obj, key) { return hasOwnProperty.call(obj, key) } /** * Create a cached version of a pure function. */ function cached (fn) { const cache = Object.create(null); return (function cachedFn (str) { const hit = cache[str]; return hit || (cache[str] = fn(str)) }) } /** * Camelize a hyphen-delimited string. */ const camelizeRE = /-(\w)/g; const camelize = cached((str) => { return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '') }); /** * Capitalize a string. */ const capitalize = cached((str) => { return str.charAt(0).toUpperCase() + str.slice(1) }); /** * Hyphenate a camelCase string. */ const hyphenateRE = /\B([A-Z])/g; const hyphenate = cached((str) => { return str.replace(hyphenateRE, '-$1').toLowerCase() }); /** * Simple bind polyfill for environments that do not support it, * e.g., PhantomJS 1.x. Technically, we don't need this anymore * since native bind is now performant enough in most browsers. * But removing it would mean breaking code that was able to run in * PhantomJS 1.x, so this must be kept for backward compatibility. */ /* istanbul ignore next */ function polyfillBind (fn, ctx) { function boundFn (a) { const l = arguments.length; return l ? l > 1 ? fn.apply(ctx, arguments) : fn.call(ctx, a) : fn.call(ctx) } boundFn._length = fn.length; return boundFn } function nativeBind (fn, ctx) { return fn.bind(ctx) } const bind = Function.prototype.bind ? nativeBind : polyfillBind; /** * Convert an Array-like object to a real Array. */ function toArray (list, start) { start = start || 0; let i = list.length - start; const ret = new Array(i); while (i--) { ret[i] = list[i + start]; } return ret } /** * Mix properties into target object. */ function extend (to, _from) { for (const key in _from) { to[key] = _from[key]; } return to } /** * Merge an Array of Objects into a single Object. */ function toObject (arr) { const res = {}; for (let i = 0; i < arr.length; i++) { if (arr[i]) { extend(res, arr[i]); } } return res } /* eslint-disable no-unused-vars */ /** * Perform no operation. * Stubbing args to make Flow happy without leaving useless transpiled code * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/). */ function noop (a, b, c) {} /** * Always return false. */ const no = (a, b, c) => false; /* eslint-enable no-unused-vars */ /** * Return the same value. */ const identity = (_) => _; /** * Generate a string containing static keys from compiler modules. */ function genStaticKeys (modules) { return modules.reduce((keys, m) => { return keys.concat(m.staticKeys || []) }, []).join(',') } /** * Check if two values are loosely equal - that is, * if they are plain objects, do they have the same shape? */ function looseEqual (a, b) { if (a === b) return true const isObjectA = isObject(a); const isObjectB = isObject(b); if (isObjectA && isObjectB) { try { const isArrayA = Array.isArray(a); const isArrayB = Array.isArray(b); if (isArrayA && isArrayB) { return a.length === b.length && a.every((e, i) => { return looseEqual(e, b[i]) }) } else if (a instanceof Date && b instanceof Date) { return a.getTime() === b.getTime() } else if (!isArrayA && !isArrayB) { const keysA = Object.keys(a); const keysB = Object.keys(b); return keysA.length === keysB.length && keysA.every(key => { return looseEqual(a[key], b[key]) }) } else { /* istanbul ignore next */ return false } } catch (e) { /* istanbul ignore next */ return false } } else if (!isObjectA && !isObjectB) { return String(a) === String(b) } else { return false } } /** * Return the first index at which a loosely equal value can be * found in the array (if value is a plain object, the array must * contain an object of the same shape), or -1 if it is not present. */ function looseIndexOf (arr, val) { for (let i = 0; i < arr.length; i++) { if (looseEqual(arr[i], val)) return i } return -1 } /** * Ensure a function is called only once. */ function once (fn) { let called = false; return function () { if (!called) { called = true; fn.apply(this, arguments); } } } const SSR_ATTR = 'data-server-rendered'; const ASSET_TYPES = [ 'component', 'directive', 'filter' ]; const LIFECYCLE_HOOKS = [ 'beforeCreate', 'created', 'beforeMount', 'mounted', 'beforeUpdate', 'updated', 'beforeDestroy', 'destroyed', 'activated', 'deactivated', 'errorCaptured', 'serverPrefetch' ]; /* */ var config = ({ /** * Option merge strategies (used in core/util/options) */ // $flow-disable-line optionMergeStrategies: Object.create(null), /** * Whether to suppress warnings. */ silent: false, /** * Show production mode tip message on boot? */ productionTip: "development" !== 'production', /** * Whether to enable devtools */ devtools: "development" !== 'production', /** * Whether to record perf */ performance: false, /** * Error handler for watcher errors */ errorHandler: null, /** * Warn handler for watcher warns */ warnHandler: null, /** * Ignore certain custom elements */ ignoredElements: [], /** * Custom user key aliases for v-on */ // $flow-disable-line keyCodes: Object.create(null), /** * Check if a tag is reserved so that it cannot be registered as a * component. This is platform-dependent and may be overwritten. */ isReservedTag: no, /** * Check if an attribute is reserved so that it cannot be used as a component * prop. This is platform-dependent and may be overwritten. */ isReservedAttr: no, /** * Check if a tag is an unknown element. * Platform-dependent. */ isUnknownElement: no, /** * Get the namespace of an element */ getTagNamespace: noop, /** * Parse the real tag name for the specific platform. */ parsePlatformTagName: identity, /** * Check if an attribute must be bound using property, e.g. value * Platform-dependent. */ mustUseProp: no, /** * Perform updates asynchronously. Intended to be used by Vue Test Utils * This will significantly reduce performance if set to false. */ async: true, /** * Exposed for legacy reasons */ _lifecycleHooks: LIFECYCLE_HOOKS }); /* */ /** * unicode letters used for parsing html tags, component names and property paths. * using https://www.w3.org/TR/html53/semantics-scripting.html#potentialcustomelementname * skipping \u10000-\uEFFFF due to it freezing up PhantomJS */ const unicodeRegExp = /a-zA-Z\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD/; /** * Check if a string starts with $ or _ */ function isReserved (str) { const c = (str + '').charCodeAt(0); return c === 0x24 || c === 0x5F } /** * Define a property. */ function def (obj, key, val, enumerable) { Object.defineProperty(obj, key, { value: val, enumerable: !!enumerable, writable: true, configurable: true }); } /** * Parse simple path. */ const bailRE = new RegExp(`[^${unicodeRegExp.source}.$_\\d]`); function parsePath (path) { if (bailRE.test(path)) { return } const segments = path.split('.'); return function (obj) { for (let i = 0; i < segments.length; i++) { if (!obj) return obj = obj[segments[i]]; } return obj } } /* */ // can we use __proto__? const hasProto = '__proto__' in {}; // Browser environment sniffing const inBrowser = typeof window !== 'undefined'; const inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform; const weexPlatform = inWeex && WXEnvironment.platform.toLowerCase(); const UA = inBrowser && window.navigator.userAgent.toLowerCase(); const isIE = UA && /msie|trident/.test(UA); const isIE9 = UA && UA.indexOf('msie 9.0') > 0; const isEdge = UA && UA.indexOf('edge/') > 0; (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android'); const isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios'); UA && /chrome\/\d+/.test(UA) && !isEdge; UA && /phantomjs/.test(UA); const isFF = UA && UA.match(/firefox\/(\d+)/); // Firefox has a "watch" function on Object.prototype... const nativeWatch = ({}).watch; let supportsPassive = false; if (inBrowser) { try { const opts = {}; Object.defineProperty(opts, 'passive', ({ get () { /* istanbul ignore next */ supportsPassive = true; } })); // https://github.com/facebook/flow/issues/285 window.addEventListener('test-passive', null, opts); } catch (e) {} } // this needs to be lazy-evaled because vue may be required before // vue-server-renderer can set VUE_ENV let _isServer; const isServerRendering = () => { if (_isServer === undefined) { /* istanbul ignore if */ if (!inBrowser && !inWeex && typeof global !== 'undefined') { // detect presence of vue-server-renderer and avoid // Webpack shimming the process _isServer = global['process'] && global['process'].env.VUE_ENV === 'server'; } else { _isServer = false; } } return _isServer }; // detect devtools const devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__; /* istanbul ignore next */ function isNative (Ctor) { return typeof Ctor === 'function' && /native code/.test(Ctor.toString()) } const hasSymbol = typeof Symbol !== 'undefined' && isNative(Symbol) && typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys); let _Set; /* istanbul ignore if */ // $flow-disable-line if (typeof Set !== 'undefined' && isNative(Set)) { // use native Set when available. _Set = Set; } else { // a non-standard Set polyfill that only works with primitive keys. _Set = class Set { constructor () { this.set = Object.create(null); } has (key) { return this.set[key] === true } add (key) { this.set[key] = true; } clear () { this.set = Object.create(null); } }; } /* */ let warn = noop; let tip = noop; let generateComponentTrace = (noop); // work around flow check let formatComponentName = (noop); { const hasConsole = typeof console !== 'undefined'; const classifyRE = /(?:^|[-_])(\w)/g; const classify = str => str .replace(classifyRE, c => c.toUpperCase()) .replace(/[-_]/g, ''); warn = (msg, vm) => { const trace = vm ? generateComponentTrace(vm) : ''; if (config.warnHandler) { config.warnHandler.call(null, msg, vm, trace); } else if (hasConsole && (!config.silent)) { console.error(`[Vue warn]: ${msg}${trace}`); } }; tip = (msg, vm) => { if (hasConsole && (!config.silent)) { console.warn(`[Vue tip]: ${msg}` + ( vm ? generateComponentTrace(vm) : '' )); } }; formatComponentName = (vm, includeFile) => { if (vm.$root === vm) { return '' } const options = typeof vm === 'function' && vm.cid != null ? vm.options : vm._isVue ? vm.$options || vm.constructor.options : vm; let name = options.name || options._componentTag; const file = options.__file; if (!name && file) { const match = file.match(/([^/\\]+)\.vue$/); name = match && match[1]; } return ( (name ? `<${classify(name)}>` : ``) + (file && includeFile !== false ? ` at ${file}` : '') ) }; const repeat = (str, n) => { let res = ''; while (n) { if (n % 2 === 1) res += str; if (n > 1) str += str; n >>= 1; } return res }; generateComponentTrace = vm => { if (vm._isVue && vm.$parent) { const tree = []; let currentRecursiveSequence = 0; while (vm) { if (tree.length > 0) { const last = tree[tree.length - 1]; if (last.constructor === vm.constructor) { currentRecursiveSequence++; vm = vm.$parent; continue } else if (currentRecursiveSequence > 0) { tree[tree.length - 1] = [last, currentRecursiveSequence]; currentRecursiveSequence = 0; } } tree.push(vm); vm = vm.$parent; } return '\n\nfound in\n\n' + tree .map((vm, i) => `${ i === 0 ? '---> ' : repeat(' ', 5 + i * 2) }${ Array.isArray(vm) ? `${formatComponentName(vm[0])}... (${vm[1]} recursive calls)` : formatComponentName(vm) }`) .join('\n') } else { return `\n\n(found in ${formatComponentName(vm)})` } }; } /* */ let uid = 0; /** * A dep is an observable that can have multiple * directives subscribing to it. */ class Dep { constructor () { this.id = uid++; this.subs = []; } addSub (sub) { this.subs.push(sub); } removeSub (sub) { remove(this.subs, sub); } depend () { if (Dep.target) { Dep.target.addDep(this); } } notify () { // stabilize the subscriber list first const subs = this.subs.slice(); if (!config.async) { // subs aren't sorted in scheduler if not running async // we need to sort them now to make sure they fire in correct // order subs.sort((a, b) => a.id - b.id); } for (let i = 0, l = subs.length; i < l; i++) { subs[i].update(); } } } // The current target watcher being evaluated. // This is globally unique because only one watcher // can be evaluated at a time. Dep.target = null; const targetStack = []; function pushTarget (target) { targetStack.push(target); Dep.target = target; } function popTarget () { targetStack.pop(); Dep.target = targetStack[targetStack.length - 1]; } /* */ class VNode { // rendered in this component's scope // component instance // component placeholder node // strictly internal // contains raw HTML? (server only) // hoisted static node // necessary for enter transition check // empty comment placeholder? // is a cloned node? // is a v-once node? // async component factory function // real context vm for functional nodes // for SSR caching // used to store functional render context for devtools // functional scope id support constructor ( tag, data, children, text, elm, context, componentOptions, asyncFactory ) { this.tag = tag; this.data = data; this.children = children; this.text = text; this.elm = elm; this.ns = undefined; this.context = context; this.fnContext = undefined; this.fnOptions = undefined; this.fnScopeId = undefined; this.key = data && data.key; this.componentOptions = componentOptions; this.componentInstance = undefined; this.parent = undefined; this.raw = false; this.isStatic = false; this.isRootInsert = true; this.isComment = false; this.isCloned = false; this.isOnce = false; this.asyncFactory = asyncFactory; this.asyncMeta = undefined; this.isAsyncPlaceholder = false; } // DEPRECATED: alias for componentInstance for backwards compat. /* istanbul ignore next */ get child () { return this.componentInstance } } const createEmptyVNode = (text = '') => { const node = new VNode(); node.text = text; node.isComment = true; return node }; function createTextVNode (val) { return new VNode(undefined, undefined, undefined, String(val)) } // optimized shallow clone // used for static nodes and slot nodes because they may be reused across // multiple renders, cloning them avoids errors when DOM manipulations rely // on their elm reference. function cloneVNode (vnode) { const cloned = new VNode( vnode.tag, vnode.data, // #7975 // clone children array to avoid mutating original in case of cloning // a child. vnode.children && vnode.children.slice(), vnode.text, vnode.elm, vnode.context, vnode.componentOptions, vnode.asyncFactory ); cloned.ns = vnode.ns; cloned.isStatic = vnode.isStatic; cloned.key = vnode.key; cloned.isComment = vnode.isComment; cloned.fnContext = vnode.fnContext; cloned.fnOptions = vnode.fnOptions; cloned.fnScopeId = vnode.fnScopeId; cloned.asyncMeta = vnode.asyncMeta; cloned.isCloned = true; return cloned } /* * not type checking this file because flow doesn't play well with * dynamically accessing methods on Array prototype */ const arrayProto = Array.prototype; const arrayMethods = Object.create(arrayProto); const methodsToPatch = [ 'push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse' ]; /** * Intercept mutating methods and emit events */ methodsToPatch.forEach(function (method) { // cache original method const original = arrayProto[method]; def(arrayMethods, method, function mutator (...args) { const result = original.apply(this, args); const ob = this.__ob__; let inserted; switch (method) { case 'push': case 'unshift': inserted = args; break case 'splice': inserted = args.slice(2); break } if (inserted) ob.observeArray(inserted); // notify change ob.dep.notify(); return result }); }); /* */ const arrayKeys = Object.getOwnPropertyNames(arrayMethods); /** * In some cases we may want to disable observation inside a component's * update computation. */ let shouldObserve = true; function toggleObserving (value) { shouldObserve = value; } /** * Observer class that is attached to each observed * object. Once attached, the observer converts the target * object's property keys into getter/setters that * collect dependencies and dispatch updates. */ class Observer { // number of vms that have this object as root $data constructor (value) { this.value = value; this.dep = new Dep(); this.vmCount = 0; def(value, '__ob__', this); if (Array.isArray(value)) { if (hasProto) { protoAugment(value, arrayMethods); } else { copyAugment(value, arrayMethods, arrayKeys); } this.observeArray(value); } else { this.walk(value); } } /** * Walk through all properties and convert them into * getter/setters. This method should only be called when * value type is Object. */ walk (obj) { const keys = Object.keys(obj); for (let i = 0; i < keys.length; i++) { defineReactive$$1(obj, keys[i]); } } /** * Observe a list of Array items. */ observeArray (items) { for (let i = 0, l = items.length; i < l; i++) { observe(items[i]); } } } // helpers /** * Augment a target Object or Array by intercepting * the prototype chain using __proto__ */ function protoAugment (target, src) { /* eslint-disable no-proto */ target.__proto__ = src; /* eslint-enable no-proto */ } /** * Augment a target Object or Array by defining * hidden properties. */ /* istanbul ignore next */ function copyAugment (target, src, keys) { for (let i = 0, l = keys.length; i < l; i++) { const 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. */ function observe (value, asRootData) { if (!isObject(value) || value instanceof VNode) { return } let ob; if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { ob = value.__ob__; } else if ( shouldObserve && !isServerRendering() && (Array.isArray(value) || isPlainObject(value)) && Object.isExtensible(value) && !value._isVue ) { ob = new Observer(value); } if (asRootData && ob) { ob.vmCount++; } return ob } /** * Define a reactive property on an Object. */ function defineReactive$$1 ( obj, key, val, customSetter, shallow ) { const dep = new Dep(); const property = Object.getOwnPropertyDescriptor(obj, key); if (property && property.configurable === false) { return } // cater for pre-defined getter/setters const getter = property && property.get; const setter = property && property.set; if ((!getter || setter) && arguments.length === 2) { val = obj[key]; } let childOb = !shallow && observe(val); Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: function reactiveGetter () { const value = getter ? getter.call(obj) : val; if (Dep.target) { dep.depend(); if (childOb) { childOb.dep.depend(); if (Array.isArray(value)) { dependArray(value); } } } return value }, set: function reactiveSetter (newVal) { const value = getter ? getter.call(obj) : val; /* eslint-disable no-self-compare */ if (newVal === value || (newVal !== newVal && value !== value)) { return } /* eslint-enable no-self-compare */ if (customSetter) { customSetter(); } // #7981: for accessor properties without setter if (getter && !setter) return if (setter) { setter.call(obj, newVal); } else { val = newVal; } childOb = !shallow && observe(newVal); dep.notify(); } }); } /** * Set a property on an object. Adds the new property and * triggers change notification if the property doesn't * already exist. */ function set (target, key, val) { if (isUndef(target) || isPrimitive(target) ) { warn(`Cannot set reactive property on undefined, null, or primitive value: ${(target)}`); } if (Array.isArray(target) && isValidArrayIndex(key)) { target.length = Math.max(target.length, key); target.splice(key, 1, val); return val } if (key in target && !(key in Object.prototype)) { target[key] = val; return val } const ob = (target).__ob__; if (target._isVue || (ob && ob.vmCount)) { warn( 'Avoid adding reactive properties to a Vue instance or its root $data ' + 'at runtime - declare it upfront in the data option.' ); return val } if (!ob) { target[key] = val; return val } defineReactive$$1(ob.value, key, val); ob.dep.notify(); return val } /** * Delete a property and trigger change if necessary. */ function del (target, key) { if (isUndef(target) || isPrimitive(target) ) { warn(`Cannot delete reactive property on undefined, null, or primitive value: ${(target)}`); } if (Array.isArray(target) && isValidArrayIndex(key)) { target.splice(key, 1); return } const ob = (target).__ob__; if (target._isVue || (ob && ob.vmCount)) { warn( 'Avoid deleting properties on a Vue instance or its root $data ' + '- just set it to null.' ); return } if (!hasOwn(target, key)) { return } delete target[key]; if (!ob) { return } ob.dep.notify(); } /** * Collect dependencies on array elements when the array is touched, since * we cannot intercept array element access like property getters. */ function dependArray (value) { for (let e, i = 0, l = value.length; i < l; i++) { e = value[i]; e && e.__ob__ && e.__ob__.dep.depend(); if (Array.isArray(e)) { dependArray(e); } } } /* */ /** * Option overwriting strategies are functions that handle * how to merge a parent option value and a child option * value into the final value. */ const strats = config.optionMergeStrategies; /** * Options with restrictions */ { strats.el = strats.propsData = function (parent, child, vm, key) { if (!vm) { warn( `option "${key}" can only be used during instance ` + 'creation with the `new` keyword.' ); } return defaultStrat(parent, child) }; } /** * Helper that recursively merges two data objects together. */ function mergeData (to, from) { if (!from) return to let key, toVal, fromVal; const keys = hasSymbol ? Reflect.ownKeys(from) : Object.keys(from); for (let i = 0; i < keys.length; i++) { key = keys[i]; // in case the object is already observed... if (key === '__ob__') continue toVal = to[key]; fromVal = from[key]; if (!hasOwn(to, key)) { set(to, key, fromVal); } else if ( toVal !== fromVal && isPlainObject(toVal) && isPlainObject(fromVal) ) { mergeData(toVal, fromVal); } } return to } /** * Data */ function mergeDataOrFn ( parentVal, childVal, vm ) { if (!vm) { // in a Vue.extend merge, both should be functions if (!childVal) { 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( typeof childVal === 'function' ? childVal.call(this, this) : childVal, typeof parentVal === 'function' ? parentVal.call(this, this) : parentVal ) } } else { return function mergedInstanceDataFn () { // instance merge const instanceData = typeof childVal === 'function' ? childVal.call(vm, vm) : childVal; const defaultData = typeof parentVal === 'function' ? parentVal.call(vm, vm) : parentVal; if (instanceData) { return mergeData(instanceData, defaultData) } else { return defaultData } } } } strats.data = function ( parentVal, childVal, vm ) { if (!vm) { if (childVal && typeof childVal !== 'function') { warn( 'The "data" option should be a function ' + 'that returns a per-instance value in component ' + 'definitions.', vm ); return parentVal } return mergeDataOrFn(parentVal, childVal) } return mergeDataOrFn(parentVal, childVal, vm) }; /** * Hooks and props are merged as arrays. */ function mergeHook ( parentVal, childVal ) { const res = childVal ? parentVal ? parentVal.concat(childVal) : Array.isArray(childVal) ? childVal : [childVal] : parentVal; return res ? dedupeHooks(res) : res } function dedupeHooks (hooks) { const res = []; for (let i = 0; i < hooks.length; i++) { if (res.indexOf(hooks[i]) === -1) { res.push(hooks[i]); } } return res } LIFECYCLE_HOOKS.forEach(hook => { strats[hook] = mergeHook; }); /** * 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, vm, key ) { const res = Object.create(parentVal || null); if (childVal) { assertObjectType(key, childVal, vm); return extend(res, childVal) } else { return res } } ASSET_TYPES.forEach(function (type) { strats[type + 's'] = mergeAssets; }); /** * Watchers. * * Watchers hashes should not overwrite one * another, so we merge them as arrays. */ strats.watch = function ( parentVal, childVal, vm, key ) { // work around Firefox's Object.prototype.watch... if (parentVal === nativeWatch) parentVal = undefined; if (childVal === nativeWatch) childVal = undefined; /* istanbul ignore if */ if (!childVal) return Object.create(parentVal || null) { assertObjectType(key, childVal, vm); } if (!parentVal) return childVal const ret = {}; extend(ret, parentVal); for (const key in childVal) { let parent = ret[key]; const child = childVal[key]; if (parent && !Array.isArray(parent)) { parent = [parent]; } ret[key] = parent ? parent.concat(child) : Array.isArray(child) ? child : [child]; } return ret }; /** * Other object hashes. */ strats.props = strats.methods = strats.inject = strats.computed = function ( parentVal, childVal, vm, key ) { if (childVal && "development" !== 'production') { assertObjectType(key, childVal, vm); } if (!parentVal) return childVal const ret = Object.create(null); extend(ret, parentVal); if (childVal) extend(ret, childVal); return ret }; strats.provide = mergeDataOrFn; /** * Default strategy. */ const defaultStrat = function (parentVal, childVal) { return childVal === undefined ? parentVal : childVal }; /** * Validate component names */ function checkComponents (options) { for (const key in options.components) { validateComponentName(key); } } function validateComponentName (name) { if (!new RegExp(`^[a-zA-Z][\\-\\.0-9_${unicodeRegExp.source}]*$`).test(name)) { warn( 'Invalid component name: "' + name + '". Component names ' + 'should conform to valid custom element name in html5 specification.' ); } if (isBuiltInTag(name) || config.isReservedTag(name)) { warn( 'Do not use built-in or reserved HTML elements as component ' + 'id: ' + name ); } } /** * Ensure all props option syntax are normalized into the * Object-based format. */ function normalizeProps (options, vm) { const props = options.props; if (!props) return const res = {}; let i, val, name; if (Array.isArray(props)) { i = props.length; while (i--) { val = props[i]; if (typeof val === 'string') { name = camelize(val); res[name] = { type: null }; } else { warn('props must be strings when using array syntax.'); } } } else if (isPlainObject(props)) { for (const key in props) { val = props[key]; name = camelize(key); res[name] = isPlainObject(val) ? val : { type: val }; } } else { warn( `Invalid value for option "props": expected an Array or an Object, ` + `but got ${toRawType(props)}.`, vm ); } options.props = res; } /** * Normalize all injections into Object-based format */ function normalizeInject (options, vm) { const inject = options.inject; if (!inject) return const normalized = options.inject = {}; if (Array.isArray(inject)) { for (let i = 0; i < inject.length; i++) { normalized[inject[i]] = { from: inject[i] }; } } else if (isPlainObject(inject)) { for (const key in inject) { const val = inject[key]; normalized[key] = isPlainObject(val) ? extend({ from: key }, val) : { from: val }; } } else { warn( `Invalid value for option "inject": expected an Array or an Object, ` + `but got ${toRawType(inject)}.`, vm ); } } /** * Normalize raw function directives into object format. */ function normalizeDirectives (options) { const dirs = options.directives; if (dirs) { for (const key in dirs) { const def$$1 = dirs[key]; if (typeof def$$1 === 'function') { dirs[key] = { bind: def$$1, update: def$$1 }; } } } } function assertObjectType (name, value, vm) { if (!isPlainObject(value)) { warn( `Invalid value for option "${name}": expected an Object, ` + `but got ${toRawType(value)}.`, vm ); } } /** * Merge two option objects into a new one. * Core utility used in both instantiation and inheritance. */ function mergeOptions ( parent, child, vm ) { { checkComponents(child); } if (typeof child === 'function') { child = child.options; } normalizeProps(child, vm); normalizeInject(child, vm); normalizeDirectives(child); // Apply extends and mixins on the child options, // but only if it is a raw options object that isn't // the result of another mergeOptions call. // Only merged options has the _base property. if (!child._base) { if (child.extends) { parent = mergeOptions(parent, child.extends, vm); } if (child.mixins) { for (let i = 0, l = child.mixins.length; i < l; i++) { parent = mergeOptions(parent, child.mixins[i], vm); } } } const options = {}; let key; for (key in parent) { mergeField(key); } for (key in child) { if (!hasOwn(parent, key)) { mergeField(key); } } function mergeField (key) { const 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. */ function resolveAsset ( options, type, id, warnMissing ) { /* istanbul ignore if */ if (typeof id !== 'string') { return } const assets = options[type]; // check local registration variations first if (hasOwn(assets, id)) return assets[id] const camelizedId = camelize(id); if (hasOwn(assets, camelizedId)) return assets[camelizedId] const PascalCaseId = capitalize(camelizedId); if (hasOwn(assets, PascalCaseId)) return assets[PascalCaseId] // fallback to prototype chain const res = assets[id] || assets[camelizedId] || assets[PascalCaseId]; if (warnMissing && !res) { warn( 'Failed to resolve ' + type.slice(0, -1) + ': ' + id, options ); } return res } /* */ function validateProp ( key, propOptions, propsData, vm ) { const prop = propOptions[key]; const absent = !hasOwn(propsData, key); let value = propsData[key]; // boolean casting const booleanIndex = getTypeIndex(Boolean, prop.type); if (booleanIndex > -1) { if (absent && !hasOwn(prop, 'default')) { value = false; } else if (value === '' || value === hyphenate(key)) { // only cast empty string / same name to boolean if // boolean has higher priority const stringIndex = getTypeIndex(String, prop.type); if (stringIndex < 0 || booleanIndex < stringIndex) { value = true; } } } // check default value if (value === undefined) { value = getPropDefaultValue(vm, prop, key); // since the default value is a fresh copy, // make sure to observe it. const prevShouldObserve = shouldObserve; toggleObserving(true); observe(value); toggleObserving(prevShouldObserve); } { assertProp(prop, key, value, vm, absent); } return value } /** * Get the default value of a prop. */ function getPropDefaultValue (vm, prop, key) { // no default, return undefined if (!hasOwn(prop, 'default')) { return undefined } const def = prop.default; // warn against non-factory defaults for Object & Array if (isObject(def)) { warn( 'Invalid default value for prop "' + key + '": ' + 'Props with type Object/Array must use a factory function ' + 'to return the default value.', vm ); } // the raw prop value was also undefined from previous render, // return previous default value to avoid unnecessary watcher trigger if (vm && vm.$options.propsData && vm.$options.propsData[key] === undefined && vm._props[key] !== undefined ) { return vm._props[key] } // call factory function for non-Function types // a value is Function if its prototype is function even across different execution context return typeof def === 'function' && getType(prop.type) !== 'Function' ? def.call(vm) : def } /** * Assert whether a prop is valid. */ function assertProp ( prop, name, value, vm, absent ) { if (prop.required && absent) { warn( 'Missing required prop: "' + name + '"', vm ); return } if (value == null && !prop.required) { return } let type = prop.type; let valid = !type || type === true; const expectedTypes = []; if (type) { if (!Array.isArray(type)) { type = [type]; } for (let i = 0; i < type.length && !valid; i++) { const assertedType = assertType(value, type[i], vm); expectedTypes.push(assertedType.expectedType || ''); valid = assertedType.valid; } } const haveExpectedTypes = expectedTypes.some(t => t); if (!valid && haveExpectedTypes) { warn( getInvalidTypeMessage(name, value, expectedTypes), vm ); return } const validator = prop.validator; if (validator) { if (!validator(value)) { warn( 'Invalid prop: custom validator check failed for prop "' + name + '".', vm ); } } } const simpleCheckRE = /^(String|Number|Boolean|Function|Symbol|BigInt)$/; function assertType (value, type, vm) { let valid; const expectedType = getType(type); if (simpleCheckRE.test(expectedType)) { const t = typeof value; valid = t === expectedType.toLowerCase(); // for primitive wrapper objects if (!valid && t === 'object') { valid = value instanceof type; } } else if (expectedType === 'Object') { valid = isPlainObject(value); } else if (expectedType === 'Array') { valid = Array.isArray(value); } else { try { valid = value instanceof type; } catch (e) { warn('Invalid prop type: "' + String(type) + '" is not a constructor', vm); valid = false; } } return { valid, expectedType } } const functionTypeCheckRE = /^\s*function (\w+)/; /** * Use function string name to check built-in types, * because a simple equality check will fail when running * across different vms / iframes. */ function getType (fn) { const match = fn && fn.toString().match(functionTypeCheckRE); return match ? match[1] : '' } function isSameType (a, b) { return getType(a) === getType(b) } function getTypeIndex (type, expectedTypes) { if (!Array.isArray(expectedTypes)) { return isSameType(expectedTypes, type) ? 0 : -1 } for (let i = 0, len = expectedTypes.length; i < len; i++) { if (isSameType(expectedTypes[i], type)) { return i } } return -1 } function getInvalidTypeMessage (name, value, expectedTypes) { let message = `Invalid prop: type check failed for prop "${name}".` + ` Expected ${expectedTypes.map(capitalize).join(', ')}`; const expectedType = expectedTypes[0]; const receivedType = toRawType(value); // check if we need to specify expected value if ( expectedTypes.length === 1 && isExplicable(expectedType) && isExplicable(typeof value) && !isBoolean(expectedType, receivedType) ) { message += ` with value ${styleValue(value, expectedType)}`; } message += `, got ${receivedType} `; // check if we need to specify received value if (isExplicable(receivedType)) { message += `with value ${styleValue(value, receivedType)}.`; } return message } function styleValue (value, type) { if (type === 'String') { return `"${value}"` } else if (type === 'Number') { return `${Number(value)}` } else { return `${value}` } } const EXPLICABLE_TYPES = ['string', 'number', 'boolean']; function isExplicable (value) { return EXPLICABLE_TYPES.some(elem => value.toLowerCase() === elem) } function isBoolean (...args) { return args.some(elem => elem.toLowerCase() === 'boolean') } /* */ function handleError (err, vm, info) { // Deactivate deps tracking while processing error handler to avoid possible infinite rendering. // See: https://github.com/vuejs/vuex/issues/1505 pushTarget(); try { if (vm) { let cur = vm; while ((cur = cur.$parent)) { const hooks = cur.$options.errorCaptured; if (hooks) { for (let i = 0; i < hooks.length; i++) { try { const capture = hooks[i].call(cur, err, vm, info) === false; if (capture) return } catch (e) { globalHandleError(e, cur, 'errorCaptured hook'); } } } } } globalHandleError(err, vm, info); } finally { popTarget(); } } function invokeWithErrorHandling ( handler, context, args, vm, info ) { let res; try { res = args ? handler.apply(context, args) : handler.call(context); if (res && !res._isVue && isPromise(res) && !res._handled) { res.catch(e => handleError(e, vm, info + ` (Promise/async)`)); // issue #9511 // avoid catch triggering multiple times when nested calls res._handled = true; } } catch (e) { handleError(e, vm, info); } return res } function globalHandleError (err, vm, info) { if (config.errorHandler) { try { return config.errorHandler.call(null, err, vm, info) } catch (e) { // if the user intentionally throws the original error in the handler, // do not log it twice if (e !== err) { logError(e, null, 'config.errorHandler'); } } } logError(err, vm, info); } function logError (err, vm, info) { { warn(`Error in ${info}: "${err.toString()}"`, vm); } /* istanbul ignore else */ if ((inBrowser || inWeex) && typeof console !== 'undefined') { console.error(err); } else { throw err } } /* */ let isUsingMicroTask = false; const callbacks = []; let pending = false; function flushCallbacks () { pending = false; const copies = callbacks.slice(0); callbacks.length = 0; for (let i = 0; i < copies.length; i++) { copies[i](); } } // Here we have async deferring wrappers using microtasks. // In 2.5 we used (macro) tasks (in combination with microtasks). // However, it has subtle problems when state is changed right before repaint // (e.g. #6813, out-in transitions). // Also, using (macro) tasks in event handler would cause some weird behaviors // that cannot be circumvented (e.g. #7109, #7153, #7546, #7834, #8109). // So we now use microtasks everywhere, again. // A major drawback of this tradeoff is that there are some scenarios // where microtasks have too high a priority and fire in between supposedly // sequential events (e.g. #4521, #6690, which have workarounds) // or even between bubbling of the same event (#6566). let timerFunc; // The nextTick behavior leverages the microtask queue, which can be accessed // via either native Promise.then or MutationObserver. // MutationObserver has wider support, however it is seriously bugged in // UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It // completely stops working after triggering a few times... so, if native // Promise is available, we will use it: /* istanbul ignore next, $flow-disable-line */ if (typeof Promise !== 'undefined' && isNative(Promise)) { const p = Promise.resolve(); timerFunc = () => { p.then(flushCallbacks); // In problematic UIWebViews, Promise.then doesn't completely break, but // it can get stuck in a weird state where callbacks are pushed into the // microtask queue but the queue isn't being flushed, until the browser // needs to do some other work, e.g. handle a timer. Therefore we can // "force" the microtask queue to be flushed by adding an empty timer. if (isIOS) setTimeout(noop); }; isUsingMicroTask = true; } else if (!isIE && typeof MutationObserver !== 'undefined' && ( isNative(MutationObserver) || // PhantomJS and iOS 7.x MutationObserver.toString() === '[object MutationObserverConstructor]' )) { // Use MutationObserver where native Promise is not available, // e.g. PhantomJS, iOS7, Android 4.4 // (#6466 MutationObserver is unreliable in IE11) let counter = 1; const observer = new MutationObserver(flushCallbacks); const textNode = document.createTextNode(String(counter)); observer.observe(textNode, { characterData: true }); timerFunc = () => { counter = (counter + 1) % 2; textNode.data = String(counter); }; isUsingMicroTask = true; } else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) { // Fallback to setImmediate. // Technically it leverages the (macro) task queue, // but it is still a better choice than setTimeout. timerFunc = () => { setImmediate(flushCallbacks); }; } else { // Fallback to setTimeout. timerFunc = () => { setTimeout(flushCallbacks, 0); }; } function nextTick (cb, ctx) { let _resolve; callbacks.push(() => { if (cb) { try { cb.call(ctx); } catch (e) { handleError(e, ctx, 'nextTick'); } } else if (_resolve) { _resolve(ctx); } }); if (!pending) { pending = true; timerFunc(); } // $flow-disable-line if (!cb && typeof Promise !== 'undefined') { return new Promise(resolve => { _resolve = resolve; }) } } /* */ let mark; let measure; { const perf = inBrowser && window.performance; /* istanbul ignore if */ if ( perf && perf.mark && perf.measure && perf.clearMarks && perf.clearMeasures ) { mark = tag => perf.mark(tag); measure = (name, startTag, endTag) => { perf.measure(name, startTag, endTag); perf.clearMarks(startTag); perf.clearMarks(endTag); // perf.clearMeasures(name) }; } } /* not type checking this file because flow doesn't play well with Proxy */ let initProxy; { const allowedGlobals = makeMap( 'Infinity,undefined,NaN,isFinite,isNaN,' + 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' + 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,' + 'require' // for Webpack/Browserify ); const warnNonPresent = (target, key) => { warn( `Property or method "${key}" is not defined on the instance but ` + 'referenced during render. Make sure that this property is reactive, ' + 'either in the data option, or for class-based components, by ' + 'initializing the property. ' + 'See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.', target ); }; const warnReservedPrefix = (target, key) => { warn( `Property "${key}" must be accessed with "$data.${key}" because ` + 'properties starting with "$" or "_" are not proxied in the Vue instance to ' + 'prevent conflicts with Vue internals. ' + 'See: https://vuejs.org/v2/api/#data', target ); }; const hasProxy = typeof Proxy !== 'undefined' && isNative(Proxy); if (hasProxy) { const isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta,exact'); config.keyCodes = new Proxy(config.keyCodes, { set (target, key, value) { if (isBuiltInModifier(key)) { warn(`Avoid overwriting built-in modifier in config.keyCodes: .${key}`); return false } else { target[key] = value; return true } } }); } const hasHandler = { has (target, key) { const has = key in target; const isAllowed = allowedGlobals(key) || (typeof key === 'string' && key.charAt(0) === '_' && !(key in target.$data)); if (!has && !isAllowed) { if (key in target.$data) warnReservedPrefix(target, key); else warnNonPresent(target, key); } return has || !isAllowed } }; const getHandler = { get (target, key) { if (typeof key === 'string' && !(key in target)) { if (key in target.$data) warnReservedPrefix(target, key); else warnNonPresent(target, key); } return target[key] } }; initProxy = function initProxy (vm) { if (hasProxy) { // determine which proxy handler to use const options = vm.$options; const handlers = options.render && options.render._withStripped ? getHandler : hasHandler; vm._renderProxy = new Proxy(vm, handlers); } else { vm._renderProxy = vm; } }; } /* */ const seenObjects = new _Set(); /** * Recursively traverse an object to evoke all converted * getters, so that every nested property inside the object * is collected as a "deep" dependency. */ function traverse (val) { _traverse(val, seenObjects); seenObjects.clear(); } function _traverse (val, seen) { let i, keys; const isA = Array.isArray(val); if ((!isA && !isObject(val)) || Object.isFrozen(val) || val instanceof VNode) { return } if (val.__ob__) { const depId = val.__ob__.dep.id; if (seen.has(depId)) { return } seen.add(depId); } if (isA) { i = val.length; while (i--) _traverse(val[i], seen); } else { keys = Object.keys(val); i = keys.length; while (i--) _traverse(val[keys[i]], seen); } } /* */ const normalizeEvent = cached((name) => { const passive = name.charAt(0) === '&'; name = passive ? name.slice(1) : name; const once$$1 = name.charAt(0) === '~'; // Prefixed last, checked first name = once$$1 ? name.slice(1) : name; const capture = name.charAt(0) === '!'; name = capture ? name.slice(1) : name; return { name, once: once$$1, capture, passive } }); function createFnInvoker (fns, vm) { function invoker () { const fns = invoker.fns; if (Array.isArray(fns)) { const cloned = fns.slice(); for (let i = 0; i < cloned.length; i++) { invokeWithErrorHandling(cloned[i], null, arguments, vm, `v-on handler`); } } else { // return handler return value for single handlers return invokeWithErrorHandling(fns, null, arguments, vm, `v-on handler`) } } invoker.fns = fns; return invoker } function updateListeners ( on, oldOn, add, remove$$1, createOnceHandler, vm ) { let name, cur, old, event; for (name in on) { cur = on[name]; old = oldOn[name]; event = normalizeEvent(name); if (isUndef(cur)) { warn( `Invalid handler for event "${event.name}": got ` + String(cur), vm ); } else if (isUndef(old)) { if (isUndef(cur.fns)) { cur = on[name] = createFnInvoker(cur, vm); } if (isTrue(event.once)) { cur = on[name] = createOnceHandler(event.name, cur, event.capture); } add(event.name, cur, event.capture, event.passive, event.params); } else if (cur !== old) { old.fns = cur; on[name] = old; } } for (name in oldOn) { if (isUndef(on[name])) { event = normalizeEvent(name); remove$$1(event.name, oldOn[name], event.capture); } } } /* */ function mergeVNodeHook (def, hookKey, hook) { if (def instanceof VNode) { def = def.data.hook || (def.data.hook = {}); } let invoker; const oldHook = def[hookKey]; function wrappedHook () { hook.apply(this, arguments); // important: remove merged hook to ensure it's called only once // and prevent memory leak remove(invoker.fns, wrappedHook); } if (isUndef(oldHook)) { // no existing hook invoker = createFnInvoker([wrappedHook]); } else { /* istanbul ignore if */ if (isDef(oldHook.fns) && isTrue(oldHook.merged)) { // already a merged invoker invoker = oldHook; invoker.fns.push(wrappedHook); } else { // existing plain hook invoker = createFnInvoker([oldHook, wrappedHook]); } } invoker.merged = true; def[hookKey] = invoker; } /* */ function extractPropsFromVNodeData ( data, Ctor, tag ) { // we are only extracting raw values here. // validation and default values are handled in the child // component itself. const propOptions = Ctor.options.props; if (isUndef(propOptions)) { return } const res = {}; const { attrs, props } = data; if (isDef(attrs) || isDef(props)) { for (const key in propOptions) { const altKey = hyphenate(key); { const keyInLowerCase = key.toLowerCase(); if ( key !== keyInLowerCase && attrs && hasOwn(attrs, keyInLowerCase) ) { tip( `Prop "${keyInLowerCase}" is passed to component ` + `${formatComponentName(tag || Ctor)}, but the declared prop name is` + ` "${key}". ` + `Note that HTML attributes are case-insensitive and camelCased ` + `props need to use their kebab-case equivalents when using in-DOM ` + `templates. You should probably use "${altKey}" instead of "${key}".` ); } } checkProp(res, props, key, altKey, true) || checkProp(res, attrs, key, altKey, false); } } return res } function checkProp ( res, hash, key, altKey, preserve ) { if (isDef(hash)) { if (hasOwn(hash, key)) { res[key] = hash[key]; if (!preserve) { delete hash[key]; } return true } else if (hasOwn(hash, altKey)) { res[key] = hash[altKey]; if (!preserve) { delete hash[altKey]; } return true } } return false } /* */ // The template compiler attempts to minimize the need for normalization by // statically analyzing the template at compile time. // // For plain HTML markup, normalization can be completely skipped because the // generated render function is guaranteed to return Array. There are // two cases where extra normalization is needed: // 1. When the children contains components - because a functional component // may return an Array instead of a single root. In this case, just a simple // normalization is needed - if any child is an Array, we flatten the whole // thing with Array.prototype.concat. It is guaranteed to be only 1-level deep // because functional components already normalize their own children. function simpleNormalizeChildren (children) { for (let i = 0; i < children.length; i++) { if (Array.isArray(children[i])) { return Array.prototype.concat.apply([], children) } } return children } // 2. When the children contains constructs that always generated nested Arrays, // e.g.