SYZOJ 增强 markdown 编辑器 和 一些更新

讨论区评论的时候,不能预览自己的评论,这就很难受。发讨论的时候,必须切换页面才能预览。就不能边写边预览吗?于是有了本文。

发现 textarea 都是 .markdown-edit,那就替换掉这个就行了。左边是编辑框,右边是预览框,还有一个按钮用来控制预览。注意新的 textarea 的 name 要和原先的一样。至于渲染,发现直接调用 /api/markdown 就能获得生成好的 html 代码。

const markdownEditor = async function () {
    $('.markdown-edit').each(function () {
        const $original = $(this);
        const initialVal = $original.val();

        const $container = $('<div>').addClass('markdown-container');
        const $left = $('<div>').addClass('markdown-left');
        const $right = $('<div>').addClass('markdown-right');
        const $textarea = $('<textarea class="markdown-source"></textarea>')
            .val(initialVal).attr('name', $original.attr('name'));
        const $preview = $('<div>').addClass('markdown-preview');
        const $toggleButton = $('<a>').attr('class', 'small ui primary button toggle-preview').text('切换预览');

        $left.append($toggleButton, $textarea);
        $right.append($preview);
        $container.append($left, $right);
        $original.replaceWith($container);

        function update() {
            $.post('/api/markdown', { s: $textarea.val() }, function (s) {
                $preview.html(s);
            });
        }

        $textarea.on('input', update);
        update();

        $toggleButton.on('click', function () {
            if ($right.is(':visible')) {
                $right.hide();
                $left.addClass('markdown-full');
            } else {
                $right.show();
                $left.removeClass('markdown-full');
            }
        });
    });
};
.markdown-container {
    display: flex;
    width: 100%;
    height: 100%;
    border: 1px solid var(--theme-border);
    border-radius: .28571429rem;
}
.markdown-left, .markdown-right {
    padding: 10px;
    box-sizing: border-box;
}
.markdown-left {
    width: 50%;
}
.markdown-right {
    width: 50%;
    overflow-y: auto;
    border-left: 1px solid var(--theme-border);
}
.markdown-full {
    width: 100%;
}
.toggle-preview {
    margin-bottom: 5px !important;
}
.markdown-source {
    max-height: unset !important;
}

另外有一些更新,支持复制讨论区的 markdown 源码和评论的 markdown 源码,支持了分割线(------)和引用块(> quote)语法。修复了 inline code。还有一些小变更。

完整代码
// ==UserScript==
// @name         SYZOJ darker
// @namespace    http://tampermonkey.net/
// @version      2025-07-12
// @description  use custom dark style for SYZOJ
// @author       XuYueming
// @match        http://?/*
// @match        http://?/*
// @match        http://?/*
// @grant        unsafeWindow
// ==/UserScript==

