8

在 SDK 0.7.3.1_r27487 中升级我的飞镖编辑器后,我遇到了错误“删除不允许的属性”。

我有一个自定义标签,其模板包含 boostarp 属性“data-target”和“data-toggle”。它在以前的版本下工作,但升级后遇到错误。

安慰

Removing disallowed attribute <A data-toggle="dropdown">
Removing disallowed attribute <BUTTON data-target=".navbar-collapse">
Removing disallowed attribute <BUTTON data-toggle="collapse">

.html 代码

<element extends="div" name="x-navbar" constructor="Navbar">
<template>    
  ..
  <a name="top" href="#" class="dropdown-toggle" data-toggle="dropdown">Shop <b class="caret"></b></a>
  ..
  <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"></button>
</template>
<script type="application/dart" src="custom_ui.dart"></script> 
</element>
4

6 回答 6

10

您可能正在使用Element.innerHtml。您应该改用Element.setInnerHtml

正如您使用这个新方法的参数所看到的,HTML 代码现在已经过验证和过滤。要恢复旧行为,您必须提供允许所有属性的验证器或树清理程序。

要明确允许锚点和按钮上的“数据”:

// Call NodeValidatorBuilder.allowX() methods to customize the validator.

final NodeValidatorBuilder _htmlValidator=new NodeValidatorBuilder.common()
  ..allowElement('a', attributes: ['data-target', 'data-toggle'])
  ..allowElement('button', attributes: ['data-target', 'data-toggle']);

query('#anElement').setInnerHtml('a content', validator: _htmlValidator);

ElementCustomElement类在几个地方(Element.html工厂、innerHtml属性、createFragment方法...)使用 HTML 清理。

即使您不直接在自己的代码中使用这些方法,它们也会被底层的 Dart 库调用(CustomElement类是为Polymer库创建的,但也被最新版本的Web UI库使用)。

目前,没有办法全局禁用或自定义默认清理规则。所以我猜你必须处理setInnerHtml调用......或者等待另一个 SDK 版本来解决这个问题(“data-”属性是有效的 HTML5 代码,但默认的清理过滤器不允许它们以及内联样式:为什么这些属性被认为是不安全的?)。

注意:您应该考虑从 Web UI 切换到 Polymer,因为Web UI 现在已弃用

于 2013-09-21T15:43:03.610 回答
4

对于那些使用 angular dart 的人,您将不得不使用自定义验证重新实现 NgDirective,如下所示:

library ng_bind_html_unsafe;

import 'dart:html' as dom;
import 'package:angular/angular.dart';

@NgDirective(
    selector: '[ng-bind-html-unsafe]',
    map: const {'ng-bind-html-unsafe': '=>value'}    )
class NgBindHtmlUnsafeDirective{
  final dom.Element element;

  NgBindHtmlUnsafeDirective(this.element);

  set value(value) => element.setInnerHtml(value == null ? '' : value.toString(),
                                             validator: new dom.NodeValidatorBuilder()
                                             ..allowHtml5()
                                             ..allowElement('a', attributes: ['href'])
                                             ..allowElement('img', attributes: ['src']));
}

在该特定示例中,我允许链接和图片不经过任何清理,您可以随意扩展它。

于 2014-03-16T17:48:20.757 回答
2

在 Angular 0.9.9ng-bind-html中支持自定义 NodeValidators。

只需注册一个返回自定义的工厂,NodeValidator如其他答案所示

factory(NodeValidator, (Injector inj) => getNodeValidator());

并将ng-bind-html使用此 NodeValidator。

我发现以这种方式包含的 HTML 不是由 Angular 处理的(任何指令/组件/表达式都被忽略)。

当我需要这个时,我使用自定义的 bind-html 指令,如@mabounassif 所示,value之后在 setter中使用此附加代码element.setInnerHtml

if(value != null) {
  _compiler(_element.childNodes, _directiveMap)(_injector, _element.childNodes);
}

另见https://github.com/angular/angular.dart/issues/742

于 2014-03-17T05:33:10.053 回答
2

我想用imgelement with innerHtml,发现上面的答案不完整。它缺少uriPolicy默认为相同来源的那个。定义自定义 UriPolicy 为我解决了这个问题。

class DefaultUriPolicy implements UriPolicy {
  DefaultUriPolicy();

  bool allowsUri(String uri) {
    // Return true/false based on uri comparison
    return true;
  }
}

定义验证器,如下所示:

allowElement('img',
              attributes: ['src'], uriPolicy: new DefaultUriPolicy()))
于 2021-01-04T12:42:33.263 回答
0

对于任何想要使用setInnerHtml并希望允许所有标签和属性的人,您可以使用此验证器:

class AllowAll implements NodeValidator {
    @override
    bool allowsAttribute(Element element, String attributeName, String value) {
       return true;
    }

    @override
    bool allowsElement(Element element) {
      return true;
    }
}

用法:

element.setInnerHtml(
    value,
    validator: AllowAll()
);
于 2021-02-01T14:50:59.827 回答
0

@mabounassif回答我做了以下也允许链接到另一个网站:

import 'dart:html' as dom;
import 'package:angular/angular.dart';

@Directive(selector: '[html-inseguro]')
class HtmlInseguro {
  final dom.Element element;

  final dom.NodeValidatorBuilder _validador;

  HtmlInseguro(this.element)
      : _validador = dom.NodeValidatorBuilder()
          ..allowHtml5()
          ..allowElement('a', attributes: ['href'], uriPolicy: _TodoUriPolicy())
          ..allowElement('img',
              attributes: ['src'], uriPolicy: _TodoUriPolicy());

  @Input('html-inseguro')
  set htmlInseguro(String value) {
    element.setInnerHtml(value?.toString() ?? '', validator: _validador);
  }
}

class _TodoUriPolicy implements dom.UriPolicy {
  @override
  bool allowsUri(String uri) {
    return true;
  }
}

然后在组件中你应该有这样的东西:

@Component(
  template: '''
<div class="vista-previa-mensaje" [html-inseguro]="mensajeAEnviar | dataReplacer: reemplazos | md2html"></div>
''',
  directives: [
    HtmlInseguro,
  ],
  pipes: [Md2Html, DataReplacer])
class YourComponent{
  //...
于 2020-01-25T16:44:56.533 回答