Greasy Fork 支持简体中文。

Adobe Fonts Downloader

Adds a download button to Adobe Fonts.

// ==UserScript==
// @name         Adobe Fonts Downloader
// @description  Adds a download button to Adobe Fonts.
// @icon         https://badnoise.net/TypeRip/favicon.png
// @version      1.3
// @author       afkarxyz
// @namespace    https://github.com/afkarxyz/misc-scripts/
// @supportURL   https://github.com/afkarxyz/misc-scripts/issues
// @license      MIT
// @match        https://fonts.adobe.com/*
// @match        https://badnoise.net/TypeRip/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        window.close
// @run-at       document-end
// ==/UserScript==

(function() {
    'use strict';

    if (window.location.hostname === 'badnoise.net') {
        const adobeUrl = GM_getValue('adobeFontUrl', '');
        if (adobeUrl) {
            GM_setValue('adobeFontUrl', '');

            const waitForElement = (selector) => {
                return new Promise(resolve => {
                    if (document.querySelector(selector)) {
                        return resolve(document.querySelector(selector));
                    }

                    const observer = new MutationObserver(mutations => {
                        if (document.querySelector(selector)) {
                            observer.disconnect();
                            resolve(document.querySelector(selector));
                        }
                    });

                    observer.observe(document.body, {
                        childList: true,
                        subtree: true
                    });
                });
            };

            Promise.all([
                waitForElement('#url_input'),
                waitForElement('#url_submit_button')
            ]).then(([urlInput, submitButton]) => {
                urlInput.value = adobeUrl;
                urlInput.dispatchEvent(new Event('input', { bubbles: true }));
                submitButton.click();
            });
        }
        return;
    }

    function getFullFontUrl(href) {
        if (!href) return '';
        if (href.startsWith('http')) return href;
        return `https://fonts.adobe.com${href}`;
    }

    function createDownloadButton(originalButton) {
        const newButton = originalButton.cloneNode(true);
        originalButton.parentNode.replaceChild(newButton, originalButton);

        const labelSpan = newButton.querySelector('.spectrum-Button-label, .add-family-label');
        if (labelSpan) {
            labelSpan.textContent = 'Download';
        }

        newButton.removeAttribute('ng-click');
        newButton.removeAttribute('ng-show');

        newButton.addEventListener('click', function(e) {
            e.preventDefault();
            e.stopPropagation();

            let fontUrl = '';
            const cardLink = newButton.closest('.adobe-fonts-family-card')?.querySelector('.adobe-fonts-family-card--link');
            if (cardLink) {
                fontUrl = getFullFontUrl(cardLink.getAttribute('href'));
            } else {
                fontUrl = window.location.href;
            }

            GM_setValue('adobeFontUrl', fontUrl);
            window.open('https://badnoise.net/TypeRip/', '_blank');
        });

        return newButton;
    }

    function modifyButtons() {
        const buttons = document.querySelectorAll([
            '.adobe-fonts-family__top-actions-add-family button',
            'button[ng-click*="useModelSyncFontpack"]',
            '.collection-show__font-pack-actions-bottom button.add-family-button',
            '.add-family-button'
        ].join(','));

        buttons.forEach(button => {
            if (button.hasAttribute('data-modified')) return;
            const newButton = createDownloadButton(button);
            newButton.setAttribute('data-modified', 'true');
        });
    }

    function changeTextToDownload(node) {
        if (node.nodeType === Node.ELEMENT_NODE) {
            if (node.classList.contains('add-family-button') && !node.hasAttribute('data-modified')) {
                const newButton = createDownloadButton(node);
                newButton.setAttribute('data-modified', 'true');
            }
            if (node.shadowRoot) {
                changeTextToDownload(node.shadowRoot);
            }
            node.childNodes.forEach(child => changeTextToDownload(child));
        }
    }

    function init() {
        modifyButtons();
        changeTextToDownload(document.body);
    }

    init();

    const observer = new MutationObserver((mutations) => {
        for (const mutation of mutations) {
            const currentUrl = location.href;
            if (window.lastUrl !== currentUrl) {
                window.lastUrl = currentUrl;
                init();
                continue;
            }

            const addedNodes = Array.from(mutation.addedNodes);
            const hasNewButton = addedNodes.some(node =>
                node.querySelector && (
                    node.querySelector('.adobe-fonts-family__top-actions-add-family') ||
                    node.querySelector('button[ng-click*="useModelSyncFontpack"]') ||
                    node.querySelector('.collection-show__font-pack-actions-bottom') ||
                    node.querySelector('.add-family-button')
                )
            );
            if (hasNewButton) {
                init();
                break;
            }

            addedNodes.forEach(changeTextToDownload);
        }
    });

    window.lastUrl = location.href;
    observer.observe(document.body, {
        childList: true,
        subtree: true
    });
})();