// ==UserScript== // @name Bilibili 显示视频分区、av号等 // @namespace https://space.bilibili.com/517723/ // @version 0.03 // @description 在视频下方显示 分区、av 号、分P标题、动态 // @note 才发现分区在tag里,现在会醒目显示此tag // @author 僠儖僲 // @include https://www.bilibili.com/video/* // @icon https://www.bilibili.com/favicon.ico // @compatible firefox Firefox78-esr // @compatible edge Edge88 // @noframes // @grant GM_addStyle // @run-at document-start // @downloadURL none // ==/UserScript== (()=>{ 'use strict'; const list=['详细信息','分P标题','动态'] const isAppend=0//为1则在简介下方 const tname_color='#d600a1'//分区TAG颜色 const ExterminatePJAX=false//关闭PJAX const root=window.unsafeWindow||window const vmp=(()=>{ const globalKey='__BILIBILI_VIEWMODEL_GLOBAL_PROMISE__' if(root[globalKey]){return root[globalKey]} const _call=Function.prototype.call,etp=EventTarget.prototype const on=_call.bind(etp.addEventListener),off=_call.bind(etp.removeEventListener) const once=(t,s,cb)=>new Promise(ok=>{on(t,s,cb=e=>{off(t,s,cb,!0);ok(e)},!0)}) const doc=document,$=doc.querySelector.bind(doc),rAF=cb=>setTimeout(cb,500) const waitElem=select=>new Promise((resolve,reject)=>{ var next=el=>{try{ (el=$(select))?resolve(el):rAF(next) }catch(e){reject(e)}} next() }) const waitVm=app=>new Promise(ok=>{ const vm=app.__vue__ if(vm){ok(vm);return} const set=vm=>{ if(!vm)return ok(vm) Object.defineProperty(app,'__vue__',{ configurable: true, enumerable: true, value: vm, writable: true }) } Object.defineProperty(app,'__vue__',{ configurable: true, enumerable: true, get(){return void 0}, set(vm){set(vm)} }) }) const p=once(doc,'DOMContentLoaded') .then(e=>waitElem('#app,#viewlater-app,.app-wrap')) .then(waitVm) p.then(vm=>{p.vm=vm}) Object.assign(p,{on,off,once,$,waitElem,soucreName:GM_info.script.name}) root[globalKey]=p return p })() const _call=Function.prototype.call, eventStopPropagation=_call.bind(Event.prototype.stopPropagation) const getEl=(value,key='title')=>{ var el=document.querySelector(`.video-desc>.info[${key}="${value}"]`) if(!el){ el=document.createElement('div') el.className='info open' el.setAttribute(key,value) el.setAttribute('data-old',location.href) el.addEventListener('click',eventStopPropagation,1) document.querySelector('.video-desc')[isAppend?'append':'prepend'](el) } return el } var curPart=null,curPartQuery='' const map={ tnameSelect:'.s_tag .tag-area>li .tag-link[href^="//www.bilibili.com/v/"]:not([href^="//www.bilibili.com/v/channel/"])', ['详细信息'](el,data){ var tnames=Array.from(document.querySelectorAll(this.tnameSelect),a=>a.innerText) var av='av'+data.aid var list=[ tnames[1]===data.tname?tnames.join('>'):('分区:'+data.tname),av,data.bvid//,'cid='+root.cid ] el.innerHTML=list.join('\u3000') .replace(/av(\d+)(?!\w)/gi,`av$1`) .replace(/(bv1)(\w{9})/gi,`$1$2`) }, ['分P标题'](el,data){ var page=data.pages[curPart?(curPart[1]-1):0]||data.pages[0] var title=page&&page.part el.innerText=title===data.title?'分P标题与标题相同':(title?'分P标题:'+title:'分P标题为空') }, eds:'—'.repeat(5), ['动态'](el,data){ el.innerText=data.dynamic?`${this.eds}动态${this.eds}\n${data.dynamic}`:'————动态为空————' } } tname_color&&GM_addStyle(`${map.tnameSelect}{color:${tname_color};}`) const inject=(data)=>{ data||(data=root.__INITIAL_STATE__.videoData) curPart=location.search.match(/[?&]p=(\d+)/) curPartQuery=curPart?('?p='+curPart[1]):'' var b=getEl('分割线').style b.height='1px' b.backgroundColor="#e5e9f0" b.margin='15px 0' list[isAppend?'reduce':'reduceRight']((acc,cur)=>{ map[cur](getEl(cur),data) },void 0) } vmp.then(vm=>{ if(ExterminatePJAX){ vm.$router.beforeEach((to,from,next)=>{ var {p}=to.query p=p?'?p='+p:'' location.href=to.path+p next(false) }) } vm.$watch('videoData',data=>{vmp.then(()=>{inject(data)})}) inject(vm.videoData) }) })()