(function () {
    'use strict';

    function copyText(text) {
        return new Promise((resolve, reject) => {
            if (!text) {
                reject('nothing copyied!');
            }
            const $textarea = $('<textarea>');
            $('body').append($textarea);
            $textarea.val(text).select();
            try {
                const successful = document.execCommand('copy');
                $textarea.remove();
                if (successful) {
                    resolve();
                } else {
                    reject();
                }
            } catch (err) {
                $textarea.remove();
                reject(err);
            }
        });
    }

    const createEditorIframe = function (code, lang, $parent, config) {
        const $iframe = $('<iframe>')
            .attr('class', 'custom-editor')
            .appendTo($parent);
        const iframe = $iframe[0];
        const win = iframe.contentWindow;
        const doc = iframe.contentDocument || iframe.contentWindow.document;

        doc.open();
        doc.write(`
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <style>
                html, body, #container {
                    margin: 0;
                    height: 100%;
                    width: 100%;
                    overflow: hidden;
                }
            </style>
            <script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"></script>
        </head>
        <body>
            <div id="container"></div>
        </body>
        </html>
        `);
        doc.close();

        return new Promise((resolve) => {
            const tryInit = () => {
                if (typeof win.require === 'undefined') {
                    setTimeout(tryInit, 50); // retry
                    return;
                }

                win.require.config({ paths: { 'vs': 'https://unpkg.com/monaco-editor@0.44.0/min/vs' } });
                win.require(['vs/editor/editor.main'], function () {
                    const editor = win.monaco.editor.create(doc.getElementById('container'), {
                        value: code,
                        language: lang,
                        theme: 'vs-dark',
                        contextmenu: false,
                        renderFinalNewline: true,
                        scrollbar: {
                            alwaysConsumeMouseWheel: false,
                        },
                        ...config
                    });

                    resolve({
                        $iframe: $iframe,
                        editor: editor,
                        winMonaco: win.monaco
                    });
                });
            };

            tryInit();
        });
    };

    const problemEditor = async function () {
        const code = unsafeWindow.editor.getValue();
        const lang = unsafeWindow.editor.getModel().getLanguageIdentifier().language;

        const { $iframe, editor, winMonaco } = await createEditorIframe(code, lang, $('#editor'));

        unsafeWindow.editor.dispose();
        unsafeWindow.editor = editor;

        $('#languages-menu .item').click(function () {
            winMonaco.editor.setModelLanguage(editor.getModel(), $(this).data('mode'));
        });
    };

    const submissionEditor = async function () {
        const script = document.createElement('script');
        script.textContent = `
            // 尝试暴露页面中的变量
            (function() {
                function decodeHtmlEntities(str) {
                    const doc = new DOMParser().parseFromString(str, 'text/html');
                    return doc.documentElement.textContent;
                }
                window._exposed = {
                    formattedCode: formattedCode && decodeHtmlEntities(formattedCode),
                    unformattedCode: unformattedCode && decodeHtmlEntities(unformattedCode),
                    language: vueApp.roughData.info['language']
                };
            })();
        `;
        document.documentElement.appendChild(script);
        script.remove();

        await new Promise(resolve => setTimeout(resolve, 50));
        const { formattedCode, unformattedCode, language } = unsafeWindow._exposed;

        let lang = undefined;

        if (language.includes('C++')) {
            lang = 'cpp';
        } else if (language.includes('Python')) {
            lang = 'python';
        } else {
            console.warn('unknown language', language);
            return;
        }

        const $div = $('<div>');
        $($('#submission_content pre:has(>code)')[0])
            .replaceWith($div);

        const { $iframe, editor } = await createEditorIframe(formattedCode || unformattedCode, lang, $div,
            {
                minimap: { enabled: false },
                scrollBeyondLastLine: false,
                readOnly: true,
                automaticLayout: false,
                scrollbar: {
                    vertical: 'hidden',
                    alwaysConsumeMouseWheel: false,
                },
            }
        );

        const updateHeight = () => {
            const contentHeight = editor.getContentHeight() + 5;
            $div.css({ height: `${contentHeight}px` });
            editor.layout();
        };

        updateHeight();

        if (formattedCode) {
            const $btn = $div.parent().find('>a');
            let formatted = true;
            $btn.on('click', () => {
                formatted = !formatted;
                editor.setValue(formatted ? formattedCode : unformattedCode);
                updateHeight();
            });
        }
    };

    const copyMarkdown = async function () {
        function getHeaderLevel($x) {
            const m = $x.prop("tagName").match(/^H([1-6])$/);
            return m ? +m[1] : null;
        }
        function tableToMarkdownWithSpan($table) {
            const grid = [];
            let maxCols = 0;

            $table.find('tr').each(function (rowIndex) {
                grid[rowIndex] = grid[rowIndex] || [];
                let colIndex = 0;

                $(this).children('th, td').each(function () {
                    // 跳过已占用的位置
                    while (grid[rowIndex][colIndex]) colIndex++;

                    const cell = $(this);
                    const text = getText(cell);
                    const rowspan = parseInt(cell.attr('rowspan') || 1);
                    const colspan = parseInt(cell.attr('colspan') || 1);

                    for (let r = 0; r < rowspan; r++) {
                        for (let c = 0; c < colspan; c++) {
                            const targetRow = rowIndex + r;
                            const targetCol = colIndex + c;

                            grid[targetRow] = grid[targetRow] || [];
                            grid[targetRow][targetCol] = text; // 使用相同文本
                        }
                    }

                    colIndex += colspan;
                    maxCols = Math.max(maxCols, colIndex);
                });
            });

            // 构建 Markdown 表格
            let markdown = '';
            for (let i = 0; i < grid.length; i++) {
                const row = grid[i];
                const paddedRow = [];
                for (let j = 0; j < maxCols; j++) {
                    paddedRow.push(row[j] !== undefined ? row[j] : '');
                }
                markdown += '| ' + paddedRow.join(' | ') + ' |\n';

                // 添加分隔线
                if (i === 0) {
                    markdown += '| ' + paddedRow.map(() => '---').join(' | ') + ' |\n';
                }
            }

            return markdown;
        }
        const getText = function ($content) {
            if ($content.is('span.mjpage')) { // math formula
                const math = $content.find('title').text().trim();
                return $content.is('.mjpage__block') ? `\n\$\$\n${math}\n\$\$\n` : ` $${math}$ `;
            }
            if ($content.is('code')) { // code
                if ($content.is(':not(pre) > code'))
                    return '`' + $content.text() + '`';
                return '```\n' + $content.text() + '```\n\n';
            }
            if ($content.is('table')) { // table
                return '\n\n' + tableToMarkdownWithSpan($content) + '\n\n';
            }
            if ($content.is('ul') || $content.is('ol')) { // list
                const prefix = $content.is('ul') ? '- ' : '1. ';
                return $content.children().map((_, li) => prefix + getText($(li)).trim().replace(/\n/g, '\n    ')).get().join('\n') + '\n';
            }
            if ($content.is('hr')) { // horizon
                return '------\n';
            }
            let text = "";
            $content.contents().each(function (index, node) {
                if (node.nodeType === 3) {
                    text += node.nodeValue;
                } else if (node.nodeType === 1) {
                    text += getText($(node));
                }
            });
            if ($content.is('strong')) { // strong
                text = `**${text}**`;
            }
            if ($content.is('s')) { // delete
                text = `~~${text}~~`;
            }
            if (getHeaderLevel($content)) { // header
                text = `${'#'.repeat(getHeaderLevel($content))} ${text}\n\n`;
            }
            if ($content.is('p')) { // paragraph
                text = text + '\n\n';
            }
            if ($content.is('.ui.message')) { // quote
                text = text.split('\n').map(s => s === '' ? '>' : '> ' + s).join('\n');
            }
            if ($content.is('a')) { // link
                return `[${text}](${$content.attr('href')})`;
            }
            if ($content.is('img')) { // image
                return `![](${$content.attr('src')})`;
            }
            return text;
        };
        const createButton = function ($content) {
            return $('<a>')
                .attr('class', 'small ui primary button copyMD')
                .text('copy MD')
                .on('click', function () {
                    if ($(this).data('copy')) {
                        return;
                    }
                    const text = getText($content);
                    console.log(text);
                    // alert(text);
                    $(this).data('copy', true)
                        .text('copying');
                    copyText(text)
                        .then(() => {
                            $(this).text('copyied!');
                        })
                        .catch((err) => {
                            $(this).text(err || 'failed!');
                        })
                        .finally(() => {
                            setTimeout(() => {
                                $(this).data('copy', null)
                                    .text('copy MD');
                            }, 3000);
                        });
                });
        };
        if (window.location.href.includes('problem')) {
            $('.ui.top.attached.header').each(function () {
                $(this).append(createButton(
                    $(this).parent().children().last()
                ));
            });
        }
        if (window.location.href.includes('article')) {
            $('.padding>p:first').append(createButton(
                $('#content')
            ));
            $('.comment').each(function () {
                $(this).find('.metadata').append(createButton(
                    $(this).find('.text')
                ))
            });
        }
    };

    const markdownEditor = async function () {
        $('.markdown-edit').each(function () {
            const $original = $(this);
            const initialVal = $original.val();

            const $container = $('<div>').addClass('markdown-container');
            const $left = $('<div>').addClass('markdown-left');
            const $right = $('<div>').addClass('markdown-right');
            const $textarea = $('<textarea class="markdown-source"></textarea>')
                .val(initialVal).attr('name', $original.attr('name'));
            const $preview = $('<div>').addClass('markdown-preview');
            const $toggleButton = $('<a>').attr('class', 'small ui primary button toggle-preview').text('切换预览');

            $left.append($toggleButton, $textarea);
            $right.append($preview);
            $container.append($left, $right);
            $original.replaceWith($container);

            function update() {
                $.post('/api/markdown', { s: $textarea.val() }, function (s) {
                    $preview.html(s);
                });
            }

            $textarea.on('input', update);
            update();

            $toggleButton.on('click', function () {
                if ($right.is(':visible')) {
                    $right.hide();
                    $left.addClass('markdown-full');
                } else {
                    $right.show();
                    $left.removeClass('markdown-full');
                }
            });
        });
    };

    const href = window.location.href;

    if (typeof unsafeWindow.onEditorLoaded === 'function')
        unsafeWindow.onEditorLoaded(problemEditor);
    if (href.includes('submission'))
        $(document).ready(submissionEditor);
    if (href.includes('problem') || href.includes('article'))
        $(document).ready(copyMarkdown);
    if ($('.markdown-edit').length > 0)
        $(document).ready(markdownEditor);
})();
/* simple CSS, reference: LOJ */

