Pixiv Favorited Tags Append

支持将 Pixiv “喜欢的标签”添加到搜索栏

// ==UserScript==
// @name         Pixiv Favorited Tags Append
// @namespace    http://tampermonkey.net/
// @version      2025-07-29
// @description  支持将 Pixiv “喜欢的标签”添加到搜索栏
// @author       ctrn43062
// @match        https://www.pixiv.net/artworks/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=pixiv.net
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    const input = document.querySelector('.charcoal-text-field-input')
    const waitForElement = (select, max_try=100, interval=20) => {
        const delay = async () => {
            return new Promise(resolve => {
                setTimeout( () => resolve(), interval)
            }
                              )
        }

        return new Promise(async (resolve, reject) => {
            let el = null

            do {
                console.debug(`Searching ${select}, ${max_try} try remain`)
                await delay(interval)
                el = document.querySelectorAll(select)
            } while ((!el || !el.length) && max_try--)
                resolve(el)
        }
                          )
    }

    input.addEventListener('click', async () => {
        const myTags = await waitForElement('.gtm-my-tag-link')
        const search = document.querySelector('.charcoal-text-field-input')

        // assert myTags is not empty
        console.log(myTags)

        myTags.forEach(tag => {
            const container = tag.parentElement
            // 判断是否已有 append 按钮
            if(container.getAttribute('data-append')) {
                return
            }

            // 修改 parent 样式
            Object.assign(container.style, {
                'flex-direction': 'column',
                'justify-content': 'center'
            })

            // 添加 append 按钮
            const appendTagToSearchButton = document.createElement('span')
            appendTagToSearchButton.textContent = '+ Append'
            Object.assign(appendTagToSearchButton.style, {
                'text-align': 'center',
                'margin-top': '4px',
                'cursor': 'pointer',
                'white-space': 'nowrap'
            })
            appendTagToSearchButton.className = tag.className

            appendTagToSearchButton.addEventListener('click', () => {
                const tagText = tag.innerText.split(/\s+/).pop().replace(/^#/, ' ')
                search.value = search.value + tagText
            })

            container.setAttribute('data-append', true)
            container.appendChild(appendTagToSearchButton)
        })
    })
})();