使用 AngleSharp 插入自定义元素

Inserting Custom Element with AngleSharp

我正在尝试更新一个网站,该网站使用基于 AngleSharp 的消毒剂来处理用户生成的 HTML 内容。站点用户需要能够嵌入 iframe,我正在尝试使用白名单来控制框架可以加载哪些域。我想将 'blocked' iframe 重写为一个新的自定义元素 "blocked-iframe",该元素随后将被消毒剂去除,因此我们可以检查是否需要将其他域添加到白名单中。

我正在尝试使用基于此答案的解决方案:

看起来是这样的:

    string BlockIFrames(string content)
    {
        var parser = new HtmlParser(new HtmlParserOptions { });

        var doc = parser.Parse(content);

        foreach (var element in doc.QuerySelectorAll("iframe"))
        {
            var src = element.GetAttribute("src");

            if (string.IsNullOrEmpty(src) || !Settings.Sanitization.IFrameWhitelist.Any(wls => src.StartsWith(wls)))
            {
                var newElement = doc.CreateElement("blocked-iframe");
                foreach (var attr in element.Attributes)
                {
                    newElement.SetAttribute(attr.Name, attr.Value);
                }

                element.Insert(AdjacentPosition.BeforeBegin, newElement.OuterHtml);

                element.Remove();
            }
        }

        return doc.FirstElementChild.OuterHtml;
    }

它表面上有效,但我注意到新元素标记中的尖括号在插入时被转义,因此结果只是作为文本写入页面。我想我可以构建一个替换映射,然后在发回之前对字符串执行它们,但我想知道是否有办法使用 AngleSharp 的 API 来完成它。该网站目前使用的是 0.9.9,考虑到其他一些依赖项,我不确定我们还能提前多久进行更新。

在源代码中挖掘,我在 INode 中找到了 ReplaceChild 方法,如果从 element

的父级调用,它会起作用
    string BlockIFrames(string content)
    {
        var parser = new HtmlParser(new HtmlParserOptions { });

        var doc = parser.Parse(content);

        foreach (var element in doc.QuerySelectorAll("iframe"))
        {
            var src = element.GetAttribute("src");

            if (string.IsNullOrEmpty(src) ||
                !Settings.Sanitization.IFrameWhitelist.Any(wls => src.StartsWith(wls)))
            {
                var newElement = doc.CreateElement("blocked-iframe");
                foreach (var attr in element.Attributes)
                {
                    newElement.SetAttribute(attr.Name, attr.Value);
                }

                element.Parent.ReplaceChild(newElement, element);
            }
        }

        return doc.FirstElementChild.OuterHtml;
    }

我会继续测试,但这对我来说似乎还不错,如果有更好的方法我很乐意听到。