body {
    background: var(--theme-background,#fff)!important
}

body {
    --theme-background: #222;
    --theme-background-transparent: #222222dd;
    --theme-foreground: rgba(255, 255, 255, .95);
    --theme-foreground-transparent: rgba(255, 255, 255, .95);
    --theme-foreground-disabled: rgba(230, 230, 230, .3);
    --theme-selection-background: rgba(155, 155, 155, .4);
    --theme-border: rgb(70, 70, 70);
    --theme-border-light: rgb(40, 40, 40);
    --theme-border-hover: #5f5f5f;
    --theme-border-active: #6f6f6f;
    --theme-shadow: rgba(24, 26, 28, .95);
    --theme-hyperlink: #61affb;
    --theme-hyperlink-hover: #97cbff;
    --theme-input-placeholder: rgba(191, 191, 191, .87);
    --theme-input-placeholder-focus: rgba(233, 233, 233, .9);
    --theme-input-border-focus: #6f6f6f;
    --theme-button-background: #4f4f4f;
    --theme-button-background-hover: #444;
    --theme-button-background-active: #3f3f3f;
    --theme-button-foreground: var(--theme-foreground);
    --theme-block-header-background: #353637;
    --theme-table-header-background: #28292a;
    --theme-toggle-lane-unchecked: rgba(255, 255, 255, .1);
    --theme-toggle-lane-unchecked-hover: rgba(255, 255, 255, .2);
    --theme-toggle-lane-checked: #0d71bb;
    --theme-toggle-lane-checked-focus: #2185D0;
    --theme-dialog-actions-background: #292a2b;
    --theme-dropdown-item-hover-background: rgb(52, 52, 52);
    --theme-dropdown-item-selected-background: rgb(47, 47, 47);
    --theme-dropdown-message-foreground: rgba(255, 255, 255, .4);
    --theme-menu-item-hover-background: rgb(47, 47, 47);
    --theme-menu-item-active-background: rgb(52, 52, 52);
    --theme-search-result-background-hover: #292a2b;
    --theme-placeholder-segment-background: #292a2b;
    --theme-accordion-non-active: rgba(255, 255, 255, .6);
    --theme-progress-bar-background: rgba(255, 255, 255, .1);
    --theme-table-progress-bar-background: rgba(255, 255, 255, .15);
    --theme-placeholder-background: var(--theme-background);
    --theme-placeholder-image: linear-gradient(to right, rgba(255, 255, 255, .08) 0, rgba(255, 255, 255, .15) 15%, rgba(255, 255, 255, .08) 30%);
    --theme-message-background: #2a2a29;
    --theme-message-foreground: var(--theme-foreground);
    --theme-message-border: var(--theme-border);
    --theme-message-error-background: #6d2727;
    --theme-message-error-foreground: var(--theme-foreground);
    --theme-message-error-border: #c74e4e;
    --theme-message-success-background: #379a3e;
    --theme-message-success-foreground: var(--theme-foreground);
    --theme-message-success-border: #64d22d;
    --theme-message-info-background: #3584a2;
    --theme-message-info-foreground: var(--theme-foreground);
    --theme-message-info-border: #3cc1dc;
    --theme-message-warning-background: #b98c26;
    --theme-message-warning-foreground: var(--theme-foreground);
    --theme-message-warning-border: #c19f57;
    --theme-scrollbar-track: rgba(255, 255, 255, .1);
    --theme-scrollbar-thumb: rgba(255, 255, 255, .25);
    --theme-scrollbar-thumb-inactive: rgba(255, 255, 255, .15);
    --theme-scrollbar-thumb-hover: rgba(255, 255, 255, .35);
    --theme-action-menu-item-background: var(--theme-background);
    --theme-action-menu-item-background-hover: var(--theme-menu-item-hover-background);
    --theme-action-menu-item-foreground: var(--theme-foreground);
    --theme-action-menu-item-foreground-hover: var(--theme-foreground);
    --theme-action-menu-item-side: rgba(210, 210, 210, .15);
    --theme-action-menu-item-side-hover: rgba(255, 255, 255, .95);
    --theme-action-menu-item-important-background: #2185d0;
    --theme-action-menu-item-important-background-hover: #1678c2;
    --theme-action-menu-item-important-foreground: #fff;
    --theme-action-menu-item-important-foreground-hover: #fff;
    --theme-action-menu-item-important-side: rgba(255, 255, 255, .5);
    --theme-action-menu-item-important-side-hover: rgba(255, 255, 255, .7);
    --theme-action-menu-item-dangerous-background: var(--theme-action-menu-item-background);
    --theme-action-menu-item-dangerous-background-hover: rgba(219, 40, 40, .12);
    --theme-action-menu-item-dangerous-foreground: #db2828;
    --theme-action-menu-item-dangerous-foreground-hover: #db2828;
    --theme-action-menu-item-dangerous-side: rgba(219, 40, 40, .5);
    --theme-action-menu-item-dangerous-side-hover: #db2828;
    --theme-status-pending: #6cf;
    --theme-status-configuration-error: #e28989;
    --theme-status-system-error: #a5a5a5;
    --theme-status-compilation-error: #3387da;
    --theme-status-canceled: #6770d0;
    --theme-status-file-error: #bc35ff;
    --theme-status-runtime-error: #bc35ff;
    --theme-status-time-limit-exceeded: #ff9840;
    --theme-status-memory-limit-exceeded: #ff9840;
    --theme-status-output-limit-exceeded: #ff9840;
    --theme-status-partially-correct: #01bab2;
    --theme-status-wrong-answer: #ff4545;
    --theme-status-accepted: #37da58;
    --theme-status-judgement-failed: #FF5722;
    --theme-status-waiting: #a5a5a5;
    --theme-status-preparing: #de4d9e;
    --theme-status-compiling: #00b5ad;
    --theme-status-running: #6cf;
    --theme-status-skipped: #78909C;
    --theme-score-0: #ff4545;
    --theme-score-1: #ff694f;
    --theme-score-2: #f8603a;
    --theme-score-3: #fc8354;
    --theme-score-4: #fa9231;
    --theme-score-5: #f7bb3b;
    --theme-score-6: #ecdb44;
    --theme-score-7: #e2ec52;
    --theme-score-8: #b0d628;
    --theme-score-9: #a9b42a;
    --theme-score-10: #37da58;
    --theme-subway-graph-level-0: #414141;
    --theme-subway-graph-level-1: #355332;
    --theme-subway-graph-level-2: #37742e;
    --theme-subway-graph-level-3: #27943d;
    --theme-subway-graph-level-4: #1dca3a;
    --theme-os-icon-light: rgba(255, 255, 255, .4);
    --theme-os-icon-heavy: rgba(255, 255, 255, .7);
    --theme-discussion-title: #d6d6d6;
    --theme-discussion-reply-count: #9c9c9c;
    --theme-discussion-border: #4e4e4e;
    --theme-discussion-border-current-user: #384d61;
    --theme-discussion-header-foreground: #9c9c9c;
    --theme-discussion-header-background: #313131;
    --theme-discussion-header-background-current-user: hsl(210 22% 17% / 1);
    --theme-discussion-header-label-border: #888;
    --theme-discussion-delete: #db2828;
    --theme-discussion-reaction-background-hover: hsl(0 0% 18% / 1);
    --theme-discussion-reaction-background-selected: hsl(0 0% 22% / 1);
    --theme-discussion-reaction-disabled: #777;
    --theme-discussion-reaction-picker-hover: rgba(255, 255, 255, .08);
    --theme-discussion-reaction-picker-selected: rgba(255, 255, 255, .13);
    --theme-discussion-line-color: #4e4e4e;
    --theme-discussion-load-more-text: #aaa;
    --theme-discussion-load-more: #474747;
    --theme-footer: #bbb;
    --theme-footer-version: #666;
    --theme-footer-icons: #a7a7a7;
    --theme-login-error-message: #c54f4d;
    --theme-secondary-title: #999;
    --theme-description-message-foreground: rgba(255, 255, 255, .4);
    --theme-blockquote-foreground: #999;
    --theme-blockquote-side: #434343
}

body #root,body .ui.popup:not(.inverted),body .ui.popup:not(.inverted):before,body .ui.modal:not(.basic),body .ui.menu:not(.tabular),body .ui.menu .dropdown.item .menu,body .ui.menu .ui.dropdown .menu>.item,body .ui.dropdown .menu,body .results {
    background: var(--theme-background)!important;
    color: var(--theme-foreground)!important
}

