AcWing美化

美化AcWing界面

目前為 2023-05-02 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         AcWing美化
// @version      3
// @description  美化AcWing界面
// @author       北极小狐
// @match        https://www.acwing.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=acwing.com
// @grant        none
// @run-at       document-start
// @require      https://cdn.bootcdn.net/ajax/libs/turndown/7.1.1/turndown.min.js
// @license      MIT
// @namespace    https://greasyfork.org/users/747162
// ==/UserScript==

// 调整样式
function loadCssCode(code){
    var style = document.createElement('style');
    style.type = 'text/css';
    style.rel = 'stylesheet';
    style.appendChild(document.createTextNode(code));
    var head = document.getElementsByTagName('head')[0];
    head.appendChild(style);
}
loadCssCode(`
/* 宽度自适应 */
.container {
    width: auto !important;
}
/* 去除没用的图标 */
.file-explorer-main-field-item.file-explorer-main-field-item-desktop {
    width: 0px;
    height: 0px;
    overflow: hidden;
}
/* 背景bing壁纸 */
#acwing_body {
    background: white url(https://bingw.jasonzeng.dev) fixed !important;
}
/* 其他 */
.fs-gui-taskbar {
    height: 3.5vh !important;
    background-color: #dde1e5  !important;
}
.fs-gui-taskbar-widgets-apps-item > img {
    height: 2.2vh !important;
    width: 2.2vh !important;
    margin: 0.5vh 0.5vh 0.5vh 0.5vh !important;
}
.fs-gui-taskbar-widgets-clock{
    width: 0px  !important;
    height: 0px  !important;
    overflow: hidden  !important;
}
.fs-gui-taskbar-widgets-apps-item {
    margin-right: 2vh !important;
}
#fs-gui-taskbar-search-field {
    font-size: 1.3vh !important;
}
.fs-gui-taskbar-search-icon {
    font-size: 1.6vh !important;
    top: 0.95vh !important;
    left: 4.3vh !important;
}
footer#acwing_footer .copyright {
    color: #fff;
}
footer#acwing_footer .copyright a, .links a, footer#acwing_footer .container {
    color: #fff;
}
.fs-gui-taskbar-begin {
    height: 3vh !important;
    width: 3vh !important;
    margin: 0.2vh !important;
    border-radius: 60%;
    background-color: #fffefe80 !important;
}
button.fs-gui-taskbar-begin.pull-left.btn.btn-default img {
    width: 83% !important;
}
#fs-gui-taskbar-search-field {
    height: 90% !important;
    margin: 0.15vh;
    border-radius: 100px;
    border-width: 0.2vh;
    border-style: solid;
    border-color: #c7d2dd;
}
#fs-gui-taskbar-search-field:focus-visible {
    border-width: 0.2vh;
    border-style: solid;
    border-color: #8bb2d9;
    outline: -webkit-focus-ring-color auto 0px;
}

/* 复制按钮 */
pre.hljs {
    display: flex;
    justify-content: space-between;
}
span.copy-button {
    cursor: pointer;
    background-color: #e6e6e6;
    color: #727378;
    height: 2vh;
    font-size: 1.3vh;
    border-radius: 0.3rem;
    padding: 1px 5px;
    margin: 5px;
    box-shadow: 0 0 1px #0000004d;
}
span.copy-button.copied {
    background-color: #07e65196;
    color: #104f2b;
}
/* html2md */
.html2md-panel {
    display: flex;
    justify-content: flex-end;
}
button.html2mdButton {
    height: 3vh;
    width: 3vh;
}
button.html2mdButton {
    cursor: pointer;
    background-color: #e6e6e6;
    color: #727378;
    height: 3vh;
    width: auto;
    font-size: 1.3vh;
    border-radius: 0.3rem;
    border: none;
    padding: 1px 5px;
    margin: 5px;
    box-shadow: 0 0 1px #0000004d;
}
button.html2mdButton.copied {
    background-color: #07e65196;
    color: #104f2b;
}
button.html2mdButton.html2md-view.mdViewed {
    background-color: #ff980057;
    color: #5a3a0c;
}
/* 打卡框 */
.ui.bottom.attached.tab.segment.active {
    padding: 0px;
}
/* 视频bar */
.embed-responsive {
    padding-bottom: 70.25%;
}
.player_bar {
    margin-top: 2px;
    height: 10vh;
    display: flex;
    justify-content: space-between;
}
.player_bar_go {
    cursor: pointer;
    width: 5vh;
    color: #999;
    height: auto;
    font-size: 1.3vh;
    border-radius: 0.3rem;
    padding: 1px 5px;
    margin: 5px;
    border: none;
    background: linear-gradient(-225deg,#d5dbe4,#f8f8f8);
    box-shadow: inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 2px 1px rgba(30,35,90,.4);
    display: flex;
    justify-content: center;
    align-items: center;
}
button#player_bar_list_add_new_item_btn {
    height: 100%;
    width: 5vh;
    background-color: #e6e6e6;
    color: #727378;
    font-size: 1.3vh;
    border-radius: 0.3rem;
    padding: 1px 5px;
    margin: 5px;
    border: none;
    box-shadow: 0 0 1px #0000004d;
}
div#player_bar_list {
    display: grid;
    width: 100%;
    height: 14vh;
}
label.player_bar_ul_li_text {
    max-width: 100%;
    height: 4vh;
    overflow-x: auto;
    font-weight: 400;
    margin: 2px 4px;
    box-shadow: 0 0 1px #0000004d;
}
ul#player_bar_ul li button {
    background-color: #e6e6e6;
    color: #727378;
    height: 2vh;
    font-size: 1.3vh;
    border-radius: 0.3rem;
    padding: 1px 5px;
    margin: 5px;
    border: none;
    box-shadow: 0 0 1px #0000004d;
}
ul#player_bar_ul {
    list-style-type: none;
    padding-inline-start: 0px;
    display: flex;
    overflow-x: auto;
    max-width: 100%;
    margin: 0px;
}
ul#player_bar_ul li {
    width: 8vh;
    display: grid;
    overflow: hidden;
    box-shadow: 0 0 1px #0000004d;
    margin: 4px 3px;
    min-width: 100px;
}
li:hover {
    background-color: #FFF3E0;
}
ul#player_bar_ul::-webkit-scrollbar {
  width: 5px;
  height: 8px;
}
ul#player_bar_ul::-webkit-scrollbar-thumb {
    border-radius: 2px;
    border: 1px solid rgba(56,56,56,.3411764706);
    background-clip: padding-box;
    background-color: #a29bb84a;
    background-image: -webkit-linear-gradient(45deg,hsla(0deg,0%,100%,.4) 25%,transparent 0,transparent 50%,hsla(0deg,0%,100%,.4) 0,hsla(0deg,0%,100%,.4) 75%,transparent 0,transparent);
}
ul#player_bar_ul::-webkit-scrollbar-track {
  background-color: #f1f1f1;
  border-radius: 5px;
}

label.player_bar_ul_li_text::-webkit-scrollbar {
  width: 5px;
  height: 7px;
  background-color: #aaa;
}
label.player_bar_ul_li_text::-webkit-scrollbar-thumb {
    border: 1px solid rgba(56,56,56,.3411764706);
    background-clip: padding-box;
    background-color: #a29bb84a;
}
label.player_bar_ul_li_text::-webkit-scrollbar-track {
  background-color: #f1f1f1;
}
.player_bar_list_add_div {
    display: flex;
    height: 3vh;
}
input#player_bar_list_add_input {
    width: 100%;
    height: 100%;
    background-color: #ffffff;
    color: #727378;
    font-size: 1.3vh;
    border-radius: 0.3rem;
    padding: 1px 5px;
    margin: 5px 5px 5px 0px;
    border: 1px solid #007e7e;
    box-shadow: 0 0 1px #0000004d;
}
input#player_bar_list_add_input:focus-visible {
    border-width: 0.2vh;
    border-style: solid;
    border-color: #8bb2d9;
    outline: -webkit-focus-ring-color auto 0px;
}
button#player_bar_list_add_new_item_btn.added,div#player_bar_go.gone {
    background-color: #07e65196;
    color: #104f2b;
}
`);

