☝🤓必应搜索屏蔽

屏蔽必应搜索结果中不想看到的网页,使用-site规则实现

// ==UserScript==
// @name         ☝🤓必应搜索屏蔽
// @namespace    http://tampermonkey.net/
// @version      1.0.1
// @description  屏蔽必应搜索结果中不想看到的网页,使用-site规则实现
// @author       ACYFT
// @license      MIT
// @match        https://cn.bing.com/search?*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=bing.com
// @noframes
// @grant        GM_addStyle
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        unsafeWindow
// ==/UserScript==

(function() {
    'use strict';
    // 获取本地数据
    var allRules=GM_getValue('allRules') ?? []
    var enabledRules=GM_getValue('enabledRules') ?? []

    var url=location.href // 原url
    var newUrl=url// 新url
    var isIncludeAll=true // url是否包含所有规则,默认为true
    var searchInputEle=document.getElementById('sb_form_q') // 搜索栏元素
    var searchInputValue=searchInputEle.value.trim() // 搜索栏内容
    var inputLength=searchInputValue.length // 搜索栏内容长度,用于判断内容是否变化
    var uselessParamsInUrl=['tsc','sp','FORM','form','pq','sc','qs','sk','cvid','lq','ghsh','ghacc','ghpl','ghc','PC','go','rdr','rdrig','FPIG'] // url无用参数

    // 生成newUrl
    enabledRules.forEach((rule)=>{
        // 匹配规则关键词的正则,使用new RegExp以便动态生成
        var regex = new RegExp(`(^|\\s)-site:${rule.replace(/[.?+*()[\]{}^$|\\]/g,'\\$&')}(\\s|$)`)
        // 尝试清除脚本自动添加的规则关键词
        searchInputValue=searchInputValue.replace(regex,' ')
        // 如果清除成功说明规则已存在
        if(searchInputValue.length < inputLength){
            // 去除搜索栏首尾及重复空格
            searchInputValue=searchInputValue.replace(/\s+/g,' ').trim()
            // 更新搜索栏内容长度
            inputLength=searchInputValue.length
        }
        // 如果长度没有变化说明规则不存在
        else {
            // 添加规则到新url中
            newUrl=newUrl.replace('q=',`q=-site%3A${rule}+`)
            // 是否包含所有规则,修正为false
            isIncludeAll=false
        }
    })

    // 修正搜索栏的内容
    searchInputEle.value=searchInputValue
    // 重定向
    if(!isIncludeAll){
        window.stop()
        location.replace(newUrl)
    } else {
        newUrl=new URL(url)
        // 去除url无用参数
        uselessParamsInUrl.forEach((paramName)=>{
            newUrl.searchParams.delete(paramName)
        })
        newUrl=newUrl.toString()
        // 清除页面地址中的规则,覆盖当前历史记录,页面不跳转
        enabledRules.forEach((rule)=>{
            // 匹配地址栏中规则的正则,使用new RegExp以便动态生成
            var regex = new RegExp(`-site%3A${rule.replace(/[.?+*()[\]{}^$|\\]/g,'\\$&')}\\+`)
            newUrl=newUrl.replace(regex,'')
        })
        history.replaceState(null,null,newUrl)
        // 修改网页标题
        document.title=`${searchInputValue} - 搜索`
            // 修改原pushState函数为跳转至目标页面
            history.pushState=(f=>function(){
                console.log('pushStateURL',arguments[2])
                window.stop()
                window.location.href=`https://cn.bing.com${arguments[2]}`
            //return f.apply(this,arguments)
            })(history.pushState)
            console.log('change pushState')
    }

    // 清除未回收的规则/规则组
    allRules.forEach((group,groupIndex)=>{
        if(group.disabled=='notYet'){
            allRules.splice(groupIndex,1)
        } else {
            group.rules.forEach((rule,ruleIndex)=>{
                if(rule.disabled=='notYet'){
                    group.rules.splice(ruleIndex,1)
                }
            })
        }
    })
    GM_setValue('allRules',allRules)

    console.log('allRules',allRules)
    console.log('enabledRules',enabledRules)

    var searchInput=document.getElementsByClassName('b_searchboxForm')[0]

    {searchInput.insertAdjacentHTML('afterend',`
        <div class='menuBtnBox'>
            <div class='menuBtn'>
                <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24">
                    <path d="M12 22q-2.075 0-3.9-.788t-3.175-2.137T2.788 15.9T2 12t.788-3.9t2.137-3.175T8.1 2.788T12 2t3.9.788t3.175 2.137T21.213 8.1T22 12t-.788 3.9t-2.137 3.175t-3.175 2.138T12 22m0-2q1.35 0 2.6-.437t2.3-1.263L5.7 7.1q-.825 1.05-1.263 2.3T4 12q0 3.35 2.325 5.675T12 20m6.3-3.1q.825-1.05 1.263-2.3T20 12q0-3.35-2.325-5.675T12 4q-1.35 0-2.6.437T7.1 5.7z"/>
                </svg>
            </div>
        </div>
        <div class='menuMainBox'>
            <div class=menuMain>
                <div class='groupCreateBox'>
                    <div class='groupCreateBtn'>
                        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
	                        <path d="M12 21q-.425 0-.712-.288T11 20v-7H4q-.425 0-.712-.288T3 12t.288-.712T4 11h7V4q0-.425.288-.712T12 3t.713.288T13 4v7h7q.425 0 .713.288T21 12t-.288.713T20 13h-7v7q0 .425-.288.713T12 21" />
                        </svg>
                    </div>
                    <div class='groupCreateForm'>
                        <input class='groupCreateInput' placeholder='组名称' value='group${allRules.length+1}'/>
                        <div class='groupCreatingBtn'>
                            <div class='groupCreatingBtnCancel'>取消</div>
                            <div class='groupCreatingBtnConfirm'>确定</div>
                        </div>
                    </div>
                </div>
                <dialog class='deleteDialog'>
                    <div class='deleteDialogContent'>
                        <div class='deleteDialogWarning'></div>
                        <div class='deleteDialogBtn'>
                            <div class='deleteDialogBtnCancel'>取消</div>
                            <div class='deleteDialogBtnConfirm'>确定</div>
                        </div>
                    </div>
                </dialog>
            </div>
        </div>
    `)}

    {    GM_addStyle(`
#sb_form {
    .b_searchboxForm {
        height: 48px;
        width: 650px;
        border: 1px solid #dedede;
        border-radius: 25px;
        box-shadow: 0 2px 4px 1px rgba(0, 0, 0, .09);
        z-index: 4;

        &:hover~.menuBtnBox,
        ~.menuBtnBox:hover {
            width: 75px;
            box-shadow: 0 2px 4px 1px rgba(0, 0, 0, .09);
        }

        &:hover~.menuMainBox,
        &~.menuBtnBox:hover~.menuMainBox {
            width: 700px;
        }
    }

    .menuBtnBox {
        background-color: white;
        height: 48px;
        width: 25px;
        border: 1px solid #dedede;
        border-left-width: 0;
        border-radius: 0 25px 25px 0;
        position: absolute;
        left: calc(100% - 26px);
        top: 0;
        display: flex;
        justify-content: flex-end;
        align-items: center;
        z-index: 3;
        transition: width 300ms, box-shadow 300ms;

        .menuBtn {
            height: 32px;
            width: 32px;
            border-radius: 16px;
            margin-right: 10px;
            display: flex;
            justify-content: center;
            align-items: center;
            cursor: pointer;

            &:hover {
                background-color: #eee;
            }

            svg {
                fill: #6f90f1;
                height: 20px;
            }
        }
    }

    .menuMainBox {
        background-color: white;
        width: 650px;
        padding-top: 48px;
        border: 1px solid #dedede;
        border-radius: 25px;
        position: absolute;
        left: 160px;
        top: 0;
        display: grid;
        grid-template-rows: 0fr;
        transition: 500ms, width 300ms;
        z-index: 2;
        overflow: hidden;

        .menuMain {
            background-color: white;
            height: fit-content;
            max-height: 398px;
            width: 100%;
            overflow: auto;

            .rulesGroup {
                display: grid;
                grid-template-rows: 40px 0fr;
                overflow: hidden;
                transition: grid-template-rows 300ms;

                .rulesGroupHeader {
                    background-color: white;
                    padding: 0 26px;
                    border-bottom: 1px solid #eee;
                    display: flex;
                    justify-content: space-between;

                    .groupHeaderLeft {
                        background-color: white;
                        height: 100%;
                        width: fit-content;
                        display: flex;
                        align-items: center;

                        .groupSwitchBtn {
                            background-color: #416cec;
                            height: 15px;
                            width: 30px;
                            border: 1px solid gray;
                            border-radius: 8px;
                            padding: 0 1px;
                            display: flex;
                            align-items: center;
                            justify-content: flex-end;
                            cursor: pointer;
                            transition: background-color 150ms;

                            .groupSwitchBall {
                                background-color: white;
                                height: 12px;
                                width: 12px;
                                border: 1px solid gray;
                                border-radius: 50%;
                                transition-duration: 150ms;
                            }
                        }

                        .groupNameBox {
                            margin-left: 10px;
                            display: flex;
                            align-items: center;

                            .groupName {
                                background-color: white;
                                color: black;
                                max-width: 260px;
                                margin-left: 10px;
                                overflow: hidden;
                                text-overflow:ellipsis;
                                font-size: 16px;
                            }

                            .groupNameEditBtn {
                                margin-left: 10px;
                                display: flex;
                                align-items: center;
                                cursor: pointer;

                                &:hover {
                                    svg {
                                        fill: #444;
                                    }
                                }

                                svg {
                                    fill: gray;
                                    height: 18px;
                                }
                            }

                            .groupNameEditInput {
                                display: none;
                                margin-left:10px;
                            }

                            .groupNameEditingBtn {
                                display: none;
                                margin-left:10px;

                                div {
                                    height: 22px;
                                    width: 22px;
                                    border-radius: 50%;
                                    display:flex;
                                    align-items: center;

                                    svg {
                                        fill: white;
                                        height: 18px;
                                    }

                                    &.groupNameEditingBtnCancel{
                                        background-color: #ddd;

                                        &:hover {
                                            background-color: #ccc;
                                        }

                                        svg {
                                            fill: none;
                                            stroke: white;
                                        }
                                    }
                                    &.groupNameEditingBtnConfirm{
                                        background-color: #6f90f1;
                                        margin-left: 10px;

                                        &:hover {
                                            background-color: #174AE4;
                                        }
                                    }
                                }
                            }

                            &[data-group-name-editing]{

                                .groupName,
                                .groupNameEditBtn {
                                    display: none;
                                }

                                .groupNameEditInput {
                                    display: inline-block;
                                }

                                .groupNameEditingBtn {
                                    display: flex;
                                }
                            }
                        }
                    }

                    .groupHeaderRight {
                        background-color: white;
                        height: 100%;
                        flex: 1;
                        display: flex;
                        align-items: center;

                        .groupOpenBtn {
                            background-color: #f9f9f9;
                            height: 28px;
                            flex: 1;
                            padding: 0 20px;
                            border-radius: 6px;
                            margin: 0 15px;
                            display: flex;
                            justify-content: space-around;
                            align-items: center;

                            &:hover .groupOpenIconSide {
                                opacity: 1;
                            }

                            svg {
                                fill: #aaa;
                                transition: 200ms;

                                &.groupOpenIconSide {
                                    opacity: 0;
                                    height: 12px;
                                }

                                &.groupOpenCenter {
                                    height: 30px;
                                }
                            }
                        }

                        .groupDeleteBtn {
                            background-color: #ddd;
                            height: 28px;
                            width: 62px;
                            border-radius: 6px;
                            display: flex;
                            justify-content: center;
                            align-items: center;
                            cursor: pointer;

                            &:hover {
                                background-color: #bbb;

                                svg {
                                    fill: #f33;
                                }
                            }

                            svg {
                                fill: #f66;
                                height: 20px;
                                width: 20px;
                            }
                        }
                    }
                }

                .rulesGroupMain {
                    background-color: white;
                    border-bottom: 6px solid #eee;
                    overflow: hidden;

                    .rulesBox {
                        padding: 4px;
                        display: grid;
                        grid-gap: 4px;
                        grid-template-columns: 1fr 1fr;

                        .rule,
                        .ruleCreateBox {
                            background-color: #f9f9f9;
                            height: 30px;
                            box-sizing: border-box;
                            border-radius: 4px;
                            display: flex;
                            justify-content: center;
                            align-items: center;
                        }

                        .rule {
                            padding: 0 25px;
                            justify-content: space-between;


                            .ruleLeftBox {
                                display: flex;
                                align-items: center;

                                .ruleSwitchBtn {
                                    background-color: #416cec;
                                    height: 14px;
                                    width: 14px;
                                    padding: 0;
                                    border: 1px solid gray;
                                    border-radius: 2px;
                                    position: relative;
                                    cursor:porinter;

                                    svg {
                                        fill: white;
                                        height: 16px;
                                        width:16px;
                                        position: absolute;
                                        top: -1px;
                                        left: -1px;
                                        display: inline;
                                    }
                                }

                                .ruleValueBox {
                                    display: flex;
                                    align-items: center;

                                    .ruleValue {
                                        color: black;
                                        font-size: 16px;
                                        max-width:200px;
                                        margin-left: 15px;
                                        overflow:hidden;
                                        text-overflow:ellipsis;
                                    }

                                    .ruleValueEditBtn {
                                        display: none;
                                        margin-left: 10px;
                                        align-items: center;
                                        cursor: pointer;

                                        &:hover {
                                            svg {
                                                fill: #444;
                                            }
                                        }

                                        svg {
                                            fill: gray;
                                            height: 18px;
                                        }
                                    }

                                    .ruleValueEditInput {
                                        display: none;
                                        width:150px;
                                        margin-left: 10px;
                                    }

                                    .ruleValueEditingBtn {
                                        display: none;
                                        margin-left:10px;

                                        div {
                                            height: 22px;
                                            width: 22px;
                                            border-radius: 50%;
                                            display: flex;
                                            align-items: center;

                                            svg {
                                                fill: white;
                                                height: 18px;
                                            }


                                            &.ruleValueEditingBtnCancel {
                                                background-color: #ddd;

                                                &:hover {
                                                    background-color: #ccc;
                                                }

                                                svg {
                                                    fill: none;
                                                    stroke: white;
                                                }
                                            }

                                            &.ruleValueEditingBtnConfirm {
                                                background-color: #6f90f1;
                                                margin-left: 10px;

                                                &:hover {
                                                    background-color: #174AE4;
                                                }
                                            }
                                        }
                                    }

                                    &:hover{
                                        .ruleValueEditBtn{
                                            display:flex;
                                        }
                                    }

                                    &[data-rule-value-editing]{
                                        .ruleValue {
                                            display: none;
                                        }

                                        .ruleValueEditBtn {
                                            display: none;
                                        }

                                        .ruleValueEditInput {
                                            display: inline-block;
                                        }

                                        .ruleValueEditingBtn {
                                            display: flex;
                                        }
                                    }
                                }
                            }

                            .ruleDeleteBtn {
                                display: flex;
                                align-items: center;
                                cursor: pointer;

                                &:hover {
                                    svg {
                                        fill: #f33;
                                    }
                                }

                                svg {
                                    fill: #f66;
                                    height: 20px;
                                    width: 20px;
                                }
                            }

                            &[data-rule-disabled]{
                                .ruleLeftBox .ruleSwitchBtn{
                                    background-color: white;

                                        svg {
                                            display: none;
                                        }
                                }
                            }
                        }

                        .ruleCreateBox{

                            .ruleCreateBtn {
                                height: 100%;
                                width: 100%;
                                display: flex;
                                justify-content: center;
                                align-items: center;
                                cursor: pointer;

                                &:hover {
                                    background-color: #eee;
                                }

                                svg {
                                    fill: #444;
                                    height: 16px;
                                }
                            }

                            .ruleCreateForm {
                                display: none;
                                width: 100%;
                                padding: 0 26px;
                                justify-content: space-between;
                                align-items: center;

                                .ruleCreateInput {
                                    background:#f9f9f9;
                                    height: 20px;
                                    border: 1px solid #bbb;
                                    border-radius: 4px;
                                }

                                .ruleCreatingBtn {
                                    display: flex;
                                    justify-content: center;
                                    align-items: center;

                                    div {
                                        height: 20px;
                                        width: 38px;
                                        border: 1px solid #ddd;
                                        border-radius: 6px;
                                        display: flex;
                                        justify-content: center;
                                        cursor: pointer;
                                        user-select: none;
                                        color: white;
                                        font-size: 14px;
                                    }

                                    .ruleCreatingBtnCancel {
                                        background-color: #ccc;

                                        &:hover {
                                            background-color: #bbb;
                                        }
                                    }

                                    .ruleCreatingBtnConfirm {
                                        background-color: #6f90f1;
                                        margin-left: 10px;

                                        &:hover {
                                            background-color: #416cec;
                                        }
                                    }
                                }
                            }

                            &[data-rule-creating] {
                                .ruleCreateBtn {
                                    display: none;
                                }

                                .ruleCreateForm {
                                    display: flex;
                                }
                            }
                        }
                    }
                }

                &[data-group-open] {
                    grid-template-rows: 40px 1fr;

                    .rulesGroupHeader .groupHeaderRight .groupOpenBtn {
                        .groupOpenIconSide {
                            opacity: 1;

                            &:first-child {
                                transform: rotate(90deg);
                            }

                            &:last-child {
                                transform: rotate(-90deg);
                            }
                        }

                        .groupOpenIconCenter {
                            opacity: 0;
                            transform: translateY(10px)
                        }
                    }
                }

                &[data-group-disabled] {
                    .rulesGroupHeader .groupHeaderLeft {
                        .groupSwitchBtn {
                            background-color: white;

                            .groupSwitchBall {
                                background-color: gray;
                                transform: translate(-15px, 0);
                            }
                        }

                        .groupName {
                            color: gray;
                        }
                    }

                    .rulesGroupMain .rulesBox .rule{
                        .ruleLeftBox {
                            .ruleSwitchBtn{
                                background-color: gray;
                            }

                            .ruleValueBox .ruleValue {
                                color: gray;
                            }
                        }

                        &[data-rule-disabled] .ruleLeftBox .ruleSwitchBtn{
                            background-color:white;
                        }
                    }
                }
            }

            .groupCreateBox {
                height: 34px;
                border-bottom: 6px solid #eee;
                display: flex;
                justify-content: center;
                align-items: center;

                .groupCreateBtn {
                    height: 100%;
                    width: 100%;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    cursor: pointer;

                    &:hover {
                        background-color: #f9f9f9;
                    }

                    svg {
                        fill: #444;
                        height: 20px;
                    }
                }

                .groupCreateForm {
                    display: none;
                    width: 100%;
                    padding: 0 26px;
                    justify-content: space-between;
                    align-items: center;

                    .groupCreateInput {
                        flex: 0.5;
                        height: 20px;
                        border: 1px solid #ddd;
                        border-radius: 4px;
                    }

                    .groupCreatingBtn {
                        display: flex;
                        justify-content: center;
                        align-items: center;

                        div {
                            height: 22px;
                            width: 40px;
                            border: 1px solid #ddd;
                            border-radius: 6px;
                            display: flex;
                            justify-content: center;
                            align-items: center;
                            cursor: pointer;
                            user-select: none;
                            color: white;
                            font-size: 14px;
                        }

                        .groupCreatingBtnCancel {
                            background-color: #ccc;

                            &:hover {
                                background-color: #bbb;
                            }
                        }

                        .groupCreatingBtnConfirm {
                            background-color: #6f90f1;
                            margin-left: 10px;

                            &:hover {
                                background-color: #416cec;
                            }
                        }
                    }
                }

                &[data-group-creating] {
                    .groupCreateBtn {
                        display: none;
                    }

                    .groupCreateForm {
                        display: flex;
                    }
                }
            }

            .deleteDialog{
                height:100px;
                width:300px;
                padding:20px 30px;
                margin-top:150px;
                outline:none;
                border:none;
                border-radius:10px;
                user-select:none;

                .deleteDialogContent{
                    height:100%;
                    width:100%;
                    display:flex;
                    flex-direction: column;
                    justify-content: space-around;


                    .deleteDialogBtn{
                        width:100%;
                        display:flex;
                        justify-content:flex-end;

                        div{
                            height:30px;
                            width:60px;
                            border-radius:6px;
                            display:flex;
                            justify-content:center;
                            align-items:center;
                            cursor:pointer;
                            color:white;

                            &.deleteDialogBtnCancel{
                                background-color:#ccc;

                                &:hover{
                                    background-color:#bbb;
                                }
                            }

                            &.deleteDialogBtnConfirm{
                                background-color:#f66;
                                margin-left:20px;

                                &:hover{
                                    background-color:#f33;
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    &[data-menu-open] {
        .menuBtnBox {
            width: 75px;
            box-shadow: 0 2px 4px 1px rgba(0, 0, 0, .09);

            .menuBtn {
                background-color: #eee;

                svg {
                    fill: #174AE4;
                }
            }
        }

        .menuMainBox {
            width: 700px;
            padding-top: 52px;
            grid-template-rows: 1fr;
            box-shadow: 0 2px 4px 1px rgba(0, 0, 0, .09);
        }
    }
}
    `)}

    var groupCreateBox=document.querySelector('.groupCreateBox')

    // 插入groupHTML
    function injectGroupHTML(groupIndex,groupData){
        groupCreateBox.insertAdjacentHTML('beforebegin',`
            <div id='rulesGroup_#${groupIndex}' class='rulesGroup'>
                <div class='rulesGroupHeader'>
                    <div class='groupHeaderLeft'>
                        <div class='groupSwitchBtn'>
                            <div class=groupSwitchBall></div>
                        </div>
                        <div class='groupNameBox'>
                            <div class='groupName'>${groupData.groupName}</div>
                            <div class='groupNameEditBtn'>
                                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
                                    <path d="M5 21q-.825 0-1.412-.587T3 19V5q0-.825.588-1.412T5 3h8.925l-2 2H5v14h14v-6.95l2-2V19q0 .825-.587 1.413T19 21zm4-6v-4.25l9.175-9.175q.3-.3.675-.45t.75-.15q.4 0 .763.15t.662.45L22.425 3q.275.3.425.663T23 4.4t-.137.738t-.438.662L13.25 15zM21.025 4.4l-1.4-1.4zM11 13h1.4l5.8-5.8l-.7-.7l-.725-.7L11 11.575zm6.5-6.5l-.725-.7zl.7.7z"/>
                                </svg>
                            </div>
                            <input id='groupNameEditInput_#${groupIndex}' class='groupNameEditInput' value='${groupData.groupName}'>
                            <div class='groupNameEditingBtn'>
                                <div class='groupNameEditingBtnCancel'>
                                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
                                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 18h3.75a5.25 5.25 0 1 0 0-10.5H5M7.5 4L4 7.5L7.5 11"/>
                                    </svg>
                                </div>
                                <div class='groupNameEditingBtnConfirm'>
                                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
                                    	<path d="m9.55 15.15l8.475-8.475q.3-.3.7-.3t.7.3t.3.713t-.3.712l-9.175 9.2q-.3.3-.7.3t-.7-.3L4.55 13q-.3-.3-.288-.712t.313-.713t.713-.3t.712.3z" />
                                    </svg>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class='groupHeaderRight'>
                        <div class='groupOpenBtn'>
                                <svg class='groupOpenIconSide' xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
                                    <path d="m14.475 12l-7.35-7.35q-.375-.375-.363-.888t.388-.887t.888-.375t.887.375l7.675 7.7q.3.3.45.675t.15.75t-.15.75t-.45.675l-7.7 7.7q-.375.375-.875.363T7.15 21.1t-.375-.888t.375-.887z"/>
                                </svg>
                                <svg class='groupOpenIconCenter' xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
                                    <path d="M6 14q-.825 0-1.412-.587T4 12t.588-1.412T6 10t1.413.588T8 12t-.587 1.413T6 14m6 0q-.825 0-1.412-.587T10 12t.588-1.412T12 10t1.413.588T14 12t-.587 1.413T12 14m6 0q-.825 0-1.412-.587T16 12t.588-1.412T18 10t1.413.588T20 12t-.587 1.413T18 14"/>
                                </svg>
                                <svg class='groupOpenIconSide' xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
                                    <path d="m9.55 12l7.35 7.35q.375.375.363.875t-.388.875t-.875.375t-.875-.375l-7.7-7.675q-.3-.3-.45-.675t-.15-.75t.15-.75t.45-.675l7.7-7.7q.375-.375.888-.363t.887.388t.375.875t-.375.875z"/>
                                </svg>
                        </div>
                        <div class='groupDeleteBtn'>
                            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
                                <path d="M7 21q-.825 0-1.412-.587T5 19V6H4V4h5V3h6v1h5v2h-1v13q0 .825-.587 1.413T17 21zM17 6H7v13h10zM9 17h2V8H9zm4 0h2V8h-2zM7 6v13z"/>
                            </svg>
                        </div>
                    </div>
                </div>
                <div class='rulesGroupMain'>
                    <div class='rulesBox'>
                        <div class='ruleCreateBox'>
                            <div class='ruleCreateBtn'>
                                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
	                                <path d="M12 21q-.425 0-.712-.288T11 20v-7H4q-.425 0-.712-.288T3 12t.288-.712T4 11h7V4q0-.425.288-.712T12 3t.713.288T13 4v7h7q.425 0 .713.288T21 12t-.288.713T20 13h-7v7q0 .425-.288.713T12 21" />
                                </svg>
                            </div>
                            <div class='ruleCreateForm'>
                                <input id='ruleCreateInput_#${groupIndex}' class='ruleCreateInput'/>
                                <div class='ruleCreatingBtn'>
                                    <div class='ruleCreatingBtnCancel'>取消</div>
                                    <div class='ruleCreatingBtnConfirm'>确定</div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        `)
    }
// 插入ruleHTNL
function injectRuleHTML(ruleCreateBox,groupIndex,ruleIndex,ruleData){
    ruleCreateBox.insertAdjacentHTML('beforebegin',`
            <div id='rule_#${groupIndex}_#${ruleIndex}' class='rule'>
                <div class=ruleLeftBox>
                    <div class='ruleSwitchBtn'>
                        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
	                        <path d="m9.55 18l-5.7-5.7l1.425-1.425L9.55 15.15l9.175-9.175L20.15 7.4z" />
                        </svg>
                    </div>
                    <div class='ruleValueBox'>
                        <div class='ruleValue'>${ruleData.value}</div>
                        <div class='ruleValueEditBtn'>
                            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
                                <path d="M5 21q-.825 0-1.412-.587T3 19V5q0-.825.588-1.412T5 3h8.925l-2 2H5v14h14v-6.95l2-2V19q0 .825-.587 1.413T19 21zm4-6v-4.25l9.175-9.175q.3-.3.675-.45t.75-.15q.4 0 .763.15t.662.45L22.425 3q.275.3.425.663T23 4.4t-.137.738t-.438.662L13.25 15zM21.025 4.4l-1.4-1.4zM11 13h1.4l5.8-5.8l-.7-.7l-.725-.7L11 11.575zm6.5-6.5l-.725-.7zl.7.7z"/>
                            </svg>
                        </div>
                        <input id='ruleValueEditInput_#${groupIndex}_#${ruleIndex}' class='ruleValueEditInput' value='${ruleData.value}'>
                        <div class='ruleValueEditingBtn'>
                            <div class=ruleValueEditingBtnCancel>
                                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 18h3.75a5.25 5.25 0 1 0 0-10.5H5M7.5 4L4 7.5L7.5 11"/>
                                </svg>
                            </div>
                            <div class=ruleValueEditingBtnConfirm>
                                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
                                	<path d="m9.55 15.15l8.475-8.475q.3-.3.7-.3t.7.3t.3.713t-.3.712l-9.175 9.2q-.3.3-.7.3t-.7-.3L4.55 13q-.3-.3-.288-.712t.313-.713t.713-.3t.712.3z" />
                                </svg>
                            </div>
                        </div>
                    </div>
                </div>
                <div class='ruleDeleteBtn'>
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
                        <path d="M7 21q-.825 0-1.412-.587T5 19V6H4V4h5V3h6v1h5v2h-1v13q0 .825-.587 1.413T17 21zM17 6H7v13h10zM9 17h2V8H9zm4 0h2V8h-2zM7 6v13z"/>
                    </svg>
                </div>
            </div>
        `)
    }

// 事件绑定和处理-展开总菜单
var sb_form=document.querySelector('#sb_form')
function menuSwitch(){
    sb_form.hasAttribute('data-menu-open')
        ? sb_form.removeAttribute('data-menu-open')
    : sb_form.setAttribute('data-menu-open','')
}
var menuBtn=sb_form.querySelector('.menuBtn')
menuBtn.addEventListener('click',menuSwitch,false)
// 事件处理-激活规则组
function groupSwitch(groupIndex,groupElement){
    return function(){
        if(groupElement.hasAttribute('data-group-disabled')){
            // 处理数据
            allRules[groupIndex].disabled=false
            allRules[groupIndex].rules.forEach((rule)=>{
                if(!rule.disabled){
                    enabledRules.push(rule.value)
                }
            })
            GM_setValue('allRules',allRules)
            GM_setValue('enabledRules',enabledRules)
            // 处理前端
            groupElement.removeAttribute('data-group-disabled')
        }else{
            // 处理数据
            allRules[groupIndex].disabled=true
            allRules[groupIndex].rules.forEach((rule)=>{
                var index=enabledRules.indexOf(rule.value)
                if(index!==-1){
                    enabledRules.splice(index,1)
                }
            })
            GM_setValue('allRules',allRules)
            GM_setValue('enabledRules',enabledRules)
            groupElement.setAttribute('data-group-disabled','')
        }
    }
}
// 事件处理-重命名规则组
function groupNameEdit(groupNameBox){
    return function(){
        // 处理前端
        if(!groupNameBox.hasAttribute('data-group-name-editing')){
            groupNameBox.setAttribute('data-group-name-editing','')
        }
    }
}
// 事件处理-取消重命名
function groupNameEditCancel(groupIndex,groupNameEditInput,groupNameBox){
    return function(){
        // 处理前端
        groupNameEditInput.value=document.querySelector(`#rulesGroup_\\#${groupIndex} .groupName`).innerText
        if(groupNameBox.hasAttribute('data-group-name-editing')){
            groupNameBox.removeAttribute('data-group-name-editing')
        }
    }
}
// 事件处理-确定重命名
function groupNameEditConfirm(groupIndex,groupName,groupNameBox){
    return function(event){
        if(event?.key=='Enter' || event.type=='click'){
            var newGroupName=document.querySelector(`#groupNameEditInput_\\#${groupIndex}`).value
            // 处理数据
            allRules[groupIndex].groupName=newGroupName
            GM_setValue('allRules',allRules)
            // 处理前端
            groupName.innerText=newGroupName
            if(groupNameBox.hasAttribute('data-group-name-editing')){
                groupNameBox.removeAttribute('data-group-name-editing')
            }
            event.preventDefault()
        }
    }
}
// 事件处理-展开规则组
function groupOpen(groupElement){
    return function(){
        // 处理前端
        groupElement.hasAttribute('data-group-open')
            ? groupElement.removeAttribute('data-group-open')
        : groupElement.setAttribute('data-group-open','')
    }
}
// 事件处理-激活规则
function ruleSwitch(groupIndex,ruleIndex,ruleElement){
    return function(){
        if(ruleElement.hasAttribute('data-rule-disabled')){
            // 处理数据
            allRules[groupIndex].rules[ruleIndex].disabled=false
            enabledRules.push(allRules[groupIndex].rules[ruleIndex].value)
            GM_setValue('allRules',allRules)
            GM_setValue('enabledRules',enabledRules)
            // 处理前端
            ruleElement.removeAttribute('data-rule-disabled')
        } else{
            // 处理数据
            allRules[groupIndex].rules[ruleIndex].disabled=true
            var index=enabledRules.indexOf(allRules[groupIndex].rules[ruleIndex].value)
            if(index!==-1){
                enabledRules.splice(index,1)
            }
            GM_setValue('allRules',allRules)
            GM_setValue('enabledRules',enabledRules)
            // 处理前端
            ruleElement.setAttribute('data-rule-disabled','')
        }
    }
}
// 事件处理-修改规则
function ruleValueEdit(ruleValueBox){
    return function(){
        // 处理前端
        if(!ruleValueBox.hasAttribute('data-rule-value-editing'))
        {ruleValueBox.setAttribute('data-rule-value-editing','')}
    }
}
// 事件处理-取消修改
function ruleValueEditCancel(groupIndex,ruleIndex,ruleValueEditInput,ruleValueBox){
    return function(){
        // 处理前端
        ruleValueEditInput.value=document.querySelector(`#rule_\\#${groupIndex}_\\#${ruleIndex} .ruleValue`).innerText
        if(ruleValueBox.hasAttribute('data-rule-value-editing')){
            ruleValueBox.removeAttribute('data-rule-value-editing')
        }
    }
}
// 事件处理-确定修改
function ruleValueEditConfirm(groupIndex,ruleIndex,ruleValue,ruleValueBox){
    return function(event){
        if(event?.key=='Enter'||event.type=='click'){
            // 处理数据
            var newRuleValue=document.querySelector(`#ruleValueEditInput_\\#${groupIndex}_\\#${ruleIndex}`).value
            var index=enabledRules.indexOf(allRules[groupIndex].rules[ruleIndex].value)
            allRules[groupIndex].rules[ruleIndex].value=newRuleValue
            if(index!=-1){
                enabledRules[index]=newRuleValue
            }
            GM_setValue('allRules',allRules)
            GM_setValue('enabledRules',enabledRules)
            // 处理前端
            ruleValue.innerText=newRuleValue
            if(ruleValueBox.hasAttribute('data-rule-value-editing')){
                ruleValueBox.removeAttribute('data-rule-value-editing')
            }
            event.preventDefault()
        }
    }
}
// 事件处理-展示删除对话框
var deleteDialog=document.querySelector('.deleteDialog')
var deleteDialogWarning=document.querySelector('.deleteDialogWarning')
function showDeleteDialog(groupIndex,ruleIndex){
    return function(){
        deleteDialogWarning.innerText = ruleIndex == undefined
            ? `确定删除规则组${document.querySelector(`#rulesGroup_\\#${groupIndex} .groupName`).innerText}吗?`
                : `确定删除规则${allRules[groupIndex].rules[ruleIndex].value}吗?`
            deleteDialog.setAttribute('data-group-index',groupIndex)
            deleteDialog.setAttribute('data-rule-index',ruleIndex)
            deleteDialog.showModal()
        }
    }
// 事件绑定和处理-取消删除
function deleteCancel(){
    deleteDialog.close()
}
var deleteDialogBtnCancel=deleteDialog.querySelector('.deleteDialogBtnCancel')
deleteDialogBtnCancel.addEventListener('click',deleteCancel,false)
// 事件绑定和处理-确定删除
function deleteConfirm(){
    var deleteDialog=document.querySelector('.deleteDialog')
    var groupIndex=deleteDialog.dataset.groupIndex
    var ruleIndex=deleteDialog.dataset.ruleIndex
    if(ruleIndex=='undefined'){
        // 处理数据
        allRules[groupIndex].disabled='notYet'
        allRules[groupIndex].rules.forEach((rule)=>{
            var index=enabledRules.indexOf(rule.value)
            if(index!==-1){
                enabledRules.splice(index,1)
            }
        })
        GM_setValue('allRules',allRules)
        GM_setValue('enabledRules',enabledRules)
        // 处理前端
        var groupElement=document.querySelector(`#rulesGroup_\\#${groupIndex}`)
        groupElement.style.display='none'
    } else {
        // 处理数据
        allRules[groupIndex].rules[ruleIndex].disabled='notYet'
        var index=enabledRules.indexOf(allRules[groupIndex].rules[ruleIndex].value)
        if(index!==-1){
            enabledRules.splice(index,1)
        }
        GM_setValue('allRules',allRules)
        GM_setValue('enabledRules',enabledRules)
        // 处理前端
        var ruleElement=document.querySelector(`#rule_\\#${groupIndex}_\\#${ruleIndex}`)
        ruleElement.style.display='none'
    }
    // 处理前端
    deleteDialog.close()
}
var deleteDialogBtnConfirm=deleteDialog.querySelector('.deleteDialogBtnConfirm')
deleteDialogBtnConfirm.addEventListener('click',deleteConfirm,false)

// 全部事件绑定-规则
function ruleAddEventListener(ruleElement,groupIndex,ruleIndex){
    // 事件绑定-开关规则
    var ruleSwitchBtn=ruleElement.querySelector('.ruleSwitchBtn')
    ruleSwitchBtn.addEventListener('click',ruleSwitch(groupIndex,ruleIndex,ruleElement),false)
    // 事件绑定-修改规则
    var ruleValueBox=ruleElement.querySelector('.ruleValueBox')
    var ruleValueEditBtn=ruleElement.querySelector('.ruleValueEditBtn')
    ruleValueEditBtn.addEventListener('click',ruleValueEdit(ruleValueBox),false)
    // 事件绑定-取消修改
    var ruleValueEditInput=ruleElement.querySelector('.ruleValueEditInput')
    var ruleValueEditingBtnCancel=ruleElement.querySelector('.ruleValueEditingBtnCancel')
    ruleValueEditingBtnCancel.addEventListener('click',ruleValueEditCancel(groupIndex,ruleIndex,ruleValueEditInput,ruleValueBox),false)
    // 事件绑定-确定修改
    var ruleValue=ruleElement.querySelector('.ruleValue')
    var ruleValueEditingBtnConfirm=ruleElement.querySelector('.ruleValueEditingBtnConfirm')
    ruleValueEditingBtnConfirm.addEventListener('click',ruleValueEditConfirm(groupIndex,ruleIndex,ruleValue,ruleValueBox),false)
    ruleValueEditInput.addEventListener('keydown',ruleValueEditConfirm(groupIndex,ruleIndex,ruleValue,ruleValueBox),false)
    // 事件绑定-删除规则
    var ruleDeleteBtn=ruleElement.querySelector('.ruleDeleteBtn')
    ruleDeleteBtn.addEventListener('click',showDeleteDialog(groupIndex,ruleIndex),false)
}
// 事件处理-创建规则
function ruleCreate(ruleCreateBox){
    return function(){
        // 处理前端
        if(!ruleCreateBox.hasAttribute('data-rule-creating')){
            ruleCreateBox.setAttribute('data-rule-creating','')
        }
    }
}
// 事件处理-取消创建
function ruleCreateCancel(ruleCreateInput,ruleCreateBox){
    return function(){
        // 处理前端
        ruleCreateInput.value=''
        if(ruleCreateBox.hasAttribute('data-rule-creating')){
            ruleCreateBox.removeAttribute('data-rule-creating','')
        }
    }
}
// 事件处理-确定创建
function ruleCreateConfirm(groupIndex,ruleCreateInput,ruleCreateBox){
    return function(event){
        if(event?.key=='Enter'||event.type=='click'){
            // 处理数据
            var ruleData={
                value:document.querySelector(`#ruleCreateInput_\\#${groupIndex}`).value,
                disabled:false,
            }
            allRules[groupIndex].rules.push(ruleData)
            enabledRules.push(ruleData.value)
            GM_setValue('allRules',allRules)
            GM_setValue('enabledRules',enabledRules)
            var ruleIndex=allRules[groupIndex].rules.length-1
            // 创建新规则
            injectRuleHTML(ruleCreateBox,groupIndex,ruleIndex,ruleData)
            var ruleElement=document.querySelector(`#rule_\\#${groupIndex}_\\#${ruleIndex}`)
            ruleAddEventListener(ruleElement,groupIndex,ruleIndex)
            // 处理前端
            ruleCreateInput.value=''
            if(ruleCreateBox.hasAttribute('data-rule-creating')){
                ruleCreateBox.removeAttribute('data-rule-creating','')
            }
            event.preventDefault()
        }
    }
}

// 全部事件绑定-规则组
function groupAddEventListener(groupElement,groupIndex,ruleCreateBox){
    // 开关规则组
    var groupSwitchBtn=groupElement.querySelector('.groupSwitchBtn')
    groupSwitchBtn.addEventListener('click',groupSwitch(groupIndex,groupElement),false)
    // 重命名规则组
    var groupNameBox=groupElement.querySelector('.groupNameBox')
    var groupNameEditBtn=groupElement.querySelector('.groupNameEditBtn')
    groupNameEditBtn.addEventListener('click',groupNameEdit(groupNameBox),false)
    // 取消重命名
    var groupNameEditInput=groupElement.querySelector('.groupNameEditInput')
    var groupNameEditingBtnCancel=groupElement.querySelector('.groupNameEditingBtnCancel')
    groupNameEditingBtnCancel.addEventListener('click',groupNameEditCancel(groupIndex,groupNameEditInput,groupNameBox),false)
    // 确定重命名
    var groupName=groupElement.querySelector('.groupName')
    var groupNameEditingBtnConfirm=groupElement.querySelector('.groupNameEditingBtnConfirm')
    groupNameEditingBtnConfirm.addEventListener('click',groupNameEditConfirm(groupIndex,groupName,groupNameBox),false)
    groupNameEditInput.addEventListener('keydown',groupNameEditConfirm(groupIndex,groupName,groupNameBox),false)
    // 展开规则组
    var groupOpenBtn=groupElement.querySelector('.groupOpenBtn')
    groupOpenBtn.addEventListener('click',groupOpen(groupElement),false)
    // 删除规则组
    var groupDeleteBtn=groupElement.querySelector('.groupDeleteBtn')
    groupDeleteBtn.addEventListener('click',showDeleteDialog(groupIndex),false)
    // 创建规则
    var ruleCreateBtn=groupElement.querySelector('.ruleCreateBtn')
    ruleCreateBtn.addEventListener('click',ruleCreate(ruleCreateBox),false)
    // 取消创建
    var ruleCreateInput=groupElement.querySelector('.ruleCreateInput')
    var ruleCreatingBtnCancel=groupElement.querySelector('.ruleCreatingBtnCancel')
    ruleCreatingBtnCancel.addEventListener('click',ruleCreateCancel(ruleCreateInput,ruleCreateBox),false)
    // 确定创建
    var ruleCreatingBtnConfirm=groupElement.querySelector('.ruleCreatingBtnConfirm')
    ruleCreatingBtnConfirm.addEventListener('click',ruleCreateConfirm(groupIndex,ruleCreateInput,ruleCreateBox),false)
    ruleCreateInput.addEventListener('keydown',ruleCreateConfirm(groupIndex,ruleCreateInput,ruleCreateBox),false)
}
// 事件绑定和处理-创建规则组
function groupCreate(){
    if(!groupCreateBox.hasAttribute('data-group-creating')){
        groupCreateBox.setAttribute('data-group-creating','')
    }
}
var groupCreateBtn=groupCreateBox.querySelector('.groupCreateBtn')
groupCreateBtn.addEventListener('click',groupCreate,false)
// 事件绑定和处理-取消创建
var groupCreateInput=groupCreateBox.querySelector('.groupCreateInput')
function groupCreateCancel(){
    groupCreateInput.value=`group${allRules.length+1}`
        if(groupCreateBox.hasAttribute('data-group-creating')){
            groupCreateBox.removeAttribute('data-group-creating')
        }
    }
var groupCreatingBtnCancel=document.querySelector('.groupCreatingBtnCancel')
groupCreatingBtnCancel.addEventListener('click',groupCreateCancel,false)
// 事件绑定和处理-确定创建
function groupCreateConfirm(event){
    if(event?.key=='Enter'||event.type=='click'){
        // 处理数据
        var groupData={
            groupName:groupCreateBox.querySelector('.groupCreateInput').value,
            disabled:false,
            rules:[]
        }
        allRules.push(groupData)
        GM_setValue('allRules',allRules)
        var groupIndex=allRules.length-1
        // 创建新规则组
        injectGroupHTML(groupIndex,groupData)
        var groupElement=document.querySelector(`#rulesGroup_\\#${groupIndex}`)
        var ruleCreateBox=groupElement.querySelector(`.ruleCreateBox`)
        groupAddEventListener(groupElement,groupIndex,ruleCreateBox)
        // 处理前端
        groupCreateInput.value=`group${groupIndex+2}`
            if(groupCreateBox.hasAttribute('data-group-creating')){
                groupCreateBox.removeAttribute('data-group-creating')
            }
            event.preventDefault()
        }
    }
var groupCreatingBtnConfirm=document.querySelector('.groupCreatingBtnConfirm')
groupCreatingBtnConfirm.addEventListener('click',groupCreateConfirm,false)
groupCreateInput.addEventListener('keydown',groupCreateConfirm,false)
// 生成规则组
allRules.forEach((groupData,groupIndex)=>{
    // 插入规则组
    injectGroupHTML(groupIndex,groupData)
    // 获取规则组元素
    var groupElement=document.querySelector(`#rulesGroup_\\#${groupIndex}`)
    if(groupData.disabled){groupElement.setAttribute('data-group-disabled','')}
    // 生成规则
    var ruleCreateBox=groupElement.querySelector(`.ruleCreateBox`)
    groupData.rules.forEach((ruleData,ruleIndex)=>{
        // 插入规则
        injectRuleHTML(ruleCreateBox,groupIndex,ruleIndex,ruleData)
        // 获取规则元素
        var ruleElement=groupElement.querySelector(`#rule_\\#${groupIndex}_\\#${ruleIndex}`)
        if(ruleData.disabled){ruleElement.setAttribute('data-rule-disabled','')}
        // 绑定规则事件
        ruleAddEventListener(ruleElement,groupIndex,ruleIndex)
    })
    // 绑定规则组事件
    groupAddEventListener(groupElement,groupIndex,ruleCreateBox)
})






























// Your code here...
})();