body .ui.basic.label {
    background: var(--theme-background)!important
}

body,body .item,body .ui.menu .ui.dropdown .menu>.item,body .ui.menu .ui.dropdown .menu>.selected.item,body .ui.comments .comment .author,body .ui.comments .comment .text {
    color: var(--theme-foreground)!important
}

body .ui.segment,body .ui.dropdown,body .header,body .content,body .ui.icon:not(.button):not(.item):not(.message),body .ui.breadcrumb .icon.divider,body .ui.input,body input,body .ui.form .inline.fields>label,body .ui.input textarea,body .ui.form textarea,body .ui.radio.checkbox input~label,body .ui.toggle.checkbox input~label,body .ui.toggle.checkbox input:checked~label,body .ui.toggle.checkbox input:focus:checked~label,body .ui.checkbox label:hover,body .ui.checkbox+label:hover,body .ui.checkbox label,body .ui.checkbox+label,body .ui.form .field>label,body .ui.form .field>input,body .ui.selection.visible.dropdown>.text:not(.default),body .ui.menu .ui.dropdown .menu>.active.item,body .ui.menu .ui.dropdown .menu>.item:hover,body .ui.accordion,body .ui.accordion>.title,body .ui.accordion>.content,body .ui.accordion>.content>.accordion,body .result,body .result>.title,body .ui.block>*,body .ui.statistic>*,body table,body tr,body td,body th,body .ui.grid,body .ui.grid>.column,body .accordion>.title,body .accordion>.content,body .padding>*, body .ui.text.loader, #editor, #pie_chart_legend li,body .ui.card,body .ui.card a,body .ui.card .meta,body .metadata {
    background: inherit!important;
    color: inherit!important;
}