// 添加复制按钮
function addCopy(){
    // 获取所有 .hljs 中的代码块
    const codeBlocks = document.querySelectorAll('.hljs code');

    // 循环遍历每个代码块
    codeBlocks.forEach(codeBlock => {
        // 创建一个 span 元素,并设置样式
        const beforeButton = document.createElement('span');
        beforeButton.textContent = "Copy";
        beforeButton.className = 'copy-button';
        // 在代码块前面插入按钮
        codeBlock.parentNode.insertBefore(beforeButton, codeBlock.nextSibling);
        // 为按钮添加点击事件
        beforeButton.addEventListener('click', event => {
            // 创建临时文本域
            const textarea = document.createElement('textarea');
            textarea.value = codeBlock.textContent.replace(/\n+$/, '');
            document.body.appendChild(textarea);
            textarea.select();
            document.execCommand('copy');
            document.body.removeChild(textarea);


            // 更新复制按钮文本
            beforeButton.classList.add('copied');
            beforeButton.textContent = "Copied";
            setTimeout(() => {
                beforeButton.classList.remove('copied');
                beforeButton.textContent = "Copy";
            }, 2000);
        }, false);
    });
}

// 移除复制按钮
function removeCopy(){
    var elements = document.querySelectorAll('.hljs .copy-button');
    for (var i = 0; i < elements.length; i++) {
        elements[i].parentNode.removeChild(elements[i]);
    }

}

