From a3889236be479a61463d3ee72b217ea89898fea7 Mon Sep 17 00:00:00 2001 From: Harvey Date: Fri, 13 May 2022 16:10:19 +0800 Subject: [PATCH] update danmuku --- docs/assets/example/danmuku.js | 88 +- .../artplayer-plugin-danmuku/index.js | 9317 +---------------- .../artplayer-plugin-danmuku/index.js.map | 2 +- docs/uncompiled/artplayer/index.js | 4 +- docs/uncompiled/artplayer/index.js.map | 2 +- .../src/img/danmu-off.svg | 6 + .../src/img/danmu-on.svg | 6 + .../artplayer-plugin-danmuku/src/index.js | 11 +- .../artplayer-plugin-danmuku/src/setting.js | 73 + packages/artplayer/src/setting/index.js | 2 +- 10 files changed, 199 insertions(+), 9312 deletions(-) create mode 100644 packages/artplayer-plugin-danmuku/src/img/danmu-off.svg create mode 100644 packages/artplayer-plugin-danmuku/src/img/danmu-on.svg create mode 100644 packages/artplayer-plugin-danmuku/src/setting.js diff --git a/docs/assets/example/danmuku.js b/docs/assets/example/danmuku.js index 26faf8ba8..77f86f7c7 100644 --- a/docs/assets/example/danmuku.js +++ b/docs/assets/example/danmuku.js @@ -1,54 +1,36 @@ -var art = new Artplayer( - { - container: '.artplayer-app', - url: '/assets/sample/video.mp4', - autoSize: true, - fullscreen: true, - fullscreenWeb: true, - plugins: [ - artplayerPluginDanmuku({ - danmuku: '/assets/sample/danmuku-v2.xml', - speed: 5, // 弹幕持续时间,单位秒 - opacity: 1, // 弹幕透明度 - margin: ['10%', 60], // 弹幕上下边距 - antiOverlap: true, // 是否防重叠 - useWorker: true, // 是否使用 web worker - synchronousPlayback: false, // 是否同步到播放速度 - filter: (danmu) => danmu.text.length < 50, // 弹幕过滤函数 - }), - ], - controls: [ - { - position: 'right', - html: '隐藏', - click: function (_, event) { - if (art.plugins.artplayerPluginDanmuku.isHide) { - art.plugins.artplayerPluginDanmuku.show(); - event.target.innerText = '隐藏'; - } else { - art.plugins.artplayerPluginDanmuku.hide(); - event.target.innerText = '显示'; - } - }, +var art = new Artplayer({ + container: '.artplayer-app', + url: '/assets/sample/video.mp4', + autoSize: true, + fullscreen: true, + fullscreenWeb: true, + setting: true, + plugins: [ + artplayerPluginDanmuku({ + danmuku: '/assets/sample/danmuku-v2.xml', + speed: 5, // 弹幕持续时间,单位秒 + opacity: 1, // 弹幕透明度 + margin: ['10%', 60], // 弹幕上下边距 + antiOverlap: true, // 是否防重叠 + useWorker: true, // 是否使用 web worker + synchronousPlayback: false, // 是否同步到播放速度 + filter: (danmu) => danmu.text.length < 50, // 弹幕过滤函数 + }), + ], + controls: [ + { + position: 'right', + html: '发送', + click: function () { + var text = prompt('请输入弹幕文本', '弹幕测试文本'); + if (!text || !text.trim()) return; + var color = '#' + Math.floor(Math.random() * 0xffffff).toString(16); + art.plugins.artplayerPluginDanmuku.emit({ + text: text, + color: color, + border: true, + }); }, - { - position: 'right', - html: '发送', - click: function () { - var text = prompt('请输入弹幕文本', '弹幕测试文本'); - if (!text || !text.trim()) return; - var color = '#' + Math.floor(Math.random() * 0xffffff).toString(16); - art.plugins.artplayerPluginDanmuku.emit({ - text: text, - color: color, - border: true, - }); - }, - }, - ], - }, - function () { - const danmuku = document.querySelector('.artplayer-danmuku'); - art.plugins.artplayerPluginDanmuku.mount(danmuku); - }, -); + }, + ], +}); diff --git a/docs/uncompiled/artplayer-plugin-danmuku/index.js b/docs/uncompiled/artplayer-plugin-danmuku/index.js index 934dff629..959222795 100644 --- a/docs/uncompiled/artplayer-plugin-danmuku/index.js +++ b/docs/uncompiled/artplayer-plugin-danmuku/index.js @@ -147,21 +147,18 @@ var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js"); parcelHelpers.defineInteropFlag(exports); var _danmuku = require("./danmuku"); var _danmukuDefault = parcelHelpers.interopDefault(_danmuku); -var _control = require("./control"); -var _controlDefault = parcelHelpers.interopDefault(_control); +var _setting = require("./setting"); +var _settingDefault = parcelHelpers.interopDefault(_setting); function artplayerPluginDanmuku(option) { return (art)=>{ const danmuku = new _danmukuDefault.default(art, option); - const control = new _controlDefault.default(art, danmuku); - if (option.el) control.mount(option.el); + _settingDefault.default(art, danmuku); return { name: 'artplayerPluginDanmuku', emit: danmuku.emit.bind(danmuku), config: danmuku.config.bind(danmuku), hide: danmuku.hide.bind(danmuku), show: danmuku.show.bind(danmuku), - mount: control.mount.bind(control), - unmount: control.unmount.bind(control), get isHide () { return danmuku.isHide; }, @@ -174,7 +171,7 @@ function artplayerPluginDanmuku(option) { exports.default = artplayerPluginDanmuku; window['artplayerPluginDanmuku'] = artplayerPluginDanmuku; -},{"./danmuku":"igPca","./control":"nK2ZQ","@parcel/transformer-js/src/esmodule-helpers.js":"8MjWm"}],"igPca":[function(require,module,exports) { +},{"./danmuku":"igPca","./setting":"8npWO","@parcel/transformer-js/src/esmodule-helpers.js":"8MjWm"}],"igPca":[function(require,module,exports) { var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js"); parcelHelpers.defineInteropFlag(exports); var _bilibili = require("./bilibili"); @@ -540,7 +537,7 @@ class Danmuku { if (!danmu.text.trim()) return this; if (!this.option.filter(danmu)) return this; if (danmu.time) danmu.time = this.utils.clamp(danmu.time, 0, Infinity); - else danmu.time = this.art.currentTime + 1; + else danmu.time = this.art.currentTime + 0.5; this.queue.push({ mode: 0, ...danmu, @@ -739,9256 +736,86 @@ exports.default = getDanmuTop; },{"@parcel/transformer-js/src/esmodule-helpers.js":"8MjWm"}],"7RMxU":[function(require,module,exports) { module.exports = "data:application/javascript,function%20getDanmuTop%28%7B%20target%20%2C%20emits%20%2C%20clientWidth%20%2C%20clientHeight%20%2C%20marginBottom%20%2C%20marginTop%20%2C%20antiOverlap%20%20%7D%29%20%7B%0A%20%20%20%20const%20danmus%20%3D%20emits.filter%28%28item%29%3D%3Eitem.mode%20%3D%3D%3D%20target.mode%20%26%26%20item.top%20%3C%3D%20clientHeight%20-%20marginBottom%0A%20%20%20%20%29.sort%28%28prev%2C%20next%29%3D%3Eprev.top%20-%20next.top%0A%20%20%20%20%29%3B%0A%20%20%20%20if%20%28danmus.length%20%3D%3D%3D%200%29%20return%20marginTop%3B%0A%20%20%20%20danmus.unshift%28%7B%0A%20%20%20%20%20%20%20%20top%3A%200%2C%0A%20%20%20%20%20%20%20%20left%3A%200%2C%0A%20%20%20%20%20%20%20%20right%3A%200%2C%0A%20%20%20%20%20%20%20%20height%3A%20marginTop%2C%0A%20%20%20%20%20%20%20%20width%3A%20clientWidth%2C%0A%20%20%20%20%20%20%20%20speed%3A%200%2C%0A%20%20%20%20%20%20%20%20distance%3A%20clientWidth%0A%20%20%20%20%7D%29%3B%0A%20%20%20%20danmus.push%28%7B%0A%20%20%20%20%20%20%20%20top%3A%20clientHeight%20-%20marginBottom%2C%0A%20%20%20%20%20%20%20%20left%3A%200%2C%0A%20%20%20%20%20%20%20%20right%3A%200%2C%0A%20%20%20%20%20%20%20%20height%3A%20marginBottom%2C%0A%20%20%20%20%20%20%20%20width%3A%20clientWidth%2C%0A%20%20%20%20%20%20%20%20speed%3A%200%2C%0A%20%20%20%20%20%20%20%20distance%3A%20clientWidth%0A%20%20%20%20%7D%29%3B%0A%20%20%20%20for%28let%20index%20%3D%201%3B%20index%20%3C%20danmus.length%3B%20index%20%2B%3D%201%29%7B%0A%20%20%20%20%20%20%20%20const%20item%20%3D%20danmus%5Bindex%5D%3B%0A%20%20%20%20%20%20%20%20const%20prev%20%3D%20danmus%5Bindex%20-%201%5D%3B%0A%20%20%20%20%20%20%20%20const%20prevBottom%20%3D%20prev.top%20%2B%20prev.height%3B%0A%20%20%20%20%20%20%20%20const%20diff%20%3D%20item.top%20-%20prevBottom%3B%0A%20%20%20%20%20%20%20%20if%20%28diff%20%3E%3D%20target.height%29%20return%20prevBottom%3B%0A%20%20%20%20%7D%0A%20%20%20%20const%20topMap%20%3D%20%5B%5D%3B%0A%20%20%20%20for%28let%20index1%20%3D%201%3B%20index1%20%3C%20danmus.length%20-%201%3B%20index1%20%2B%3D%201%29%7B%0A%20%20%20%20%20%20%20%20const%20item%20%3D%20danmus%5Bindex1%5D%3B%0A%20%20%20%20%20%20%20%20if%20%28topMap.length%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20last%20%3D%20topMap%5BtopMap.length%20-%201%5D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20%28last%5B0%5D.top%20%3D%3D%3D%20item.top%29%20last.push%28item%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20else%20topMap.push%28%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20item%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%29%3B%0A%20%20%20%20%20%20%20%20%7D%20else%20topMap.push%28%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20item%0A%20%20%20%20%20%20%20%20%5D%29%3B%0A%20%20%20%20%7D%0A%20%20%20%20if%20%28antiOverlap%29%20switch%28target.mode%29%7B%0A%20%20%20%20%20%20%20%20case%200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20result%20%3D%20topMap.find%28%28list%29%3D%3E%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20list.every%28%28danmu%29%3D%3E%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20%28clientWidth%20%3C%20danmu.distance%29%20return%20false%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20%28target.speed%20%3C%20danmu.speed%29%20return%20true%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20overlapTime%20%3D%20danmu.right%20%2F%20%28target.speed%20-%20danmu.speed%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20%28overlapTime%20%3E%20danmu.time%29%20return%20true%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20false%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20result%20%26%26%20result%5B0%5D%20%3F%20result%5B0%5D.top%20%3A%20undefined%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20case%201%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20undefined%3B%0A%20%20%20%20%20%20%20%20default%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%7D%0A%20%20%20%20else%20%7B%0A%20%20%20%20%20%20%20%20switch%28target.mode%29%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20case%200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20topMap.sort%28%28prev%2C%20next%29%3D%3E%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20nextMinRight%20%3D%20Math.min%28...next.map%28%28item%29%3D%3Eitem.right%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%29%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20prevMinRight%20%3D%20Math.min%28...prev.map%28%28item%29%3D%3Eitem.right%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%29%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20nextMinRight%20%2a%20next.length%20-%20prevMinRight%20%2a%20prev.length%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20case%201%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20topMap.sort%28%28prev%2C%20next%29%3D%3E%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20nextMaxWidth%20%3D%20Math.max%28...next.map%28%28item%29%3D%3Eitem.width%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%29%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20prevMaxWidth%20%3D%20Math.max%28...prev.map%28%28item%29%3D%3Eitem.width%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%29%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20prevMaxWidth%20%2a%20prev.length%20-%20nextMaxWidth%20%2a%20next.length%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20default%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20topMap%5B0%5D%5B0%5D.top%3B%0A%20%20%20%20%7D%0A%7D%0Aonmessage%20%3D%20%28event%29%3D%3E%7B%0A%20%20%20%20const%20%7B%20data%20%20%7D%20%3D%20event%3B%0A%20%20%20%20const%20top%20%3D%20getDanmuTop%28data%29%3B%0A%20%20%20%20self.postMessage%28%7B%0A%20%20%20%20%20%20%20%20top%2C%0A%20%20%20%20%20%20%20%20id%3A%20data.id%0A%20%20%20%20%7D%29%3B%0A%7D%3B%0A%0A"; -},{}],"nK2ZQ":[function(require,module,exports) { +},{}],"8npWO":[function(require,module,exports) { var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js"); parcelHelpers.defineInteropFlag(exports); -var _styleLess = require("bundle-text:./style.less"); -var _styleLessDefault = parcelHelpers.interopDefault(_styleLess); -var _vue = require("vue"); -var _appVue = require("./App.vue"); -var _appVueDefault = parcelHelpers.interopDefault(_appVue); -if (typeof document !== 'undefined') { - if (!document.getElementById('artplayer-plugin-danmuku-style')) { - const $style = document.createElement('style'); - $style.id = 'artplayer-plugin-danmuku-style'; - $style.textContent = _styleLessDefault.default; - document.head.appendChild($style); - } -} -class Control { - constructor(art, danmuku){ - this.art = art; - this.danmuku = danmuku; - this.apps = new Map(); - } - mount(el) { - const that = this; - const app1 = _vue.createApp(_appVueDefault.default); - app1.use({ - install (app) { - app.config.globalProperties.$art = that.art; - app.config.globalProperties.$danmuku = that.danmuku; - } - }); - app1.mount(el); - this.apps.set(el, app1); - return app1; - } - unmount(el) { - const app = this.apps.get(el); - if (app) { - app.unmount(); - this.apps.delete(el); - } - } -} -exports.default = Control; - -},{"vue":"5Gshn","./App.vue":"b6WPi","@parcel/transformer-js/src/esmodule-helpers.js":"8MjWm","bundle-text:./style.less":"24DKH"}],"5Gshn":[function(require,module,exports) { -var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js"); -parcelHelpers.defineInteropFlag(exports); -parcelHelpers.export(exports, "compile", ()=>compile -); -var _runtimeDom = require("@vue/runtime-dom"); -parcelHelpers.exportAll(_runtimeDom, exports); -function initDev() { - _runtimeDom.initCustomFormatter(); -} -initDev(); -const compile = ()=>{ - _runtimeDom.warn(`Runtime compilation is not supported in this build of Vue.` + ` Configure your bundler to alias "vue" to "vue/dist/vue.esm-bundler.js".`); -}; - -},{"@vue/runtime-dom":"hgqy6","@parcel/transformer-js/src/esmodule-helpers.js":"8MjWm"}],"hgqy6":[function(require,module,exports) { -var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js"); -parcelHelpers.defineInteropFlag(exports); -parcelHelpers.export(exports, "Transition", ()=>Transition -); -parcelHelpers.export(exports, "TransitionGroup", ()=>TransitionGroup -); -parcelHelpers.export(exports, "VueElement", ()=>VueElement -); -parcelHelpers.export(exports, "createApp", ()=>createApp -); -parcelHelpers.export(exports, "createSSRApp", ()=>createSSRApp -); -parcelHelpers.export(exports, "defineCustomElement", ()=>defineCustomElement -); -parcelHelpers.export(exports, "defineSSRCustomElement", ()=>defineSSRCustomElement -); -parcelHelpers.export(exports, "hydrate", ()=>hydrate -); -parcelHelpers.export(exports, "initDirectivesForSSR", ()=>initDirectivesForSSR -); -parcelHelpers.export(exports, "render", ()=>render -); -parcelHelpers.export(exports, "useCssModule", ()=>useCssModule -); -parcelHelpers.export(exports, "useCssVars", ()=>useCssVars -); -parcelHelpers.export(exports, "vModelCheckbox", ()=>vModelCheckbox -); -parcelHelpers.export(exports, "vModelDynamic", ()=>vModelDynamic -); -parcelHelpers.export(exports, "vModelRadio", ()=>vModelRadio -); -parcelHelpers.export(exports, "vModelSelect", ()=>vModelSelect -); -parcelHelpers.export(exports, "vModelText", ()=>vModelText -); -parcelHelpers.export(exports, "vShow", ()=>vShow -); -parcelHelpers.export(exports, "withKeys", ()=>withKeys -); -parcelHelpers.export(exports, "withModifiers", ()=>withModifiers -); -var _runtimeCore = require("@vue/runtime-core"); -var _shared = require("@vue/shared"); -parcelHelpers.exportAll(_runtimeCore, exports); -const svgNS = 'http://www.w3.org/2000/svg'; -const doc = typeof document !== 'undefined' ? document : null; -const templateContainer = doc && /*#__PURE__*/ doc.createElement('template'); -const nodeOps = { - insert: (child, parent, anchor)=>{ - parent.insertBefore(child, anchor || null); - }, - remove: (child)=>{ - const parent = child.parentNode; - if (parent) parent.removeChild(child); - }, - createElement: (tag, isSVG, is, props)=>{ - const el = isSVG ? doc.createElementNS(svgNS, tag) : doc.createElement(tag, is ? { - is - } : undefined); - if (tag === 'select' && props && props.multiple != null) el.setAttribute('multiple', props.multiple); - return el; - }, - createText: (text)=>doc.createTextNode(text) - , - createComment: (text)=>doc.createComment(text) - , - setText: (node, text)=>{ - node.nodeValue = text; - }, - setElementText: (el, text)=>{ - el.textContent = text; - }, - parentNode: (node)=>node.parentNode - , - nextSibling: (node)=>node.nextSibling - , - querySelector: (selector)=>doc.querySelector(selector) - , - setScopeId (el, id) { - el.setAttribute(id, ''); - }, - cloneNode (el) { - const cloned = el.cloneNode(true); - // #3072 - // - in `patchDOMProp`, we store the actual value in the `el._value` property. - // - normally, elements using `:value` bindings will not be hoisted, but if - // the bound value is a constant, e.g. `:value="true"` - they do get - // hoisted. - // - in production, hoisted nodes are cloned when subsequent inserts, but - // cloneNode() does not copy the custom property we attached. - // - This may need to account for other custom DOM properties we attach to - // elements in addition to `_value` in the future. - if (`_value` in el) cloned._value = el._value; - return cloned; - }, - // __UNSAFE__ - // Reason: innerHTML. - // Static content here can only come from compiled templates. - // As long as the user only uses trusted templates, this is safe. - insertStaticContent (content, parent, anchor, isSVG, start, end) { - // before | first ... last | anchor - const before = anchor ? anchor.previousSibling : parent.lastChild; - // #5308 can only take cached path if: - // - has a single root node - // - nextSibling info is still available - if (start && (start === end || start.nextSibling)) // cached - while(true){ - parent.insertBefore(start.cloneNode(true), anchor); - if (start === end || !(start = start.nextSibling)) break; - } - else { - // fresh insert - templateContainer.innerHTML = isSVG ? `${content}` : content; - const template = templateContainer.content; - if (isSVG) { - // remove outer svg wrapper - const wrapper = template.firstChild; - while(wrapper.firstChild)template.appendChild(wrapper.firstChild); - template.removeChild(wrapper); - } - parent.insertBefore(template, anchor); - } - return [ - // first - before ? before.nextSibling : parent.firstChild, - // last - anchor ? anchor.previousSibling : parent.lastChild - ]; - } -}; -// compiler should normalize class + :class bindings on the same element -// into a single binding ['staticClass', dynamic] -function patchClass(el, value, isSVG) { - // directly setting className should be faster than setAttribute in theory - // if this is an element during a transition, take the temporary transition - // classes into account. - const transitionClasses = el._vtc; - if (transitionClasses) value = (value ? [ - value, - ...transitionClasses - ] : [ - ...transitionClasses - ]).join(' '); - if (value == null) el.removeAttribute('class'); - else if (isSVG) el.setAttribute('class', value); - else el.className = value; -} -function patchStyle(el, prev, next) { - const style = el.style; - const isCssString = _shared.isString(next); - if (next && !isCssString) { - for(const key in next)setStyle(style, key, next[key]); - if (prev && !_shared.isString(prev)) { - for(const key in prev)if (next[key] == null) setStyle(style, key, ''); - } - } else { - const currentDisplay = style.display; - if (isCssString) { - if (prev !== next) style.cssText = next; - } else if (prev) el.removeAttribute('style'); - // indicates that the `display` of the element is controlled by `v-show`, - // so we always keep the current `display` value regardless of the `style` - // value, thus handing over control to `v-show`. - if ('_vod' in el) style.display = currentDisplay; - } -} -const importantRE = /\s*!important$/; -function setStyle(style, name, val) { - if (_shared.isArray(val)) val.forEach((v)=>setStyle(style, name, v) - ); - else { - if (val == null) val = ''; - if (name.startsWith('--')) // custom property definition - style.setProperty(name, val); - else { - const prefixed = autoPrefix(style, name); - if (importantRE.test(val)) // !important - style.setProperty(_shared.hyphenate(prefixed), val.replace(importantRE, ''), 'important'); - else style[prefixed] = val; - } - } -} -const prefixes = [ - 'Webkit', - 'Moz', - 'ms' -]; -const prefixCache = {}; -function autoPrefix(style, rawName) { - const cached = prefixCache[rawName]; - if (cached) return cached; - let name = _runtimeCore.camelize(rawName); - if (name !== 'filter' && name in style) return prefixCache[rawName] = name; - name = _shared.capitalize(name); - for(let i = 0; i < prefixes.length; i++){ - const prefixed = prefixes[i] + name; - if (prefixed in style) return prefixCache[rawName] = prefixed; - } - return rawName; -} -const xlinkNS = 'http://www.w3.org/1999/xlink'; -function patchAttr(el, key, value, isSVG, instance) { - if (isSVG && key.startsWith('xlink:')) { - if (value == null) el.removeAttributeNS(xlinkNS, key.slice(6, key.length)); - else el.setAttributeNS(xlinkNS, key, value); - } else { - // note we are only checking boolean attributes that don't have a - // corresponding dom prop of the same name here. - const isBoolean = _shared.isSpecialBooleanAttr(key); - if (value == null || isBoolean && !_shared.includeBooleanAttr(value)) el.removeAttribute(key); - else el.setAttribute(key, isBoolean ? '' : value); - } -} -// __UNSAFE__ -// functions. The user is responsible for using them with only trusted content. -function patchDOMProp(el, key, value, // the following args are passed only due to potential innerHTML/textContent -// overriding existing VNodes, in which case the old tree must be properly -// unmounted. -prevChildren, parentComponent, parentSuspense, unmountChildren) { - if (key === 'innerHTML' || key === 'textContent') { - if (prevChildren) unmountChildren(prevChildren, parentComponent, parentSuspense); - el[key] = value == null ? '' : value; - return; - } - if (key === 'value' && el.tagName !== 'PROGRESS' && // custom elements may use _value internally - !el.tagName.includes('-')) { - // store value as _value as well since - // non-string values will be stringified. - el._value = value; - const newValue = value == null ? '' : value; - if (el.value !== newValue || // #4956: always set for OPTION elements because its value falls back to - // textContent if no value attribute is present. And setting .value for - // OPTION has no side effect - el.tagName === 'OPTION') el.value = newValue; - if (value == null) el.removeAttribute(key); - return; - } - let needRemove = false; - if (value === '' || value == null) { - const type = typeof el[key]; - if (type === 'boolean') // e.g. - try { - el[key] = value; - } catch (e) { - _runtimeCore.warn(`Failed setting prop "${key}" on <${el.tagName.toLowerCase()}>: ` + `value ${value} is invalid.`, e); - } - needRemove && el.removeAttribute(key); -} -// Async edge case fix requires storing an event listener's attach timestamp. -const [_getNow, skipTimestampCheck] = /*#__PURE__*/ (()=>{ - let _getNow1 = Date.now; - let skipTimestampCheck1 = false; - if (typeof window !== 'undefined') { - // Determine what event timestamp the browser is using. Annoyingly, the - // timestamp can either be hi-res (relative to page load) or low-res - // (relative to UNIX epoch), so in order to compare time we have to use the - // same timestamp type when saving the flush timestamp. - if (Date.now() > document.createEvent('Event').timeStamp) // if the low-res timestamp which is bigger than the event timestamp - // (which is evaluated AFTER) it means the event is using a hi-res timestamp, - // and we need to use the hi-res version for event listeners as well. - _getNow1 = ()=>performance.now() - ; - // #3485: Firefox <= 53 has incorrect Event.timeStamp implementation - // and does not fire microtasks in between event propagation, so safe to exclude. - const ffMatch = navigator.userAgent.match(/firefox\/(\d+)/i); - skipTimestampCheck1 = !!(ffMatch && Number(ffMatch[1]) <= 53); - } - return [ - _getNow1, - skipTimestampCheck1 - ]; -})(); -// To avoid the overhead of repeatedly calling performance.now(), we cache -// and use the same timestamp for all event listeners attached in the same tick. -let cachedNow = 0; -const p = /*#__PURE__*/ Promise.resolve(); -const reset = ()=>{ - cachedNow = 0; -}; -const getNow = ()=>cachedNow || (p.then(reset), cachedNow = _getNow()) -; -function addEventListener(el, event, handler, options) { - el.addEventListener(event, handler, options); -} -function removeEventListener(el, event, handler, options) { - el.removeEventListener(event, handler, options); -} -function patchEvent(el, rawName, prevValue, nextValue, instance = null) { - // vei = vue event invokers - const invokers = el._vei || (el._vei = {}); - const existingInvoker = invokers[rawName]; - if (nextValue && existingInvoker) // patch - existingInvoker.value = nextValue; - else { - const [name, options] = parseName(rawName); - if (nextValue) { - // add - const invoker = invokers[rawName] = createInvoker(nextValue, instance); - addEventListener(el, name, invoker, options); - } else if (existingInvoker) { - // remove - removeEventListener(el, name, existingInvoker, options); - invokers[rawName] = undefined; - } - } -} -const optionsModifierRE = /(?:Once|Passive|Capture)$/; -function parseName(name) { - let options; - if (optionsModifierRE.test(name)) { - options = {}; - let m; - while(m = name.match(optionsModifierRE)){ - name = name.slice(0, name.length - m[0].length); - options[m[0].toLowerCase()] = true; - } - } - return [ - _shared.hyphenate(name.slice(2)), - options - ]; -} -function createInvoker(initialValue, instance) { - const invoker = (e)=>{ - // async edge case #6566: inner click event triggers patch, event handler - // attached to outer element during patch, and triggered again. This - // happens because browsers fire microtask ticks between event propagation. - // the solution is simple: we save the timestamp when a handler is attached, - // and the handler would only fire if the event passed to it was fired - // AFTER it was attached. - const timeStamp = e.timeStamp || _getNow(); - if (skipTimestampCheck || timeStamp >= invoker.attached - 1) _runtimeCore.callWithAsyncErrorHandling(patchStopImmediatePropagation(e, invoker.value), instance, 5 /* NATIVE_EVENT_HANDLER */ , [ - e - ]); - }; - invoker.value = initialValue; - invoker.attached = getNow(); - return invoker; -} -function patchStopImmediatePropagation(e1, value) { - if (_shared.isArray(value)) { - const originalStop = e1.stopImmediatePropagation; - e1.stopImmediatePropagation = ()=>{ - originalStop.call(e1); - e1._stopped = true; - }; - return value.map((fn)=>(e)=>!e._stopped && fn && fn(e) - ); - } else return value; -} -const nativeOnRE = /^on[a-z]/; -const patchProp = (el, key, prevValue, nextValue, isSVG = false, prevChildren, parentComponent, parentSuspense, unmountChildren)=>{ - if (key === 'class') patchClass(el, nextValue, isSVG); - else if (key === 'style') patchStyle(el, prevValue, nextValue); - else if (_shared.isOn(key)) // ignore v-model listeners - { - if (!_shared.isModelListener(key)) patchEvent(el, key, prevValue, nextValue, parentComponent); - } else if (key[0] === '.' ? (key = key.slice(1), true) : key[0] === '^' ? (key = key.slice(1), false) : shouldSetAsProp(el, key, nextValue, isSVG)) patchDOMProp(el, key, nextValue, prevChildren, parentComponent, parentSuspense, unmountChildren); - else { - // special case for with - // :true-value & :false-value - // store value as dom properties since non-string values will be - // stringified. - if (key === 'true-value') el._trueValue = nextValue; - else if (key === 'false-value') el._falseValue = nextValue; - patchAttr(el, key, nextValue, isSVG); - } -}; -function shouldSetAsProp(el, key, value, isSVG) { - if (isSVG) { - // most keys must be set as attribute on svg elements to work - // ...except innerHTML & textContent - if (key === 'innerHTML' || key === 'textContent') return true; - // or native onclick with function values - if (key in el && nativeOnRE.test(key) && _shared.isFunction(value)) return true; - return false; - } - // these are enumerated attrs, however their corresponding DOM properties - // are actually booleans - this leads to setting it with a string "false" - // value leading it to be coerced to `true`, so we need to always treat - // them as attributes. - // Note that `contentEditable` doesn't have this problem: its DOM - // property is also enumerated string values. - if (key === 'spellcheck' || key === 'draggable' || key === 'translate') return false; - // #1787, #2840 form property on form elements is readonly and must be set as - // attribute. - if (key === 'form') return false; - // #1526 must be set as attribute - if (key === 'list' && el.tagName === 'INPUT') return false; - // #2766