.ui.selectable.table tbody tr:hover, .ui.table tbody tr td.selectable:hover {
    color: inherit!important;
}

body .ui.segment:not(.red):not(.orange):not(.yellow):not(.olive):not(.green):not(.teal):not(.blue):not(.violet):not(.purple):not(.pink):not(.brown):not(.grey):not(.black),body .ui.dropdown,body .header,body .content,body .ui.popup:not(.inverted),body .ui.popup:not(.inverted):before,body .ui.menu,body .ui.input,body input,body .ui.input textarea,body .ui.form textarea,body .ui.basic.label:not(.red):not(.orange):not(.yellow):not(.olive):not(.green):not(.teal):not(.blue):not(.violet):not(.purple):not(.pink):not(.brown):not(.grey):not(.black),body .results,body .result,body table:not(.red):not(.orange):not(.yellow):not(.olive):not(.green):not(.teal):not(.blue):not(.violet):not(.purple):not(.pink):not(.brown):not(.grey):not(.black),body tr,body td,body th,body .ui.tabular.menu .active.item {
    border-color: var(--theme-border)!important
}

body table,body .ui.segment {
    border-left-color: var(--theme-border)!important;
    border-right-color: var(--theme-border)!important;
    border-bottom-color: var(--theme-border)!important
}

body table:not(.basic)>thead>tr>th,body table:not(.basic)>tfoot>tr>th {
    background-color: var(--theme-table-header-background)!important
}

body .disabled.item {
    color: var(--theme-foreground-disabled)!important
}

body .ui.basic.label:not(.red):not(.orange):not(.yellow):not(.olive):not(.green):not(.teal):not(.blue):not(.violet):not(.purple):not(.pink):not(.brown):not(.grey):not(.black) {
    color: var(--theme-foreground)!important
}

body .ui.button:not(.primary):not(.positive):not(.negative):not(.inverted):not(.red):not(.orange):not(.yellow):not(.olive):not(.green):not(.teal):not(.blue):not(.violet):not(.purple):not(.pink):not(.brown):not(.grey):not(.black),body .ui.label:not(.basic):not(.red):not(.orange):not(.yellow):not(.olive):not(.green):not(.teal):not(.blue):not(.violet):not(.purple):not(.pink):not(.brown):not(.grey):not(.black) {
    background: var(--theme-button-background)!important
}

body .ui.button:not(.primary):not(.positive):not(.negative):not(.inverted):not(.red):not(.orange):not(.yellow):not(.olive):not(.green):not(.teal):not(.blue):not(.violet):not(.purple):not(.pink):not(.brown):not(.grey):not(.black):not(.loading),body .ui.label:not(.basic):not(.red):not(.orange):not(.yellow):not(.olive):not(.green):not(.teal):not(.blue):not(.violet):not(.purple):not(.pink):not(.brown):not(.grey):not(.black):not(.loading) {
    color: var(--theme-button-foreground)!important
}

body .ui.button:not(.primary):not(.positive):not(.negative):not(.inverted):not(.red):not(.orange):not(.yellow):not(.olive):not(.green):not(.teal):not(.blue):not(.violet):not(.purple):not(.pink):not(.brown):not(.grey):not(.black):hover,body a.ui.label:not(.basic):not(.red):not(.orange):not(.yellow):not(.olive):not(.green):not(.teal):not(.blue):not(.violet):not(.purple):not(.pink):not(.brown):not(.grey):not(.black):hover,body .ui.button:not(.primary):not(.positive):not(.negative):not(.inverted):not(.red):not(.orange):not(.yellow):not(.olive):not(.green):not(.teal):not(.blue):not(.violet):not(.purple):not(.pink):not(.brown):not(.grey):not(.black):focus,body a.ui.label:not(.basic):not(.red):not(.orange):not(.yellow):not(.olive):not(.green):not(.teal):not(.blue):not(.violet):not(.purple):not(.pink):not(.brown):not(.grey):not(.black):focus {
    background: var(--theme-button-background-hover)!important
}