document.addEventListener('DOMContentLoaded', function() {
    // 让某些链接在新窗口打开
    var regExps = [
        /常用代码模板/,
        /example/,
        /test/
    ];
    var aTags = document.getElementsByTagName('a');
    for (var i = 0; i < aTags.length; i++) {
        for (var j = 0; j < regExps.length; j++) {
            if (regExps[j].test(aTags[i].textContent)) {
                aTags[i].setAttribute('target', '_blank');
                break;
            }
        }
    }
    // 自动恢复进度条
    setTimeout(function() {
        try {
            document.querySelector('.play-jump').click();
        } catch (error) {
            // do nothing
        }
    }, 3000);
    // 复制按钮
    addCopy();
    // 移除广告元素
    let ADidADList = ["1024-activity","test"];
    ADtraverseDom(document.body);
    function ADtraverseDom(node) {
        if (node.nodeType === Node.ELEMENT_NODE && ADidADList.includes(node.id)) {
            node.parentNode.removeChild(node);
        } else {
            for (let i = 0; i < node.childNodes.length; i++) {
                ADtraverseDom(node.childNodes[i]);
            }
        }
    }
    // 修改打卡页代码框默认高度
    var element = document.getElementById("martor-content");
    if(element){
        var style = window.getComputedStyle(element);
        element.style.height = "55vh";
    }
});

// MarkDown

