はてなブックマークメタブ展開

    @@ -6,6 +6,7 @@ // @description コメントメタブと2階ブクマを展開します。 // @author Lhankor_Mhy // @match https://b.hatena.ne.jp/entry/* +// @include https://b.hatena.ne.jp/entry/* // @icon https://b.hatena.ne.jp/favicon.ico // @grant none // ==/UserScript==
  • // ==UserScript==
    // @name         はてなブックマークメタブ展開
    // @title        はてなブックマークメタブ展開
    // @namespace    http://tampermonkey.net/
    // @version      0.1
    // @description  コメントメタブと2階ブクマを展開します。
    // @author       Lhankor_Mhy
    // @match        https://b.hatena.ne.jp/entry/*
    // @include      https://b.hatena.ne.jp/entry/*
    // @icon         https://b.hatena.ne.jp/favicon.ico
    // @grant        none
    // ==/UserScript==
    
    
    (async () => {
        // ブクマ展開(x-template再利用)
        const addBookmark = function (targetElement, bookmark, eid) {
            targetElement.insertAdjacentHTML(
                'beforeend',
                document.getElementById('autoloader-bookmark-item').textContent
                    .replaceAll('{{user_name}}', bookmark.user)
                    .replaceAll('{{bookmarked_url}}', bookmark.url)
                    .replaceAll('{{user_page_path}}', `/${bookmark.user}/`)
                    .replaceAll('{{ sort }}', `recent`)
                    .replaceAll('{{profile_image_url}}', `https://cdn.profile-image.st-hatena.com/users/${bookmark.user}/profile.png`)
                    .replaceAll('{{ #is_public }}is-hidden{{ /is_public }}', `is-hidden`)
                    .replaceAll('{{{comment_expanded}}}', bookmark.comment)
                    .replaceAll('{{{tags}}}', `<li>${bookmark.tags.join('<li>')}`)
                    .replaceAll('{{created}}', bookmark.timestamp)
                    .replaceAll('{{comment_page_path}}', `/entry/${eid}/comment/${bookmark.user}`)
                    .replaceAll('{{#should_nofollow}}nofollow{{/should_nofollow}}', 'nofollow')
                    .replaceAll('{{#enable_button}} is-enabled{{/enable_button}}', 'is-enabled')
    
            )
        };
    
        // 2階ブクマAPIコール
        const targetURLs = [location.href], bookmarksList = []
        for (const targetURL of targetURLs) {
            const { bookmarks, entry_url, eid } = (await (await fetch('https://b.hatena.ne.jp/entry/jsonlite/?url=' + encodeURIComponent(targetURL))).json()) ?? { bookmarks: [], entry_url: null, eid: undefined }
            if (entry_url) targetURLs.push(entry_url)
            bookmarksList.push([bookmarks, eid])
        }
    
        // 2階ブクマをHTMLに展開
        function addUpstairsBookmark(targetElements) {
            bookmarksList.forEach(([bookmarks, eid]) => {
                bookmarks.forEach(bookmark => {
                    const targetUserBookmark = targetElements.find(element => element.dataset?.userName === bookmark.user)
                    if (!targetUserBookmark) return undefined
                    const targetElement = [targetUserBookmark, ...targetUserBookmark.querySelectorAll(`[data-user-name="${bookmark.user}"]`)].pop()
                    addBookmark(targetElement, bookmark, eid)
                })
            })
        }
    
        // メタブをHTMLに展開
        function addMetaBookmark(targetElements) {
            targetElements.forEach(async element => {
                const targetURL = element.querySelector('[data-gtm-label="entry-recent-permalink"]').href
                const { bookmarks, entry_url, eid } = (await (await fetch('https://b.hatena.ne.jp/entry/jsonlite/?url=' + encodeURIComponent(targetURL))).json()) ?? { bookmarks: [], entry_url: null }
                if (!bookmarks.length) return undefined
                // console.log(bookmarks, eid, entry_url)
                bookmarks.forEach(
                    bookmark => {
                        addBookmark(element, bookmark, eid)
                    }
                )
            })
        }
    
        // 初回呼び出し
        addUpstairsBookmark(Array.from(document.querySelectorAll(`.js-bookmarks-recent [data-user-name]`)))
        addMetaBookmark(Array.from(document.querySelectorAll(`.js-bookmarks-recent [data-user-name]`)))
    
        // ブクマ遅延読み込み監視
        const targetNode = document.querySelector('.js-bookmarks-recent');
    
        const upstairsBookmarkMutationConfig = { childList: true };
        const upstairsBookmarkMutationCallback = function (mutationsList, observer) {
            for (const mutation of mutationsList) {
                if (mutation.type === 'childList') {
                    addUpstairsBookmark(Array.from(mutation.addedNodes).filter(node => node.dataset?.userName))
                }
            }
        };
        const upstairsBookmarkMutationObserver = new MutationObserver(upstairsBookmarkMutationCallback);
        upstairsBookmarkMutationObserver.observe(targetNode, upstairsBookmarkMutationConfig);
    
        const metaBookmarkMutationConfig = { childList: true, subtree: true };
        const metaBookmarkMutationCallback = function (mutationsList, observer) {
            for (const mutation of mutationsList) {
                if (mutation.type === 'childList') {
                    addMetaBookmark(Array.from(mutation.addedNodes).filter(node => node.dataset?.userName))
                }
            }
        };
        const metaBookmarkMutationObserver = new MutationObserver(metaBookmarkMutationCallback);
        metaBookmarkMutationObserver.observe(targetNode, metaBookmarkMutationConfig);
    
    })()
    
    
    
    
  • Permalink
    このページへの個別リンクです。
    RAW
    書かれたコードへの直接のリンクです。
    Packed
    文字列が圧縮された書かれたコードへのリンクです。
    Userscript
    Greasemonkey 等で利用する場合の .user.js へのリンクです。
    Loader
    @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
    Metadata
    コード中にコメントで @xxx と書かれたメタデータの JSON です。

History

  1. 2024/03/28 12:21:28 - 19 hours ago
  2. 2024/02/13 19:20:41 - 02/13
  3. 2024/02/10 11:23:56 - 02/10
  4. 2023/04/14 19:09:20 - 2023-04-14
  5. 2023/04/13 16:02:01 - 2023-04-13
  6. 2023/04/06 16:06:41 - 2023-04-06
  7. 2023/01/04 15:14:24 - 2023-01-04
  8. 2022/12/28 15:21:54 - 2022-12-28
  9. 2022/12/28 14:33:58 - 2022-12-28
  10. 2022/12/28 14:33:40 - 2022-12-28
  11. 2022/12/27 18:35:10 - 2022-12-27
  12. 2022/12/27 18:28:52 - 2022-12-27
  13. 2022/12/27 18:26:23 - 2022-12-27
  14. 2022/12/27 18:23:32 - 2022-12-27