body .ui.button:not(.primary):not(.positive):not(.negative):not(.inverted):not(.red):not(.orange):not(.yellow):not(.olive):not(.green):not(.teal):not(.blue):not(.violet):not(.purple):not(.pink):not(.brown):not(.grey):not(.black):active,body a.ui.label:not(.basic):not(.red):not(.orange):not(.yellow):not(.olive):not(.green):not(.teal):not(.blue):not(.violet):not(.purple):not(.pink):not(.brown):not(.grey):not(.black):active {
    background: var(--theme-button-background-active)!important
}

body input::placeholder,body .ui.input textarea::placeholder,body .ui.form textarea::placeholder {
    color: var(--theme-input-placeholder)!important
}

body input:focus::placeholder,body .ui.input textarea:focus::placeholder,body .ui.form textarea:focus::placeholder {
    color: var(--theme-input-placeholder-focus)!important
}

body .ui.input.focus:not(.transparent)>input,body .ui.input:not(.transparent)>input:focus,body .ui.form textarea:focus {
    border-color: var(--theme-input-border-focus)!important
}

body a,body .ui.breadcrumb a {
    color: var(--theme-hyperlink)
}

body a:hover,body .ui.breadcrumb a:hover {
    color: var(--theme-hyperlink-hover)
}

body .ui.block.header {
    background: var(--theme-block-header-background)!important
}

body .ui.toggle.checkbox label:before {
    background-color: var(--theme-toggle-lane-unchecked)!important
}

body .ui.toggle.checkbox label:hover:before,body .ui.toggle.checkbox label:focus:before {
    background-color: var(--theme-toggle-lane-unchecked-hover)!important
}

body .ui.toggle.checkbox input:checked~label:before,body .ui.toggle.checkbox input:checked:hover~label:before {
    background-color: var(--theme-toggle-lane-checked)!important
}

body .ui.toggle.checkbox input:checked:focus~label:before {
    background-color: var(--theme-toggle-lane-checked-focus)!important
}

body .ui.modal:not(.basic)>.actions {
    background-color: var(--theme-dialog-actions-background)!important
}

body .ui.dropdown .menu {
    border-color: var(--theme-border)!important
}

body .ui.selection.dropdown:hover {
    border-color: var(--theme-border-hover)!important
}

body .ui.selection.dropdown:focus,body .ui.selection.active.dropdown,body .ui.selection.active.dropdown .menu {
    border-color: var(--theme-border-active)!important
}

body .ui.dropdown .menu>.item {
    border-color: var(--theme-border-light)!important
}

body .ui.menu .ui.dropdown .menu>.item:hover,body .ui.dropdown .menu>.item:hover {
    background-color: var(--theme-dropdown-item-hover-background)!important
}

body .ui.dropdown .menu .selected.item,body .ui.dropdown.selected,body .ui.menu .ui.dropdown .menu>.selected.item {
    background-color: var(--theme-dropdown-item-selected-background)!important
}

body .ui.menu:not(.tabular).link .item:hover,body .ui.menu:not(.tabular) .dropdown.item:hover,body .ui.menu:not(.tabular) .link.item:hover,body .ui.menu:not(.tabular) a.item:hover {
    background-color: var(--theme-menu-item-hover-background)!important
}

body .ui.menu:not(.tabular) .active.item,body .ui.menu:not(.tabular) .active.item:hover,body .ui.menu:not(.tabular).vertical.active.item:hover,body .ui.menu:not(.tabular).pagination.active.item {
    background-color: var(--theme-menu-item-active-background)!important
}

body .ui.menu.tabular .active.item {
    background-color: var(--theme-background)!important
}

body .ui.secondary.pointing.menu .item:hover,body .ui.secondary.pointing.menu .active.item,body .ui.secondary.pointing.menu .item {
    background-color: transparent!important
}

body .ui.dropdown .menu>.message:not(.ui) {
    color: var(--theme-dropdown-message-foreground)
}

body .menu .item:before,body .menu:not(.pointing) .item:after {
    background-color: var(--theme-border)!important
}

body .menu.pointing .item:after {
    background-color: var(--theme-menu-item-active-background)!important;
    border-color: var(--theme-border)!important
}

body .ui.menu:not(.attached):not(.secondary) {
    box-shadow: 0 1px 2px 0 var(--theme-shadow)
}

body .ui.popup:not(.inverted):before {
    box-shadow: 1px 1px 0 0 var(--theme-border)!important
}

body .ui.popup:not(.inverted).right.center:before {
    box-shadow: -1px 1px 0 0 var(--theme-border)!important
}

body .ui.popup:not(.inverted).left.center:before {
    box-shadow: 1px -1px 0 0 var(--theme-border)!important
}

body .ui.popup:not(.inverted).bottom:before {
    box-shadow: -1px -1px 0 0 var(--theme-border)!important
}

body .ui.category.search>.results .category .result:hover,body .ui.search>.results .result:hover {
    background-color: var(--theme-search-result-background-hover)!important
}

body .ui.segment:not(.vertical):not(.attached) {
    box-shadow: 0 1px 2px 0 var(--theme-shadow)
}

body .ui.styled.accordion,body .ui.styled.accordion .accordion {
    box-shadow: 0 1px 2px 0 var(--theme-border),0 0 0 1px var(--theme-border)
}