document.addEventListener('DOMContentLoaded', function() {
    let debug = false; // whether to enable on editor

    let turndownService = new TurndownService();

    turndownService.keep(['del']);

    // code block
    turndownService.addRule('pre', {
        filter: 'pre',
        replacement: function (content, node) {
            let t = $(node).attr("class").split(/\s+/).slice(-1);
            if (t == "hljs") t = "";
            return "```" + t + "\n" + content.trim() + "\n```";
        }
    });

    // remove <script> math
    turndownService.addRule('remove-script', {
        filter: function (node, options) {
            return node.tagName.toLowerCase() == "script" && node.type.startsWith("math/tex");
        },
        replacement: function (content, node) {
            return "";
        }
    });

    // inline math
    turndownService.addRule('inline-math', {
        filter: function (node, options) {
            return node.tagName.toLowerCase() == "span" && node.className == "MathJax";
        },
        replacement: function (content, node) {
            return "$ " + $(node).next().text() + " $";
        }
    });

    // block math
    turndownService.addRule('block-math', {
        filter: function (node, options) {
            return node.tagName.toLowerCase() == "div" && node.className == "MathJax_Display";
        },
        replacement: function (content, node) {
            return "\n$$\n" + $(node).next().text() + "\n$$\n";
        }
    });

    // add buttons
    $("div[data-tab='preview-tab-content']").each(function() {
        if (debug || $(this).prev().attr('data-tab') != "editor-tab-content")
            $(this).before(
                "<div class='html2md-panel'> <button class='html2mdButton html2md-view'>MarkDown视图</button> <button class='html2mdButton html2md-cb'>Copy</button> </div>"
            );
    });

    $(".html2md-cb").click(function() {
        let target = $(this).parent().next().get(0);
        if (!target.markdown){
            removeCopy();
            target.markdown = turndownService.turndown($(target).html());
            addCopy();
        }
        const textarea = document.createElement('textarea');
        textarea.value = target.markdown;
        document.body.appendChild(textarea);
        textarea.select();
        document.execCommand('copy');
        document.body.removeChild(textarea);
        // console.log(markdown);
        $(this).addClass("copied");
        $(this).text("Copied");
        // 更新复制按钮文本
        setTimeout(() => {
            $(this).removeClass("copied");
            $(this).text("Copy");
        }, 2000);
    });

    $(".html2md-view").click(function() {
        let target = $(this).parent().next().get(0);
        if (target.viewmd) {
            target.viewmd = false;
            $(this).text("MarkDown视图");
            $(this).removeClass("mdViewed");
            $(target).html(target.original_html);
            addCopy();
        } else {
            target.viewmd = true;
            removeCopy();
            if (!target.original_html)
                target.original_html = $(target).html();
            if (!target.markdown)
                target.markdown = turndownService.turndown($(target).html());
            $(this).text("原始内容");
            $(this).addClass("mdViewed");
            $(target).html(`<span oninput="$(this).parent().get(0).markdown=this.value;" style="width:auto; height:auto; white-space: pre;"> ${target.markdown} </span>`);
        }
    });
});


