// ==UserScript==
// @name 自定义注入css和js脚本(广告屏蔽等)
// @description 可自定义css选择器屏蔽页面广告,注入js脚本
// @namespace _cus_ad_sp
// @version 1.0.0
// @author vizo
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js
// @require https://cdn.jsdelivr.net/npm/vio-utils/utils.js
// @include /https?:\/\/[^localhost|127.0.0.1|192.168]+/
// @run-at document-start
// @grant GM_getResourceText
// @grant GM_addStyle
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_listValues
// @grant GM_registerMenuCommand
// @noframes
// ==/UserScript==
;(function() {
if (vio.isMobile()) return
let k = GM_getValue(`cus_${location.host}`) || {}
if (k.css) {
let css = `<style class="sty9z1p52">${k.css}</style>`
document.head.insertAdjacentHTML('beforeend', css)
}
})()
GM_addStyle(`
img {
display:none !important;
height: 0 !important;
overflow: hidden !important;
pointer-events: none;
}
#modal5sn, #modal5sn * {
margin: 0;
padding: 0;
box-sizing: border-box !important;
}
#modal5sn {
width: 28vw;
height: 68vh;
min-width: 400px;
padding: 30px;
background: #fff;
border-radius: 3px;
line-height: 1.5;
font-size: 12px;
box-shadow: 0 0 5px #ccc;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 50050;
margin: auto;
}
#modal5sn .md-wp {
height: 100%;
display: flex;
flex-direction: column;
}
#modal5sn .tit {
color: #555;
font-size: 18px;
text-align: center;
margin-bottom: 15px;
}
#modal5sn .c-item {
margin-bottom: 10px;
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
#modal5sn .css-item,
#modal5sn .js-item,
#modal5sn .allset-item {
flex: 1;
}
#modal5sn .sti {
font-size: 15px;
margin-bottom: 3px;
position: relative;
}
#modal5sn .view-all-set {
color: #09e;
cursor: pointer;
user-select: none;
position: absolute;
top: 0;
right: 0;
}
#modal5sn .inpy {
flex: 0 0 auto;
height: 32px;
border: 1px solid #ddd;
color: #555;
border-radius: 2px;
padding: 0 10px;
outline: none;
}
#modal5sn .inpy:focus {
border: 1px solid #c1c1c1;
}
#modal5sn .txtr1z {
flex: 1;
color: #555;
padding: 6px;
overflow-x: hidden;
overflow-y: auto;
border-radius: 2px;
border: 1px solid #ddd;
font-size: 12px;
resize: none;
white-space: pre-line;
outline: none;
font-family: Consolas,sans-serif,"Helvetica Neue",Helvetica,"PingFang SC","Microsoft YaHei";
}
#modal5sn .txtr1z:focus {
border: 1px solid #c1c1c1;
}
#modal5sn .txtr1z::-webkit-scrollbar {
width: 4px;
}
#modal5sn .txtr1z::-webkit-scrollbar-corner,
#modal5sn .txtr1z::-webkit-scrollbar-track {
background-color: #fff;
}
#modal5sn .txtr1z::-webkit-scrollbar-thumb {
background: #fff;
}
#modal5sn .txtr1z:hover::-webkit-scrollbar-thumb {
background: #e1e1e1;
}
#modal5sn .txtr1z:hover::-webkit-scrollbar-corner,
#modal5sn .txtr1z:hover::-webkit-scrollbar-track {
background-color: #f7f7f7;
}
#modal5sn .btn-w {
margin-top: 5px;
display: flex;
flex-direction: row-reverse;
}
#modal5sn .btn-w .c-btn {
width: 90px;
height: 32px;
border-radius: 2px;
margin-right: 10px;
color: #555;
background-color: #f1f1f1;
cursor: pointer;
outline: none;
border: 0;
}
#modal5sn .btn-w .c-btn.b1 {
color: #fff;
background-color: #09e;
}
#modal5sn .btn-w .c-btn:first-child {
margin-right: 0;
}
#modal5sn .btn-w .c-btn:focus {
border: 0;
}
#modal5sn .btn-w .c-btn:hover {
opacity: 0.9;
}
`)
const G = {
html: `
<div id="modal5sn" v-show="dialog1s">
<div class="md-wp">
<div class="tit">设置</div>
<div class="c-item">
<p class="sti">打开面板快捷键 <span class="view-all-set" @click="hdlViewAllSet">{{ viewSetText }}</span></p>
<input type="text" class="inpy" v-model="eKey" placeholder="请输入a-z的任意字母">
</div>
<div class="c-item css-item" v-show="!showAllSet">
<p class="sti">注入css(不用写style标签)</p>
<textarea class="txtr1z" v-model="texCssVal" placeholder="请输入css代码"></textarea>
</div>
<div class="c-item js-item" v-show="!showAllSet">
<p class="sti">注入js(不用写script标签)</p>
<textarea class="txtr1z" v-model="texJsVal" placeholder="请输入js代码"></textarea>
</div>
<div class="c-item allset-item" v-show="showAllSet">
<p class="sti">全部网站已注入的css和js</p>
<textarea class="txtr1z" v-model="allSetJson"></textarea>
</div>
<div class="btn-w">
<button class="c-btn b2" @click="hdlCancel">取消</button>
<button class="c-btn b1" @click="hdlSave">保存</button>
</div>
</div>
</div>
`,
}
const vm = new Vue({
data() {
return {
// 模态框状态
dialog1s: false,
// 快捷键名称
eKey: '',
showAllSet: false,
// css代码
texCssVal: '',
// js代码
texJsVal: '',
// 全部设置
allSetJson: '',
}
},
computed: {
viewSetText() {
return this.showAllSet ? '查看当前网站' : '查看全部网站'
},
},
watch: {
eKey(nVal) {
this.eKey = /[a-z]/.test(nVal) ? nVal.slice(0, 1) : ''
GM_setValue('cusBKEkey', this.eKey)
},
dialog1s(nVal) {
if (!nVal) {
this.showAllSet = false
}
},
},
methods: {
setGmVal(val) {
return GM_setValue(`cus_${location.host}`, val)
},
getGmVal() {
return GM_getValue(`cus_${location.host}`) || {}
},
hdlSave() {
this.injectCssAndRemoveOld()
this.injectJsAndRemoveOld()
this.initAllCssJsJson()
this.dialog1s = false
},
hdlCancel() {
this.dialog1s = false
},
injectCssAndRemoveOld() {
let css = `<style class="sty9z1p52">${this.texCssVal}</style>`
document.head.insertAdjacentHTML('beforeend', css)
this.setGmVal({
...this.getGmVal(),
css: this.texCssVal
})
Array.from(document.querySelectorAll('.sty9z1p52')).forEach((v, i, y) => {
if (i !== y.length - 1) {
v.remove()
}
})
},
injectJsAndRemoveOld() {
let st = document.createElement('script')
st.classList.add('js7z1p32')
st.textContent = this.texJsVal
document.body.appendChild(st)
this.setGmVal({
...this.getGmVal(),
js: this.texJsVal
})
Array.from(document.querySelectorAll('.js7z1p32')).forEach((v, i, y) => {
if (i !== y.length - 1) {
v.remove()
}
})
},
tgCfgDialog() {
this.dialog1s = !this.dialog1s
},
hdlViewAllSet() {
this.showAllSet = !this.showAllSet
// GM_listValues()
},
resetInjectCss() {
this.texCssVal = ''
this.setGmVal({
...this.getGmVal(),
css: '',
})
location.reload()
},
resetInjectJs() {
this.texJsVal = ''
this.setGmVal({
...this.getGmVal(),
js: '',
})
location.reload()
},
initEvt() {
window.addEventListener('keydown', e => {
if (
!(/text|search|number/.test(e.target.type)) &&
e.target.tagName !== 'TEXTAREA' &&
!e.altKey &&
!e.ctrlKey &&
e.key === this.eKey
) {
this.tgCfgDialog()
}
})
},
initEkey() {
this.eKey = GM_getValue('cusBKEkey') || ''
},
initCssJsVal() {
this.texCssVal = this.getGmVal().css || ''
this.texJsVal = this.getGmVal().js || ''
},
initAllCssJsJson() {
const res = GM_listValues()
.filter(v => v.includes('cus_'))
.reduce((acc, v) => {
return {
...acc,
[v.slice(4)]: GM_getValue(v)
}
}, {})
this.allSetJson = JSON.stringify(res, null, 2)
},
initInjectedScript() {
let js = this.getGmVal().js
if (js) {
let st = document.createElement('script')
st.classList.add('js7z1p32')
st.textContent = js
document.body.appendChild(st)
}
},
},
mounted() {
this.initEvt()
this.initEkey()
this.initCssJsVal()
this.initAllCssJsJson()
this.initInjectedScript()
},
})
const initFunc = () => {
if (vio.isMobile()) return
document.body.insertAdjacentHTML('beforeend', G.html)
vm.$mount('#modal5sn')
GM_registerMenuCommand('打开设置面板', vm.tgCfgDialog)
GM_registerMenuCommand('重置注入的css', vm.resetInjectCss)
GM_registerMenuCommand('重置注入的js', vm.resetInjectJs)
}
initFunc()