body .ui.styled.accordion>.title,body .ui.styled.accordion .accordion>.title {
    background: none!important
}

body .ui.styled.accordion>.title:not(:hover):not(.active),body .ui.styled.accordion .accordion>.title:not(:hover):not(.active) {
    color: var(--theme-accordion-non-active)!important
}

body .ui.placeholder.segment {
    background: var(--theme-placeholder-segment-background)!important
}

body .ui.divider:not(.vertical):not(.horizontal) {
    border-color: var(--theme-border)!important
}

body .ui.progress {
    background: var(--theme-progress-bar-background)!important
}

body .ui.placeholder:not(.segment) {
    background-image: var(--theme-placeholder-image)
}

body .ui.placeholder:not(.segment),body .ui.placeholder:not(.segment)>.line {
    background-color: var(--theme-placeholder-background)
}

body .ui.message {
    background-color: var(--theme-message-background)!important;
    color: var(--theme-message-foreground)!important;
    box-shadow: 0 0 0 1px var(--theme-message-border) inset,0 0 rgba(0,0,0,0)!important
}

body .ui.negative.message {
    background-color: var(--theme-message-error-background)!important;
    color: var(--theme-message-error-foreground)!important;
    box-shadow: 0 0 0 1px var(--theme-message-error-border) inset,0 0 rgba(0,0,0,0)!important
}

body .ui.message.error,body .noty_type__error {
    background-color: var(--theme-message-error-background)!important;
    color: var(--theme-message-error-foreground)!important;
    box-shadow: 0 0 0 1px var(--theme-message-error-border) inset,0 0 rgba(0,0,0,0)!important
}

body .ui.message.success,body .noty_type__success {
    background-color: var(--theme-message-success-background)!important;
    color: var(--theme-message-success-foreground)!important;
    box-shadow: 0 0 0 1px var(--theme-message-success-border) inset,0 0 rgba(0,0,0,0)!important
}

body .ui.message.info,body .noty_type__info {
    background-color: var(--theme-message-info-background)!important;
    color: var(--theme-message-info-foreground)!important;
    box-shadow: 0 0 0 1px var(--theme-message-info-border) inset,0 0 rgba(0,0,0,0)!important
}

body .ui.message.warning,body .noty_type__warning {
    background-color: var(--theme-message-warning-background)!important;
    color: var(--theme-message-warning-foreground)!important;
    box-shadow: 0 0 0 1px var(--theme-message-warning-border) inset,0 0 rgba(0,0,0,0)!important
}

body .ui.checkbox input:checked~label:after {
    color: var(--theme-foreground)!important
}

body .ui.checkbox input~label:before,body .ui.checkbox input:checked~label:before,body .ui.checkbox input:focus~label:before {
    background-color: var(--theme-background)!important
}

body .ui.checkbox input~label:before {
    border-color: var(--theme-border)!important
}

body .ui.checkbox input:checked~label:before,body .ui.checkbox input~label:hover:before {
    border-color: var(--theme-border-hover)!important
}

body .ui.checkbox input:focus~label:before {
    border-color: var(--theme-border-active)!important
}

body .ui.checkbox.radio input:checked~label:after {
    background-color: var(--theme-foreground)!important
}

body ::selection {
    color: unset!important;
    background-color: var(--theme-selection-background)!important
}

body ::-moz-selection {
    color: unset!important;
    background-color: var(--theme-selection-background)!important
}

body ::-webkit-selection {
    color: unset!important;
    background-color: var(--theme-selection-background)!important
}

html ::-webkit-scrollbar,body ::-webkit-scrollbar {
    -webkit-appearance: none;
    width: 10px;
    height: 10px
}

html ::-webkit-scrollbar-track,body ::-webkit-scrollbar-track {
    background: var(--theme-scrollbar-track)!important;
    border-radius: 0
}

html ::-webkit-scrollbar-thumb,body ::-webkit-scrollbar-thumb {
    cursor: pointer;
    border-radius: 5px;
    background: var(--theme-scrollbar-thumb)!important;
    -webkit-transition: color .2s ease;
    transition: color .2s ease
}

html ::-webkit-scrollbar-thumb:window-inactive,body ::-webkit-scrollbar-thumb:window-inactive {
    background: var(--theme-scrollbar-thumb-inactive)!important
}

html ::-webkit-scrollbar-thumb:hover,body ::-webkit-scrollbar-thumb:hover {
    background: var(--theme-scrollbar-thumb-hover)!important
}

.submit_time, a.black-link, div.description, a.result .title {
    color: inherit !important;
}

i.icon.download {
    color: var(--theme-foreground) !important;
}

body .ui.card, body .ui.cards>.card {
    box-shadow: 0 1px 3px 0 var(--theme-border), 0 0 0 1px var(--theme-border) !important;
}

/* I think lighter green is for higher score */

.score_10,span.status.accepted {
    color: #52ff00!important;
}
.score_7 {
    color: forestgreen;
}

/* highlight code edited from /self/tomorrow.css */

