Inject Stylus into shadowRoots

inject styles of stylus-addon in shadowRoot

当前为 2025-10-18 提交的版本,查看 最新版本

// ==UserScript==
// @name                Inject Stylus into shadowRoots
// @namespace           https://greasyfork.org/users/821661
// @version             2.0
// @description         inject styles of stylus-addon in shadowRoot
// @author              hdyzen
// @run-at              document-start
// @match               https://*/*
// @grant               none
// @license             GPL-3.0-only
// ==/UserScript==

const sheet = new CSSStyleSheet();
const sheetInDoc = new CSSStyleSheet();
const originalShadowRootDescriptor = Object.getOwnPropertyDescriptor(ShadowRoot.prototype, "adoptedStyleSheets");
const originalDocumentDescriptor = Object.getOwnPropertyDescriptor(Document.prototype, "adoptedStyleSheets");
const originalAttachShadow = Element.prototype.attachShadow;

function syncStyles() {
    const nodes = document.querySelectorAll(
        "html > style:is(.stylus, .stylish-style, .xstyle, [data-source='User JavaScript and CSS'], .amino, [id^='stylebot']), body > style[data-style-created-by='magicss'], head > style[data-custom-css-by-denis]",
    );

    if (nodes.length === 0) return;

    let cssText = "";
    for (const node of nodes) {
        cssText += `${node.textContent}\n`;
    }

    sheet.replaceSync(cssText);
}

Element.prototype.attachShadow = function (init) {
    const shadowRoot = originalAttachShadow.call(this, init);

    shadowRoot.adoptedStyleSheets.push(sheet);
    shadowRoot.adoptedStyleSheets.push(sheetInDoc);

    return shadowRoot;
};

Object.defineProperty(ShadowRoot.prototype, "adoptedStyleSheets", {
    get() {
        return originalShadowRootDescriptor.get.call(this);
    },
    set(newSheets) {
        if (!newSheets.includes(sheet)) {
            newSheets.push(sheet);
        }
        if (!newSheets.includes(sheetInDoc)) {
            newSheets.push(sheetInDoc);
        }

        originalShadowRootDescriptor.set.call(this, newSheets);
    },
    configurable: true,
    enumerable: true,
});

function syncAdoptedStyles() {
    let stylusRules = "";

    for (const sheet of document.adoptedStyleSheets) {
        if (!sheet.media.mediaText.includes("stylus-")) {
            continue;
        }

        for (const cssRule of sheet.cssRules) {
            stylusRules += `${cssRule.cssText}\n`;
        }
    }

    console.log("Stylus adopted:", stylusRules);

    sheetInDoc.replaceSync(stylusRules);
}
syncAdoptedStyles();

Object.defineProperty(Document.prototype, "adoptedStyleSheets", {
    configurable: true,
    enumerable: originalDocumentDescriptor.enumerable,
    get: originalDocumentDescriptor.get,
    set(newSheets) {
        const result = originalDocumentDescriptor.set.call(this, newSheets);

        syncAdoptedStyles();

        return result;
    },
});

new MutationObserver(syncStyles).observe(document.documentElement, {
    childList: true,
    subtree: true,
    characterData: true,
});