=A!

    @@ -7,9 +7,19 @@ // @license MIT License https://opensource.org/licenses/MIT // @javascript_url +// request part // TODO // - error handling -// - request timeout +// - timeout check +// - responses assert +// - exact feedback +// - under a async request +// TBD +// - wait per fetch +// +// overall +// TODO +// - [Promise#]finally // login required (() => { @@ -46,23 +56,20 @@ const bar = Object.assign(document.createElement('progress'), { max, value: 0, - textContent: 0, + textContent: '0/' + max, }); + // TBD bulk style assign Object.assign(bar.style, { - zIndex: Number.MAX_SAFE_INTEGER || Number.MAX_VALUE, + zIndex: Number.MAX_SAFE_INTEGER, position: 'fixed', top: '50%', opacity: 0.7, }); document.body.appendChild(bar); - // TBD merge style section - bar.style.left = [ - 'calc(50% -', - getComputedStyle(bar).width, - '/ 2)', - ].join(' '); + // TBD merge into style section + bar.style.left = 'calc(50% - ' + getComputedStyle(bar).width + ' / 2)'; return bar; }; @@ -72,36 +79,53 @@ return new Promise(res => setTimeout(res, wait)); }; - // NOTE `await` do not working within Array/NodeList callback loops, sucks + const title = document.title; + // NOTE `await wait()` do not working within Array/NodeList callback loops, sucks // i.e. can not use w/ Array#forEach() NodeList#forEach() and Array#map() et al. WTH // https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop // https://qiita.com/frameair/items/e7645066075666a13063 - // TBD replace to Promise.all stepping w/ loop callback + // TBD replace to Promise.all-stepping w/ loop callback (async () => { const links = document.body.querySelectorAll([ 'a[href^="./editpage?cid="]', ]); const max = links.length; - // TODO feedback visible text + // TODO visible text feedback const feedback = progress(max); // TBD incremental for let done = 0; for (const link of links) { refresh(link); - // TODO into feedback - feedback.value = feedback.textContent = done += 1; + + // TODO decrement from async-part + feedback.value = done += 1; + // TODO into a feedback + const state = [ + String(done).padStart(String(max).length, '0'), + '/', + max, + ].join(''); + feedback.textContent = state; + const remain = max - done; + document.title = '(' + remain + ') ' + title; + await sleep(); - // TBD omit console - console.debug && console.debug([ //eslint-disable-line no-console + // TBD + // - omit console + // - show checkee url + // - responses status + console && console.debug && console.debug([ //eslint-disable-line no-console (new Date).toTimeString().slice(0, 8), - String(done).padStart(String(max).length, '0') + '/' + max, + state, link.textContent, link.href, ].join(' ')); } + // TODO into async finally feedback.remove(); + document.title = title; })(); })();
  • // @title =A!
    // @description Hatena Antenna force bulk checker
    // @include http://a.hatena.ne.jp/HATENA_ID/checklist
    // @include http://a.hatena.ne.jp/HATENA_ID/
    // @contributor noromanba   http://let.hatelabo.jp/noromanba/let/hLHUksLx6YMy
    // @contributor a-kuma3     http://h.hatena.ne.jp/a-kuma3/227133357563872599 (reviewer)
    // @license     MIT License https://opensource.org/licenses/MIT
    // @javascript_url
    
    // request part
    // TODO
    //  - error handling
    //   - timeout check
    //   - responses assert
    //  - exact feedback
    //   - under a async request
    // TBD
    //  - wait per fetch
    //
    // overall
    // TODO
    //   - [Promise#]finally
    
    // login required
    (() => {
        'use strict';
    
        const refresh = async (antenna) => {
            const headers = new Headers();
            headers.set('Content-Type', 'text/html;charset=euc-jp');
    
            const edit = await fetch(antenna.href, {
                // needs cookie
                credentials: 'same-origin',
                // XXX ignoring charset
                headers,
            });
            const txt = await edit.text();
            // TBD DOMParser()
            const url = (txt.match(/^<td><a\s+href="(https?[^"]+)"\s+target="_blank"/m) || [])[1];
            if (!url) return;
    
            // manual checker syntax;
            //      http://a.hatena.ne.jp/check?url=<ENCODED_URL>[&robots=1]
            // min GET interval: 5min c.f.
            //  http://a.hatena.ne.jp/check
            const checker = new URL('http://a.hatena.ne.jp/check');
            checker.searchParams.set('url', url);
    
            await fetch(checker.href, {
                credentials: 'same-origin',
            });
        };
    
        const progress = (max) => {
            const bar = Object.assign(document.createElement('progress'), {
                max,
                value: 0,
                textContent: '0/' + max,
            });
    
            // TBD bulk style assign
            Object.assign(bar.style, {
                zIndex: Number.MAX_SAFE_INTEGER,
                position: 'fixed',
                top: '50%',
                opacity: 0.7,
            });
    
            document.body.appendChild(bar);
            // TBD merge into style section
            bar.style.left = 'calc(50% - ' + getComputedStyle(bar).width + ' / 2)';
    
            return bar;
        };
    
        const sleep = (wait = 1 * 1000) => {
            //const Promise = window.Promise; // ESLint workaround
            return new Promise(res => setTimeout(res, wait));
        };
    
        const title = document.title;
        // NOTE `await wait()` do not working within Array/NodeList callback loops, sucks
        //      i.e. can not use w/ Array#forEach() NodeList#forEach() and Array#map() et al. WTH
        // https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop
        // https://qiita.com/frameair/items/e7645066075666a13063
        // TBD  replace to Promise.all-stepping w/ loop callback
        (async () => {
            const links = document.body.querySelectorAll([
                'a[href^="./editpage?cid="]',
            ]);
            const max = links.length;
    
            // TODO visible text feedback
            const feedback = progress(max);
            // TBD incremental for
            let done = 0;
            for (const link of links) {
                refresh(link);
    
                // TODO decrement from async-part
                feedback.value = done += 1;
                // TODO into a feedback
                const state = [
                    String(done).padStart(String(max).length, '0'),
                    '/',
                    max,
                ].join('');
                feedback.textContent = state;
                const remain = max - done;
                document.title = '(' + remain + ') ' + title;
    
                await sleep();
    
                // TBD
                //  - omit console
                //  - show checkee url
                //  - responses status
                console && console.debug && console.debug([ //eslint-disable-line no-console
                    (new Date).toTimeString().slice(0, 8),
                    state,
                    link.textContent,
                    link.href,
                ].join(' '));
            }
            // TODO into async finally
            feedback.remove();
            document.title = title;
        })();
    })();
    
    
  • Permalink
    このページへの個別リンクです。
    RAW
    書かれたコードへの直接のリンクです。
    Packed
    文字列が圧縮された書かれたコードへのリンクです。
    Userscript
    Greasemonkey 等で利用する場合の .user.js へのリンクです。
    Loader
    @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
    Metadata
    コード中にコメントで @xxx と書かれたメタデータの JSON です。

History

  1. 2018/01/21 04:18:00 - 2018-01-21
  2. 2018/01/02 10:48:20 - 2018-01-02
  3. 2018/01/02 10:31:06 - 2018-01-02
  4. 2017/12/31 06:44:10 - 2017-12-31
  5. 2017/12/30 06:18:15 - 2017-12-30
  6. 2017/12/30 05:37:53 - 2017-12-30
  7. 2017/12/27 08:56:10 - 2017-12-27
  8. 2017/12/27 08:07:28 - 2017-12-27
  9. 2017/12/27 07:44:21 - 2017-12-27
  10. 2017/12/27 07:27:35 - 2017-12-27
  11. 2017/12/27 07:25:24 - 2017-12-27