I've got a <safe-html>
element working. Verified on Chrome and even post-dart2js on Safari. Vote up this answer if you'd like me to turn it into a lib available on pub.dartlang.org.
Usage:
<safe-html validator="{{nodeValidator}}">{{someHtml}}</safe-html>
(Passing in your own validator
is optional. Without it, we'll use a default.)
safe_html.html:
<link rel="import" href="../../../../../../../packages/polymer/polymer.html">
<polymer-element name="safe-html">
<template>
<div id="container"></div>
</template>
<script type="application/dart" src='safe_html.dart'></script>
</polymer-element>
safe_html.dart:
library safe_html;
import 'dart:async';
import "dart:html";
import "package:polymer/polymer.dart";
@CustomTag("safe-html")
class SafeHtml extends PolymerElement {
@published NodeValidator validator = new NodeValidatorBuilder()
..allowHtml5(uriPolicy: new DefaultUriPolicy());
SafeHtml.created() : super.created();
addFragment() {
DivElement container = $['container'];
String fragment = this.text;
container.setInnerHtml(fragment, // Set the fragment in a safe way.
validator: validator);
this.text = ""; // Clear the original fragment passed to the element.
}
attached() {
addFragment();
}
}
class DefaultUriPolicy implements UriPolicy {
DefaultUriPolicy();
// Allow all external, absolute URLs.
RegExp regex = new RegExp(r'(?:http://|https://|//)?.*');
bool allowsUri(String uri) {
return regex.hasMatch(uri);
}
}
If you choose to pass your own NodeValidator
, do it by specifying a getter in the parent element that uses <safe-html>
:
NodeValidator get nodeValidator => new NodeValidatorBuilder()
..allowHtml5(uriPolicy: new ItemUrlPolicy());
As you can see I reference a UriPolicy
which I keep in a separate file like uri_policy.dart:
import 'dart:html';
class ItemUrlPolicy implements UriPolicy {
ItemUrlPolicy();
RegExp regex = new RegExp(r'(?:http://|https://|//)?.*');
bool allowsUri(String uri) {
return regex.hasMatch(uri);
}
}
With lots of help from Günter Zöchbauer and the authors of other helpful posts on SO.