.hll { background-color: #3e4451 } /* 高亮行背景 */
.pl-c { color: #5c6370 } /* Comment */
.pl-err { color: #e06c75 } /* Error */
.pl-k { color: #c678dd } /* Keyword */
.pl-l { color: #56b6c2 } /* Literal */
.pl-n { color: #abb2bf } /* Name */
.pl-o { color: #61aeee } /* Operator */
.pl-p { color: #abb2bf } /* Punctuation */
.pl-ch { color: #5c6370 } /* Comment.Hashbang */
.pl-cm { color: #5c6370 } /* Comment.Multiline */
.pl-cp { color: #c678dd } /* Comment.Preproc */
.pl-cpf { color: #38a } /* Comment.PreprocFile */
.pl-c1 { color: #5c6370 } /* Comment.Single */
.pl-cs { color: #5c6370 } /* Comment.Special */
.pl-gd { color: #e06c75 } /* Generic.Deleted */
.pl-ge { font-style: italic } /* Generic.Emph */
.pl-gh { color: #abb2bf; font-weight: bold } /* Generic.Heading */
.pl-gi { color: #98c379 } /* Generic.Inserted */
.pl-gp { color: #5c6370; font-weight: bold } /* Generic.Prompt */
.pl-gs { font-weight: bold } /* Generic.Strong */
.pl-gu { color: #61aeee; font-weight: bold } /* Generic.Subheading */
.pl-kc { color: #c678dd } /* Keyword.Constant */
.pl-kd { color: #c678dd } /* Keyword.Declaration */
.pl-kn { color: #61aeee } /* Keyword.Namespace */
.pl-kp { color: #c678dd } /* Keyword.Pseudo */
.pl-kr { color: #c678dd } /* Keyword.Reserved */
.pl-kt { color: #d19a66 } /* Keyword.Type */
.pl-ld { color: #98c379 } /* Literal.Date */
.pl-m { color: #d19a66 } /* Literal.Number */
.pl-s { color: #98c379 } /* Literal.String */
.pl-na { color: #d19a66 } /* Name.Attribute */
.pl-nb { color: #e6c07b } /* Name.Builtin */
.pl-nc { color: #e6c07b } /* Name.Class */
.pl-no { color: #e06c75 } /* Name.Constant */
.pl-nd { color: #61aeee } /* Name.Decorator */
.pl-ni { color: #abb2bf } /* Name.Entity */
.pl-ne { color: #e06c75 } /* Name.Exception */
.pl-nf { color: #61aeee } /* Name.Function */
.pl-nl { color: #abb2bf } /* Name.Label */
.pl-nn { color: #e6c07b } /* Name.Namespace */
.pl-nx { color: #61aeee } /* Name.Other */
.pl-py { color: #d19a66 } /* Name.Property */
.pl-nt { color: #e06c75 } /* Name.Tag */
.pl-nv { color: #e06c75 } /* Name.Variable */
.pl-ow { color: #61aeee } /* Operator.Word */
.pl-w { color: #abb2bf } /* Text.Whitespace */
.pl-mb { color: #d19a66 } /* Literal.Number.Bin */
.pl-mf { color: #d19a66 } /* Literal.Number.Float */
.pl-mh { color: #d19a66 } /* Literal.Number.Hex */
.pl-mi { color: #d19a66 } /* Literal.Number.Integer */
.pl-mo { color: #d19a66 } /* Literal.Number.Oct */
.pl-sb { color: #98c379 } /* Literal.String.Backtick */
.pl-sc { color: #abb2bf } /* Literal.String.Char */
.pl-sd { color: #5c6370 } /* Literal.String.Doc */
.pl-s2 { color: #98c379 } /* Literal.String.Double */
.pl-se { color: #d19a66 } /* Literal.String.Escape */
.pl-sh { color: #98c379 } /* Literal.String.Heredoc */
.pl-si { color: #d19a66 } /* Literal.String.Interpol */
.pl-sx { color: #98c379 } /* Literal.String.Other */
.pl-sr { color: #98c379 } /* Literal.String.Regex */
.pl-s1 { color: #98c379 } /* Literal.String.Single */
.pl-ss { color: #98c379 } /* Literal.String.Symbol */
.pl-bp { color: #abb2bf } /* Name.Builtin.Pseudo */
.pl-vc { color: #e06c75 } /* Name.Variable.Class */
.pl-vg { color: #e06c75 } /* Name.Variable.Global */
.pl-vi { color: #e06c75 } /* Name.Variable.Instance */
.pl-il { color: #d19a66 } /* Literal.Number.Integer.Long */

/* custom-editor style */

iframe.custom-editor {
    height: 100%;
    width: 100%;
    border: 1px solid var(--theme-border)!important;
}

#editor {
    border: unset !important;
}

/* update: 2025-7-9 */

a.copyMD.ui.primary.button {
    background-color: #2185d0 !important;
    margin-left: 10px;
    padding: 10px;
}

a.copyMD.ui.primary.button:hover {
    background-color: #1678c2 !important;
}

/* update: 2025-7-12 */

body .ui.menu .item.disabled, body .ui.menu .item.disabled:hover {
    color: rgba(255, 255, 255, .4) !important;
}

body .ui.comments .comment .actions a:last-child {
    color: inherit;
}

.markdown-container {
    display: flex;
    width: 100%;
    height: 100%;
    border: 1px solid var(--theme-border);
    border-radius: .28571429rem;
}
.markdown-left, .markdown-right {
    padding: 10px;
    box-sizing: border-box;
}
.markdown-left {
    width: 50%;
}
.markdown-right {
    width: 50%;
    overflow-y: auto;
    border-left: 1px solid var(--theme-border);
}
.markdown-full {
    width: 100%;
}
.toggle-preview {
    margin-bottom: 5px !important;
}
.markdown-source {
    max-height: unset !important;
}
posted @ 2025-07-12 21:13  XuYueming  阅读(23)  评论(0)    收藏  举报