I[★] Fork

    @@ -2,24 +2,33 @@ * @title greed quote star feat. Proxy * @description 引用になってなくても引用スターできるようにします * @include http://* - * @license MIT License + * @include https://* + * @contributor Hatena inc. https://s.hatena.ne.jp/images/add.gif + * @contributor a-kuma3 http://let.hatelabo.jp/a-kuma3/let/hJmc_YyG8sE- + * @nitpicker noromanba + * @license MIT License https://opensource.org/licenses/MIT * @javascript_url */ + (() => { + 'use strict'; + // make star add button's color gold function change_button_color(img) { // change color with canvas // https://developer.mozilla.org/ja/docs/Web/Guide/HTML/Canvas_tutorial/Pixel_manipulation_with_canvas let canvas; - document.querySelectorAll('img.hatena-star-add-button[src*="s.hatena.ne.jp"').forEach(target => { + document.body.querySelectorAll([ + 'img.hatena-star-add-button[src*="s.hatena.ne.jp"]', + ]).forEach(button => { if (! canvas) { - canvas = Object.assign(document.createElement("canvas"), { + canvas = Object.assign(document.createElement('canvas'), { width: img.width, height: img.height, }); - let ctx = canvas.getContext('2d'); + const ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0); - let imageData = ctx.getImageData(0, 0, img.width, img.height); + const imageData = ctx.getImageData(0, 0, img.width, img.height); let data = imageData.data; for (let i = 0 ; i < data.length ; i += 4) { if (data[i] < 200) {
    @@ -32,35 +41,35 @@ } ctx.putImageData(imageData, 0, 0); } - target.src = canvas.toDataURL(); - target.title = target.title + " (force quote)"; + button.src = canvas.toDataURL(); + button.title = button.title + ' (force quote)'; }); } - document.body.appendChild(Object.assign(document.createElement("img"), { - // http://s.hatena.ne.jp/images/add.gif + document.body.appendChild(Object.assign(document.createElement('img'), { + // https://s.hatena.ne.jp/images/add.gif + // XXX check term of use src: 'data:image/gif;base64,R0lGODlhEAAQAIABALrJ9f///yH5BAEAAAEALAAAAAAQABAAAAIojI+pm+APYQCIMlfZtLOvSEkexhmchXkjaHYlGpLpqrZNqbngnvd+AQA7', // https://stackoverflow.com/questions/17035106/context-getimagedata-operation-is-insecure - crossOrigin: "anonymous", - onload: function() { + crossOrigin: 'anonymous', + onload() { change_button_color(this); }, })); - // http://q.hatena.ne.jp/1487227736#a1262105 - function convert_numeric_reference_quote(url /* string */) { + function convert_numeric_reference_quote(url_string) { // https://developer.mozilla.org/en-US/docs/Web/API/URL // https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams - const u = new URL(url); /* string -> URL */ - let param = u.searchParams; /* URLSearchParams */ - let quote = param.get("quote"); + const url = new URL(url_string); + const param = url.searchParams; + let quote = param.get('quote'); if (quote) { // to numeric reference quote = (s => { - let o = "", i = 0; + let o = '', i = 0; while (i < s.length) { - let code = s.codePointAt(i); + const code = s.codePointAt(i); o += code < 128 ? String.fromCharCode(code) : `&#${code};`; i += 1; if (code > 0xffff) { // for surrogate pair
    @@ -69,29 +78,28 @@ } return o; })(quote); - param.set("quote", quote); - u.search = "?" + param.toString(); - url = u.href; + param.set('quote', quote); + url_string = url.href; } - return url; + return url_string; } - const re_addstar = new RegExp(String.raw`^https?://s\.hatena\.ne\.jp/star\.add\.json`); + const Ten = window.Ten; + if (!Ten) return; // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy Ten.JSONP = new Proxy(Ten.JSONP, { construct: (target, args) => { + const re_addstar = /^https?:\/\/s\.hatena\.ne\.jp\/star\.add\.json/; let url = args[0]; if (re_addstar.test(url)) { url = convert_numeric_reference_quote(url); args[0] = url; } - let obj = Reflect.construct(target, args); - return obj; + return Reflect.construct(target, args); }, }); })(); -
  • /*
     * @title greed quote star feat. Proxy
     * @description 引用になってなくても引用スターできるようにします
     * @include http://*
     * @include https://*
     * @contributor Hatena inc. https://s.hatena.ne.jp/images/add.gif
     * @contributor a-kuma3     http://let.hatelabo.jp/a-kuma3/let/hJmc_YyG8sE-
     * @nitpicker   noromanba
     * @license     MIT License https://opensource.org/licenses/MIT
     * @javascript_url
     */
    
    (() => {
        'use strict';
    
        // make star add button's color gold
        function change_button_color(img) {
            // change color with canvas
            // https://developer.mozilla.org/ja/docs/Web/Guide/HTML/Canvas_tutorial/Pixel_manipulation_with_canvas
            let canvas;
            document.body.querySelectorAll([
                'img.hatena-star-add-button[src*="s.hatena.ne.jp"]',
            ]).forEach(button => {
                if (! canvas) {
                    canvas = Object.assign(document.createElement('canvas'), {
                        width: img.width,
                        height: img.height,
                    });
                    const ctx = canvas.getContext('2d');
                    ctx.drawImage(img, 0, 0);
                    const imageData = ctx.getImageData(0, 0, img.width, img.height);
                    let data = imageData.data;
                    for (let i = 0 ; i < data.length ; i += 4) {
                        if (data[i] < 200) {
                            // gold : rgb(255,215,0)
                            data[i]     = 255;      // red
                            data[i + 1] = 215;      // green
                            data[i + 2] = 0;        // blue
    //                      data[i + 3] = 255;      // opacity
                        }
                    }
                    ctx.putImageData(imageData, 0, 0);
                }
                button.src = canvas.toDataURL();
                button.title = button.title + ' (force quote)';
            });
        }
    
        document.body.appendChild(Object.assign(document.createElement('img'), {
            // https://s.hatena.ne.jp/images/add.gif
            // XXX check term of use
            src: 'data:image/gif;base64,R0lGODlhEAAQAIABALrJ9f///yH5BAEAAAEALAAAAAAQABAAAAIojI+pm+APYQCIMlfZtLOvSEkexhmchXkjaHYlGpLpqrZNqbngnvd+AQA7',
            // https://stackoverflow.com/questions/17035106/context-getimagedata-operation-is-insecure
            crossOrigin: 'anonymous',
            onload() {
                change_button_color(this);
            },
        }));
    
        // http://q.hatena.ne.jp/1487227736#a1262105
        function convert_numeric_reference_quote(url_string) {
            // https://developer.mozilla.org/en-US/docs/Web/API/URL
            // https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
            const url = new URL(url_string);
            const param = url.searchParams;
            let quote = param.get('quote');
            if (quote) {
                // to numeric reference
                quote = (s => {
                    let o = '', i = 0;
                    while (i < s.length) {
                        const code = s.codePointAt(i);
                        o += code < 128 ? String.fromCharCode(code) : `&#${code};`;
                        i += 1;
                        if (code > 0xffff) {    // for surrogate pair
                            i += 1;
                        }
                    }
                    return o;
                })(quote);
                param.set('quote', quote);
                url_string = url.href;
            }
            return url_string;
        }
    
        const Ten = window.Ten;
        if (!Ten) return;
    
        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
        Ten.JSONP = new Proxy(Ten.JSONP, {
            construct: (target, args) => {
                const re_addstar = /^https?:\/\/s\.hatena\.ne\.jp\/star\.add\.json/;
                let url = args[0];
                if (re_addstar.test(url)) {
                    url = convert_numeric_reference_quote(url);
                    args[0] = url;
                }
    
                return Reflect.construct(target, args);
            },
        });
    
    })();
    
    
  • Permalink
    このページへの個別リンクです。
    RAW
    書かれたコードへの直接のリンクです。
    Packed
    文字列が圧縮された書かれたコードへのリンクです。
    Userscript
    Greasemonkey 等で利用する場合の .user.js へのリンクです。
    Loader
    @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
    Metadata
    コード中にコメントで @xxx と書かれたメタデータの JSON です。