Select CSS iOS 内容阻止中的父“选择器”

Select CSS Parent `selector` in iOS Content Blocking

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

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

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

现在,我想知道我是否可以有一个 CSS 选择器选择 .bad 然后删除整个 .random div 块。

我试过类似的东西:

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

div:has(a).

似乎没有任何效果。

有人知道这是否可能吗?我什至找不到任何地方说明 apple 支持什么 (CSS4?)

Update:: 现在在 Safari 和 Safari 中得到支持 iOS。来源:caniuse

目前 selector 在 css 中没有父项,尽管它是请求最多的 CSS 功能之一。

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

目前最接近父元素 select 或 CSS 的是 :focus-within,如果元素或其任何元素匹配后代是重点。但是它对你的情况没有用。

提议的父 selector 实现是 :has 并且是 CSS selectors.[=27= 的第 4 级的一部分]

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

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

https://caniuse.com/css-has

即使没有 CSS 父 select 或者,您所描述的内容可以通过 Javascript 在您的 Safari 扩展中轻松实现。

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

用户必须接受权限。如果他们拒绝,您将无法通过 javascript.

访问页面 DOM

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

在content_scripts中你需要添加

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

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

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