0

我正在设置一些内容拦截器(https://developer.apple.com/documentation/safariservices/creating_a_content_blocker

我正在测试的 HTML 看起来像这样:

<div class="<random>">
  <div>
    <div>
      <div>
        <a class="bad" />

现在,我想知道我是否可以有一个 CSS 选择器,它选择打开.bad但随后删除整个.randomdiv 块。

我试过这样的事情:

  {
    "action": {
      "type": "css-display-none",
      "selector": "div > div > div > div >a[href*='speedtest.net']"
    },
    "trigger": {
      "url-filter": "^https?:\/+([^\/:]+\\.)?google.*[:\/]"
    }
  }

div:has(a)

似乎没有任何效果。

任何人都知道它是否可能?我什至找不到任何说明苹果对此支持的地方(CSS4?)

4

1 回答 1

3

目前 CSS 中没有父选择器,尽管它是最需要的 CSS 功能之一。

缺乏实现的简单原因是性能问题。 https://snook.ca/archives/html_and_css/css-parent-selectors

我们现在最接近 CSS 中的父选择器的是:focus-within,如果元素或其任何后代被聚焦,它将匹配一个元素。但是,在您的情况下它没有用。

您提到的父选择器的建议实现是:has并且是 CSS 选择器第 4 级的一部分。

https://www.w3.org/TR/selectors-4/

虽然它还没有在任何浏览器中实现,但它现在是 Safari 技术预览的一部分,所以我们可能有一天会得到它。然而,它还不是 iOS 技术预览的一部分,这可能仍然需要很多时间。

https://caniuse.com/css-has

即使没有 CSS 父选择器,您所描述的也可以通过 Safari 扩展中的 Javascript 轻松实现。

但是,您需要授予 Safari 扩展权限才能在网页中注入脚本。

用户必须接受权限。如果他们拒绝,您将无法通过 javascript 访问页面 DOM。

你可以通过进入manifest.json你的 Xcode 项目来做到这一点:AppName => Shared (Extension) => Ressources => manifest

在 content_scripts 你需要添加

"content_scripts": [{
    "js": [ "content.js" ],
    "matches": [ "<all_urls>" ]
}]

您还可以像以前一样使用正则表达式选择您希望扩展程序可以访问的站点。

https://developer.apple.com/documentation/safariservices/safari_web_extensions/managing_safari_web_extension_permissions

然后在content.js文件中,您可以添加您的 javascript 代码以随意编辑网页。

这是一个可以用来删除坏元素的父元素的函数:

const removeBadElementParent = () =>{
    const badElements = document.querySelectorAll('.bad-class-name')
    if(badElements.length === 0) return;
    
    badElements.forEach(element =>{
        if(!element instanceof HTMLElement) return;
        const parent = element.parentElement;
        
        if(!parent instanceof HTMLElement) return;
        parent.style.display = 'none'
    })
}

您不想立即使用它,但仅在 DOM 加载后才使用它,因此您需要像这样调用它:

if( document.readyState !== 'loading' ) {
    removeBadElementParent();
} else {
    document.addEventListener("DOMContentLoaded", function(event) {
        removeBadElementParent();
    });
}

然而,大多数网站都会对 DOM 进行更改,并且可能会在 DOMContentLoaded 事件触发后添加错误元素。因此,您需要添加一个变异观察者来检查 DOM 何时更改:

const onDOMMutation = (callback) =>{
    MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
    const observer = new MutationObserver(function(mutations, observer) {
        callback();
    });

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

您可以这样调用它,而不是直接调用removeBadElementParent函数:

if( document.readyState !== 'loading' ) {
    onDOMMutation(removeBadElementParent);
} else {
    document.addEventListener("DOMContentLoaded", function(event) {
        onDOMMutation(removeBadElementParent);
    });
}

https://developer.apple.com/documentation/safariservices/safari_app_extensions/injecting_a_script_into_a_webpage

于 2022-01-26T22:17:36.887 回答