// ==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)
})
})()