darkmode Fork

    @@ -1,67 +1,112 @@ /* - * @title 黒背景 - * @description サイトの背景を黒に、文字色を、元々の色の彩度を最大にしたものにします。 2種類モードがあり、実行するたび切り替わります:1.一番下の背景色が透明に、その他の要素の背景色が透明になります。 2.ほぼすべての要素の背景色が黒になります。 1より見た目は悪いです。 + * @title darkmode + * @description switchable darkmode + * @include http://* + * @include https://* + * @contributor nanikamado http://let.hatelabo.jp/nanikamado/let/hLHU5aii3YU5 + * @nitpicker noromanba https://noromanba.github.com + * @license Unknown (as-is) * @javascript_url */ - (()=>{ - let my_style, - all = document.querySelectorAll('*'), - mode = (my_style = document.querySelector('.dark_visited_style')) ? Number(my_style.getAttribute('mode_stat')) : 0, - set_color = elm => { - elm.forEach((v) => { - let c = window.getComputedStyle(v).getPropertyValue('color'), - c_ob = { - r: Number(c.replace(/rgba?\((\d{1,3}), \d{1,3}, \d{1,3}.*/, '$1')), - g: Number(c.replace(/rgba?\(\d{1,3}, (\d{1,3}), \d{1,3}.*/, '$1')), - b: Number(c.replace(/rgba?\(\d{1,3}, \d{1,3}, (\d{1,3}).*/, '$1')), - }; - let s = 255 - Math.max(c_ob.r, c_ob.g, c_ob.b); - v.style.color = `rgb(${c_ob.r+s}, ${c_ob.g+s}, ${c_ob.b+s})`; - }); - }, - set_color_all = (style = my_style_text) => { - set_color(all); - document.querySelectorAll('iframe').forEach((v) => { - if (v.src && (new URL(v.src, location)).origin == location.origin || v.src == 'about:blank') { - set_color(v.contentDocument.querySelectorAll('*')); - let my_style = v.contentDocument.createElement("style"); - my_style.innerText = style; - v.contentDocument.body.appendChild(my_style); - } - }) - }; + + // license of modified part + // The MIT license + // https://opensource.org/licenses/MIT + + // WIP refactoring + // - chaos conditional; do simply + // - naming; what is that? + // - readability; + + // NOTE mode 0 -> 1 -> 2 -> 1 -> 2... + // TODO write mode detail + // level of extremely(?) + // | 0 + // | 1 + // | 2 + // v + + (() => { + 'use strict'; + + // TODO avoid "God object" + let dark_style = document.body.querySelector('.dark_visited_style'); + const mode = dark_style ? Number(dark_style.getAttribute('mode_stat')) : 0; + + const set_color = (nodes) => { + nodes.forEach(node => { + const color = window.getComputedStyle(node).getPropertyValue('color'); + const [ r, g, b, ] = [ + Number(color.replace(/rgba?\((\d{1,3}), \d{1,3}, \d{1,3}.*/, '$1')), + Number(color.replace(/rgba?\(\d{1,3}, (\d{1,3}), \d{1,3}.*/, '$1')), + Number(color.replace(/rgba?\(\d{1,3}, \d{1,3}, (\d{1,3}).*/, '$1')), + ]; + // TODO rename; what mean "s" is? + const s = 255 - Math.max(r, g, b); + node.style.color = `rgb(${r + s}, ${g + s}, ${b + s})`; + }); + }; + + // TODO use newline w/ Array#join() or heredoc-like `` and use Space, unreadable const my_style_text = 'a:visited{color:#b553ff!important;}:not(html){background-color:transparent!important}html{background-color:#000!important}::-webkit-scrollbar{overflow:hidden;width:.8rem;background:#000;}::-webkit-scrollbar-thumb{overflow:hidden;border-radius:.4rem;background:#ddd;}'; + // TODO element node only + const all = document.body.querySelectorAll('*'); + + const set_color_all = (style = my_style_text) => { + set_color(all); + + document.body.querySelectorAll('iframe[src]').forEach(iframe => { + if (!iframe.src) return; + + // TBD omit base URL + if ((new URL(iframe.src, location.href)).origin === location.origin || + iframe.src === 'about:blank') { + const i_doc = iframe.contentDocument; + set_color(i_doc.querySelectorAll('*')); + + i_doc.body.appendChild(Object.assign(i_doc.createElement('style'), { + innerText: style, + })); + } + }); + }; + switch (mode) { + // TODO separate style and length state case 0: set_color_all(); - my_style = document.createElement("style"); - my_style.className = 'dark_visited_style'; - my_style.innerText = my_style_text; - document.body.appendChild(my_style); - my_style.setAttribute('all_elm_length', all.length); - my_style.setAttribute('mode_stat', 1); + dark_style = document.createElement('style'); + dark_style.className = 'dark_visited_style'; + dark_style.innerText = my_style_text; + document.body.appendChild(dark_style); + + dark_style.setAttribute('all_elm_length', all.length); + dark_style.setAttribute('mode_stat', 1); console.log('0'); break; case 1: - my_style.innerText = '*{background-color:#000!important}'; - if (my_style.getAttribute('all_elm_length') != all.length) { - set_color_all('*{background-color:#000!important}'); - my_style.setAttribute('all_elm_length', all.length); + dark_style.innerText = '* { background-color:#000 !important; }'; + + if (Number(dark_style.getAttribute('all_elm_length')) !== all.length) { + set_color_all('* { background-color: #000 !important; }'); + dark_style.setAttribute('all_elm_length', all.length); } - my_style.setAttribute('mode_stat', 2); + dark_style.setAttribute('mode_stat', 2); console.log('1'); break; case 2: - my_style.innerText = my_style_text; - if (my_style.getAttribute('all_elm_length') != all.length) { + dark_style.innerText = my_style_text; + + if (Number(dark_style.getAttribute('all_elm_length')) !== all.length) { set_color_all(); - my_style.setAttribute('all_elm_length', all.length); + dark_style.setAttribute('all_elm_length', all.length); } - my_style.setAttribute('mode_stat', 1); + dark_style.setAttribute('mode_stat', 1); console.log('2'); break; default: - alert('error mode_stat=' + mode); + console.error('error mode_stat=' + mode); break; } - })()+ })(); +
  • /*
     * @title darkmode
     * @description switchable darkmode
     * @include http://*
     * @include https://*
     * @contributor nanikamado  http://let.hatelabo.jp/nanikamado/let/hLHU5aii3YU5
     * @nitpicker   noromanba   https://noromanba.github.com
     * @license     Unknown (as-is)
     * @javascript_url
     */
    
    // license of modified part
    // The MIT license
    // https://opensource.org/licenses/MIT
    
    // WIP refactoring
    // - chaos conditional; do simply
    // - naming; what is that?
    // - readability;
    
    // NOTE mode 0 -> 1 -> 2 -> 1 -> 2...
    // TODO write mode detail
    // level of extremely(?)
    //  | 0
    //  | 1
    //  | 2
    //  v
    
    (() => {
        'use strict';
    
        // TODO avoid "God object"
        let dark_style = document.body.querySelector('.dark_visited_style');
        const mode = dark_style ? Number(dark_style.getAttribute('mode_stat')) : 0;
    
        const set_color = (nodes) => {
            nodes.forEach(node => {
                const color = window.getComputedStyle(node).getPropertyValue('color');
                const [ r, g, b, ] = [
                    Number(color.replace(/rgba?\((\d{1,3}), \d{1,3}, \d{1,3}.*/, '$1')),
                    Number(color.replace(/rgba?\(\d{1,3}, (\d{1,3}), \d{1,3}.*/, '$1')),
                    Number(color.replace(/rgba?\(\d{1,3}, \d{1,3}, (\d{1,3}).*/, '$1')),
                ];
                // TODO rename; what mean "s" is?
                const s = 255 - Math.max(r, g, b);
                node.style.color = `rgb(${r + s}, ${g + s}, ${b + s})`;
            });
        };
    
        // TODO use newline w/ Array#join() or heredoc-like `` and use Space, unreadable
        const my_style_text = 'a:visited{color:#b553ff!important;}:not(html){background-color:transparent!important}html{background-color:#000!important}::-webkit-scrollbar{overflow:hidden;width:.8rem;background:#000;}::-webkit-scrollbar-thumb{overflow:hidden;border-radius:.4rem;background:#ddd;}';
        // TODO element node only
        const all = document.body.querySelectorAll('*');
    
        const set_color_all = (style = my_style_text) => {
            set_color(all);
    
            document.body.querySelectorAll('iframe[src]').forEach(iframe => {
                if (!iframe.src) return;
    
                // TBD omit base URL
                if ((new URL(iframe.src, location.href)).origin === location.origin ||
                    iframe.src === 'about:blank') {
                    const i_doc = iframe.contentDocument;
                    set_color(i_doc.querySelectorAll('*'));
    
                    i_doc.body.appendChild(Object.assign(i_doc.createElement('style'), {
                        innerText: style,
                    }));
                }
            });
        };
    
        switch (mode) {
            // TODO separate style and length state
            case 0:
                set_color_all();
                dark_style = document.createElement('style');
                dark_style.className = 'dark_visited_style';
                dark_style.innerText = my_style_text;
                document.body.appendChild(dark_style);
    
                dark_style.setAttribute('all_elm_length', all.length);
                dark_style.setAttribute('mode_stat', 1);
                console.log('0');
                break;
            case 1:
                dark_style.innerText = '* { background-color:#000 !important; }';
    
                if (Number(dark_style.getAttribute('all_elm_length')) !== all.length) {
                    set_color_all('* { background-color: #000 !important; }');
                    dark_style.setAttribute('all_elm_length', all.length);
                }
                dark_style.setAttribute('mode_stat', 2);
                console.log('1');
                break;
            case 2:
                dark_style.innerText = my_style_text;
    
                if (Number(dark_style.getAttribute('all_elm_length')) !== all.length) {
                    set_color_all();
                    dark_style.setAttribute('all_elm_length', all.length);
                }
                dark_style.setAttribute('mode_stat', 1);
                console.log('2');
                break;
            default:
                console.error('error mode_stat=' + mode);
                break;
        }
    })();
    
    
  • Permalink
    このページへの個別リンクです。
    RAW
    書かれたコードへの直接のリンクです。
    Packed
    文字列が圧縮された書かれたコードへのリンクです。
    Userscript
    Greasemonkey 等で利用する場合の .user.js へのリンクです。
    Loader
    @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
    Metadata
    コード中にコメントで @xxx と書かれたメタデータの JSON です。