// 播放器添加节点标签功能
function addPlayerBar(player_bar_video){
    // 创建元素
    var player = document.querySelector('.prism-player');
    var player_bar = document.createElement('div');
    player_bar.classList.add('player_bar');
    player.parentNode.insertBefore(player_bar, player.nextSibling);

    var player_bar_list = document.createElement('div');
    player_bar_list.classList.add('player_bar_list');
    player_bar_list.setAttribute("id","player_bar_list");
    player_bar.appendChild(player_bar_list);

    var player_bar_ul = document.createElement('ul');
    player_bar_ul.classList.add('player_bar_ul');
    player_bar_ul.setAttribute("id","player_bar_ul");
    player_bar_list.appendChild(player_bar_ul);

    var player_bar_list_add_div = document.createElement('div');
    player_bar_list_add_div.classList.add('player_bar_list_add_div');
    player_bar_list.appendChild(player_bar_list_add_div);

    var player_bar_list_add_input = document.createElement('input');
    player_bar_list_add_input.classList.add('player_bar_list_add_input');
    player_bar_list_add_input.setAttribute("type","text");
    player_bar_list_add_input.setAttribute("id","player_bar_list_add_input");
    player_bar_list_add_div.appendChild(player_bar_list_add_input);

    var player_bar_list_add_button = document.createElement('button');
    player_bar_list_add_button.classList.add('player_bar_list_add_button');
    player_bar_list_add_button.setAttribute("id","player_bar_list_add_new_item_btn");
    var player_bar_list_add_buttonText = document.createTextNode("Add");
    player_bar_list_add_button.appendChild(player_bar_list_add_buttonText);
    player_bar_list_add_div.appendChild(player_bar_list_add_button);

    var player_bar_go = document.createElement('div');
    player_bar_go.classList.add('player_bar_go');
    player_bar_go.setAttribute("id","player_bar_go");
    var player_bar_goText = document.createTextNode("Go!");
    player_bar_go.appendChild(player_bar_goText);
    player_bar.appendChild(player_bar_go);

    //存储cookie的名称和标识符
    const COOKIE_NAME = "listItems";
    const PAGE_IDENTIFIER = window.location.href;
    //计数器
    let counter = 0;

    //获取cookie中的数据
    function getListData() {
        let data = getCookie(COOKIE_NAME);
        if (!data) {
            data = {};
        } else {
            data = JSON.parse(data);
        }
        if (!data[PAGE_IDENTIFIER]) {
            data[PAGE_IDENTIFIER] = [];
        }
        return data[PAGE_IDENTIFIER];
    }

    //将数据保存到cookie中
    function saveListData(data) {
        let cookieData = getCookie(COOKIE_NAME);
        if (cookieData) {
            cookieData = JSON.parse(cookieData);
        } else {
            cookieData = {};
        }
        cookieData[PAGE_IDENTIFIER] = data;
        setCookie(COOKIE_NAME, JSON.stringify(cookieData), 36500);
    }

    //创建新的li元素
    function createListItemElement(text) {
        const li = document.createElement("li");
        const radio = document.createElement("input");
        radio.type = "radio";
        radio.name = "player_bar_ul";
        radio.id = counter++;
        li.appendChild(radio);
        const label = document.createElement("label");
        label.textContent = text;
        label.classList.add("player_bar_ul_li_text");
        label.setAttribute("for", radio.id);
        li.appendChild(label);
        const deleteBtn = document.createElement("button");
        deleteBtn.textContent = "Delete";
        deleteBtn.addEventListener("click", () => {
            const list = document.getElementById("player_bar_ul");
            const index = Array.from(list.children).indexOf(li);
            const data = getListData();
            data.splice(index, 1);
            saveListData(data);
            li.remove();
        });
        li.appendChild(deleteBtn);
        return li;
    }

    //渲染列表
    function renderList() {
        const listContainer = document.getElementById("player_bar_list");
        const list = document.getElementById("player_bar_ul");
        list.innerHTML = "";
        const data = getListData();
        data.forEach((item) => {
            list.appendChild(createListItemElement(item.text));
        });
    }

    //新增列表项
    function addNewItem() {
        const input = document.getElementById("player_bar_list_add_input");
        const text = input.value.trim();
        if (text === "") {
            alert("请输入内容");
            return;
        }
        const data = getListData();
        data.push({text: text, time: player_bar_video.currentTime});
        saveListData(data);
        const list = document.getElementById("player_bar_ul");
        list.appendChild(createListItemElement(text));
        input.value = "";
    }

    //设置cookie
    function setCookie(name, value, days) {
        let cookie = `${name}=${encodeURIComponent(value)}; path=/`;
        if (days) {
            const expireDate = new Date();
            expireDate.setDate(expireDate.getDate() + days);
            cookie += `; expires=${expireDate.toUTCString()}`;
        }
        document.cookie = cookie;
    }

    //获取cookie
    function getCookie(name) {
        const cookies = document.cookie.split("; ");
        for (let i = 0; i < cookies.length; i++) {
            const [cookieName, cookieValue] = cookies[i].split("=");
            if (cookieName === name) {
                return decodeURIComponent(cookieValue);
            }
        }
        return null;
    }

    //为添加按钮添加事件处理程序
    var player_bar_add_button = document.getElementById("player_bar_list_add_new_item_btn")
    player_bar_add_button.addEventListener("click", ()=>{
        addNewItem();
        player_bar_add_button.classList.add('added');
        player_bar_add_button.textContent = "Added";
        setTimeout(() => {
            player_bar_add_button.classList.remove('added');
            player_bar_add_button.textContent = "Add";
        }, 2000);
    });

    //在页面加载时渲染列表
    renderList();

    //为跳转按钮添加事件处理程序
    var click_player_bar_go = document.getElementById("player_bar_go");
    click_player_bar_go.addEventListener("click", () => {
        const selected = document.querySelector('input[name="player_bar_ul"]:checked');
        if (selected) {
            const data = getListData();
            const index = Array.from(selected.parentNode.parentNode.children).indexOf(selected.parentNode);
            player_bar_video.currentTime = data[index].time;
        } else {
            alert("请选择一项");
        }
        click_player_bar_go.classList.add('gone');
        click_player_bar_go.textContent = "Gone";
        setTimeout(() => {
            click_player_bar_go.classList.remove('gone');
            click_player_bar_go.textContent = "Go!";
        }, 2000);
    });
}

window.addEventListener('load', function() {
    var player_bar_video = document.querySelector('video');
    if(player_bar_video!=null)addPlayerBar(player_bar_video);
});