用于设置任意网站的 Shadow DOM 元素样式的用户脚本

问题描述 投票:0回答:1

这是我的用户脚本,用于更改访问链接的颜色。假设它能够与任何网站一起使用。

// ==UserScript==
// @name        Change the color of visited links
// @description -
// @match       *://*/*
// ==/UserScript==

function style(css) {
  let head, style;
  head = document.getElementsByTagName('head')[0];
  if (!head) return;
  style = document.createElement('style');
  style.type = 'text/css';
  style.innerHTML = css.replace(/;/g, '!important;');
  head.appendChild(style);
}

function links(anylink, link, visited, hover, active) {
  style(`
    ${anylink} { outline: solid 1px; }
    ${link}    { color: blue;    }
    ${visited} { color: fuchsia; }
    ${hover}   { color: red;     }
    ${active}  { color: yellow;  }
  `);
}

links('a:any-link , a:any-link *',
      'a:link     , a:link     *',
      'a:visited  , a:visited  *',
      'a:hover    , a:hover    *',
      'a:active   , a:active   *'
     );

问题在于,在某些网站上,某些链接属于影子 DOM 元素,因此它们不受脚本的影响。如何解决这个问题?

javascript css shadow-dom userscripts
1个回答
0
投票

您可以使用

document.querySelector(selector).shadowRoot

访问影子 DOM

从那里您需要使用

head
找到第一个
querySelectorAll
或默认为元素本身,然后在那里注入 CSS。

// setup example
const host = document.querySelector("#host");
const shadow = host.attachShadow({
  mode: "open"
});
const span = document.createElement("span");
span.innerHTML = "I'm in the shadow DOM <a href='#'>link</a>";
shadow.appendChild(span);


function addToHeadOrSelf(elem, css) {
  var head

  if (elem.getElementsByTagName) {
    head = elem.getElementsByTagName('head')[0];
  }

  if (elem.querySelectorAll) {
    head = elem.querySelectorAll('head')[0]
  }

  if (!head) {
    head = elem
  }

  style = document.createElement('style');
  style.type = 'text/css';
  style.innerHTML = css.replace(/;/g, '!important;');
  head.appendChild(style);
}

function style(css) {
  addToHeadOrSelf(document, css)

  var elementsWithShadowRoot = findElementsWithShadowRoot()
  elementsWithShadowRoot.forEach(function(elem) {
    addToHeadOrSelf(elem.shadowRoot, css)
  })

}

function findElementsWithShadowRoot() {
  function hasShadowRoot(element) {
    return element.shadowRoot !== null;
  }

  function traverseTree(node) {
    if (hasShadowRoot(node)) {
      elementsWithShadowRoot.push(node);
    }

    const children = node.children || [];
    for (let i = 0; i < children.length; i++) {
      traverseTree(children[i]);
    }
  }

  const elementsWithShadowRoot = [];
  traverseTree(document.body);
  return elementsWithShadowRoot;
}



function links(anylink, link, visited, hover, active) {
  style(`
    ${anylink} { outline: solid 1px; }
    ${link}    { color: blue;    }
    ${visited} { color: fuchsia; }
    ${hover}   { color: red;     }
    ${active}  { color: yellow;  }
  `);
}

links('a:any-link , a:any-link *',
  'a:link     , a:link     *',
  'a:visited  , a:visited  *',
  'a:hover    , a:hover    *',
  'a:active   , a:active   *'
);
<div id="host"></div>

<span>I'm not in the shadow DOM <a href='#'>link</a></span>
<br />

© www.soinside.com 2019 - 2024. All rights reserved.