uri.parse('/foo%20bar').getPath()
will return the decoded path,
+ * /foo bar.
+ *
+ * The raw versions of fields are available too.
+ * uri.parse('/foo%20bar').getRawPath()
will return the raw path,
+ * /foo%20bar. Use the raw setters with care, since
+ * URI::toString
is not guaranteed to return a valid url if a
+ * raw setter was used.
+ *
+ *
All setters return this and so may be chained, a la
+ * uri.parse('/foo').setFragment('part').toString()
.
+ *
+ *
You should not use this constructor directly -- please prefer the factory + * functions {@link uri.parse}, {@link uri.create}, {@link uri.resolve} + * instead.
+ * + *The parameters are all raw (assumed to be properly escaped) parts, and + * any (but not all) may be null. Undefined is not allowed.
+ * + * @constructor + */ +function URI( + rawScheme, + rawCredentials, rawDomain, port, + rawPath, rawQuery, rawFragment) { + this.scheme_ = rawScheme; + this.credentials_ = rawCredentials; + this.domain_ = rawDomain; + this.port_ = port; + this.path_ = rawPath; + this.query_ = rawQuery; + this.fragment_ = rawFragment; + /** + * @type {Array|null} + */ + this.paramCache_ = null; +} + +/** returns the string form of the url. */ +URI.prototype.toString = function () { + var out = []; + if (null !== this.scheme_) { out.push(this.scheme_, ':'); } + if (null !== this.domain_) { + out.push('//'); + if (null !== this.credentials_) { out.push(this.credentials_, '@'); } + out.push(this.domain_); + if (null !== this.port_) { out.push(':', this.port_.toString()); } + } + if (null !== this.path_) { out.push(this.path_); } + if (null !== this.query_) { out.push('?', this.query_); } + if (null !== this.fragment_) { out.push('#', this.fragment_); } + return out.join(''); +}; + +URI.prototype.clone = function () { + return new URI(this.scheme_, this.credentials_, this.domain_, this.port_, + this.path_, this.query_, this.fragment_); +}; + +URI.prototype.getScheme = function () { + // HTML5 spec does not require the scheme to be lowercased but + // all common browsers except Safari lowercase the scheme. + return this.scheme_ && decodeURIComponent(this.scheme_).toLowerCase(); +}; +URI.prototype.getRawScheme = function () { + return this.scheme_; +}; +URI.prototype.setScheme = function (newScheme) { + this.scheme_ = encodeIfExists2( + newScheme, URI_DISALLOWED_IN_SCHEME_OR_CREDENTIALS_); + return this; +}; +URI.prototype.setRawScheme = function (newScheme) { + this.scheme_ = newScheme ? newScheme : null; + return this; +}; +URI.prototype.hasScheme = function () { + return null !== this.scheme_; +}; + + +URI.prototype.getCredentials = function () { + return this.credentials_ && decodeURIComponent(this.credentials_); +}; +URI.prototype.getRawCredentials = function () { + return this.credentials_; +}; +URI.prototype.setCredentials = function (newCredentials) { + this.credentials_ = encodeIfExists2( + newCredentials, URI_DISALLOWED_IN_SCHEME_OR_CREDENTIALS_); + + return this; +}; +URI.prototype.setRawCredentials = function (newCredentials) { + this.credentials_ = newCredentials ? newCredentials : null; + return this; +}; +URI.prototype.hasCredentials = function () { + return null !== this.credentials_; +}; + + +URI.prototype.getDomain = function () { + return this.domain_ && decodeURIComponent(this.domain_); +}; +URI.prototype.getRawDomain = function () { + return this.domain_; +}; +URI.prototype.setDomain = function (newDomain) { + return this.setRawDomain(newDomain && encodeURIComponent(newDomain)); +}; +URI.prototype.setRawDomain = function (newDomain) { + this.domain_ = newDomain ? newDomain : null; + // Maintain the invariant that paths must start with a slash when the URI + // is not path-relative. + return this.setRawPath(this.path_); +}; +URI.prototype.hasDomain = function () { + return null !== this.domain_; +}; + + +URI.prototype.getPort = function () { + return this.port_ && decodeURIComponent(this.port_); +}; +URI.prototype.setPort = function (newPort) { + if (newPort) { + newPort = Number(newPort); + if (newPort !== (newPort & 0xffff)) { + throw new Error('Bad port number ' + newPort); + } + this.port_ = '' + newPort; + } else { + this.port_ = null; + } + return this; +}; +URI.prototype.hasPort = function () { + return null !== this.port_; +}; + + +URI.prototype.getPath = function () { + return this.path_ && decodeURIComponent(this.path_); +}; +URI.prototype.getRawPath = function () { + return this.path_; +}; +URI.prototype.setPath = function (newPath) { + return this.setRawPath(encodeIfExists2(newPath, URI_DISALLOWED_IN_PATH_)); +}; +URI.prototype.setRawPath = function (newPath) { + if (newPath) { + newPath = String(newPath); + this.path_ = + // Paths must start with '/' unless this is a path-relative URL. + (!this.domain_ || /^\//.test(newPath)) ? newPath : '/' + newPath; + } else { + this.path_ = null; + } + return this; +}; +URI.prototype.hasPath = function () { + return null !== this.path_; +}; + + +URI.prototype.getQuery = function () { + // From http://www.w3.org/Addressing/URL/4_URI_Recommentations.html + // Within the query string, the plus sign is reserved as shorthand notation + // for a space. + return this.query_ && decodeURIComponent(this.query_).replace(/\+/g, ' '); +}; +URI.prototype.getRawQuery = function () { + return this.query_; +}; +URI.prototype.setQuery = function (newQuery) { + this.paramCache_ = null; + this.query_ = encodeIfExists(newQuery); + return this; +}; +URI.prototype.setRawQuery = function (newQuery) { + this.paramCache_ = null; + this.query_ = newQuery ? newQuery : null; + return this; +}; +URI.prototype.hasQuery = function () { + return null !== this.query_; +}; + +/** + * sets the query given a list of strings of the form + * [ key0, value0, key1, value1, ... ]. + * + *uri.setAllParameters(['a', 'b', 'c', 'd']).getQuery()
+ * will yield 'a=b&c=d'
.
+ */
+URI.prototype.setAllParameters = function (params) {
+ if (typeof params === 'object') {
+ if (!(params instanceof Array)
+ && (params instanceof Object
+ || Object.prototype.toString.call(params) !== '[object Array]')) {
+ var newParams = [];
+ var i = -1;
+ for (var k in params) {
+ var v = params[k];
+ if ('string' === typeof v) {
+ newParams[++i] = k;
+ newParams[++i] = v;
+ }
+ }
+ params = newParams;
+ }
+ }
+ this.paramCache_ = null;
+ var queryBuf = [];
+ var separator = '';
+ for (var j = 0; j < params.length;) {
+ var k = params[j++];
+ var v = params[j++];
+ queryBuf.push(separator, encodeURIComponent(k.toString()));
+ separator = '&';
+ if (v) {
+ queryBuf.push('=', encodeURIComponent(v.toString()));
+ }
+ }
+ this.query_ = queryBuf.join('');
+ return this;
+};
+URI.prototype.checkParameterCache_ = function () {
+ if (!this.paramCache_) {
+ var q = this.query_;
+ if (!q) {
+ this.paramCache_ = [];
+ } else {
+ var cgiParams = q.split(/[&\?]/);
+ var out = [];
+ var k = -1;
+ for (var i = 0; i < cgiParams.length; ++i) {
+ var m = cgiParams[i].match(/^([^=]*)(?:=(.*))?$/);
+ // From http://www.w3.org/Addressing/URL/4_URI_Recommentations.html
+ // Within the query string, the plus sign is reserved as shorthand
+ // notation for a space.
+ out[++k] = decodeURIComponent(m[1]).replace(/\+/g, ' ');
+ out[++k] = decodeURIComponent(m[2] || '').replace(/\+/g, ' ');
+ }
+ this.paramCache_ = out;
+ }
+ }
+};
+/**
+ * sets the values of the named cgi parameters.
+ *
+ *
So, uri.parse('foo?a=b&c=d&e=f').setParameterValues('c', ['new'])
+ *
yields foo?a=b&c=new&e=f.
http://www.gbiv.com/protocols/uri/rfc/rfc3986.html#RFC2234 says + * As the "first-match-wins" algorithm is identical to the "greedy" + * disambiguation method used by POSIX regular expressions, it is natural and + * commonplace to use a regular expression for parsing the potential five + * components of a URI reference. + * + *
The following line is the regular expression for breaking-down a + * well-formed URI reference into its components. + * + *
+ * ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? + * 12 3 4 5 6 7 8 9 + *+ * + *
The numbers in the second line above are only to assist readability; they
+ * indicate the reference points for each subexpression (i.e., each paired
+ * parenthesis). We refer to the value matched for subexpression msamuel: I have modified the regular expression slightly to expose the
+ * credentials, domain, and port separately from the authority.
+ * The modified version yields
+ *
+ * The HTML sanitizer is built around a SAX parser and HTML element and
+ * attributes schemas.
+ *
+ * If the cssparser is loaded, inline styles are sanitized using the
+ * css property and value schemas. Else they are remove during
+ * sanitization.
+ *
+ * If it exists, uses parseCssDeclarations, sanitizeCssProperty, cssSchema
+ *
+ * @author mikesamuel@gmail.com
+ * @author jasvir@gmail.com
+ * \@requires html4, URI
+ * \@overrides window
+ * \@provides html, html_sanitize
+ */
+
+// The Turkish i seems to be a non-issue, but abort in case it is.
+// if ('I'.toLowerCase() !== 'i') { throw 'I/i problem'; } # Sam ... screwing up in turkish browsers seems a silly idea
+
+/**
+ * \@namespace
+ */
+var html = (function(html4) {
+
+ // For closure compiler
+ var parseCssDeclarations, sanitizeCssProperty, cssSchema;
+ if ('undefined' !== typeof window) {
+ parseCssDeclarations = window.parseCssDeclarations;
+ sanitizeCssProperty = window.sanitizeCssProperty;
+ cssSchema = window.cssSchema;
+ }
+
+ // The keys of this object must be 'quoted' or JSCompiler will mangle them!
+ // This is a partial list -- lookupEntity() uses the host browser's parser
+ // (when available) to implement full entity lookup.
+ // Note that entities are in general case-sensitive; the uppercase ones are
+ // explicitly defined by HTML5 (presumably as compatibility).
+ var ENTITIES = {
+ 'lt': '<',
+ 'LT': '<',
+ 'gt': '>',
+ 'GT': '>',
+ 'amp': '&',
+ 'AMP': '&',
+ 'quot': '"',
+ 'apos': '\'',
+ 'nbsp': '\240'
+ };
+
+ // Patterns for types of entity/character reference names.
+ var decimalEscapeRe = /^#(\d+)$/;
+ var hexEscapeRe = /^#x([0-9A-Fa-f]+)$/;
+ // contains every entity per http://www.w3.org/TR/2011/WD-html5-20110113/named-character-references.html
+ var safeEntityNameRe = /^[A-Za-z][A-za-z0-9]+$/;
+ // Used as a hook to invoke the browser's entity parsing.
+ * http://www.ics.uci.edu/pub/ietf/uri/#Related
+ *
+ * results in the following subexpression matches:
+ *
+ * $1 = http:
+ * $2 = http
+ * $3 = //www.ics.uci.edu
+ * $4 = www.ics.uci.edu
+ * $5 = /pub/ietf/uri/
+ * $6 =
+ * where
+ * scheme = $2
+ * authority = $4
+ * path = $5
+ * query = $7
+ * fragment = $9
+ *
+ *
+ *
+ * $1 = http scheme
+ * $2 =
+ */
+var URI_RE_ = new RegExp(
+ "^" +
+ "(?:" +
+ "([^:/?#]+)" + // scheme
+ ":)?" +
+ "(?://" +
+ "(?:([^/?#]*)@)?" + // credentials
+ "([^/?#:@]*)" + // domain
+ "(?::([0-9]+))?" + // port
+ ")?" +
+ "([^?#]+)?" + // path
+ "(?:\\?([^#]*))?" + // query
+ "(?:#(.*))?" + // fragment
+ "$"
+ );
+
+var URI_DISALLOWED_IN_SCHEME_OR_CREDENTIALS_ = /[#\/\?@]/g;
+var URI_DISALLOWED_IN_PATH_ = /[\#\?]/g;
+
+URI.parse = parse;
+URI.create = create;
+URI.resolve = resolve;
+URI.collapse_dots = collapse_dots; // Visible for testing.
+
+// lightweight string-based api for loadModuleMaker
+URI.utils = {
+ mimeTypeOf: function (uri) {
+ var uriObj = parse(uri);
+ if (/\.html$/.test(uriObj.getPath())) {
+ return 'text/html';
+ } else {
+ return 'application/javascript';
+ }
+ },
+ resolve: function (base, uri) {
+ if (base) {
+ return resolve(parse(base), parse(uri)).toString();
+ } else {
+ return '' + uri;
+ }
+ }
+};
+
+
+return URI;
+})();
+
+// Copyright Google Inc.
+// Licensed under the Apache Licence Version 2.0
+// Autogenerated at Wed Feb 20 13:32:22 EST 2013
+// @overrides window
+// @provides html4
+var html4 = {};
+html4.atype = {
+ 'NONE': 0,
+ 'URI': 1,
+ 'URI_FRAGMENT': 11,
+ 'SCRIPT': 2,
+ 'STYLE': 3,
+ 'HTML': 12,
+ 'ID': 4,
+ 'IDREF': 5,
+ 'IDREFS': 6,
+ 'GLOBAL_NAME': 7,
+ 'LOCAL_NAME': 8,
+ 'CLASSES': 9,
+ 'FRAME_TARGET': 10,
+ 'MEDIA_QUERY': 13
+};
+html4.ATTRIBS = {
+ '*::class': 9,
+ '*::dir': 0,
+ '*::draggable': 0,
+ '*::hidden': 0,
+ '*::id': 4,
+ '*::inert': 0,
+ '*::itemprop': 0,
+ '*::itemref': 6,
+ '*::itemscope': 0,
+ '*::lang': 0,
+ '*::onblur': 2,
+ '*::onchange': 2,
+ '*::onclick': 2,
+ '*::ondblclick': 2,
+ '*::onfocus': 2,
+ '*::onkeydown': 2,
+ '*::onkeypress': 2,
+ '*::onkeyup': 2,
+ '*::onload': 2,
+ '*::onmousedown': 2,
+ '*::onmousemove': 2,
+ '*::onmouseout': 2,
+ '*::onmouseover': 2,
+ '*::onmouseup': 2,
+ '*::onreset': 2,
+ '*::onscroll': 2,
+ '*::onselect': 2,
+ '*::onsubmit': 2,
+ '*::onunload': 2,
+ '*::spellcheck': 0,
+ '*::style': 3,
+ '*::title': 0,
+ '*::translate': 0,
+ 'a::accesskey': 0,
+ 'a::coords': 0,
+ 'a::href': 1,
+ 'a::hreflang': 0,
+ 'a::name': 7,
+ 'a::onblur': 2,
+ 'a::onfocus': 2,
+ 'a::shape': 0,
+ 'a::tabindex': 0,
+ 'a::target': 10,
+ 'a::type': 0,
+ 'area::accesskey': 0,
+ 'area::alt': 0,
+ 'area::coords': 0,
+ 'area::href': 1,
+ 'area::nohref': 0,
+ 'area::onblur': 2,
+ 'area::onfocus': 2,
+ 'area::shape': 0,
+ 'area::tabindex': 0,
+ 'area::target': 10,
+ 'audio::controls': 0,
+ 'audio::loop': 0,
+ 'audio::mediagroup': 5,
+ 'audio::muted': 0,
+ 'audio::preload': 0,
+ 'bdo::dir': 0,
+ 'blockquote::cite': 1,
+ 'br::clear': 0,
+ 'button::accesskey': 0,
+ 'button::disabled': 0,
+ 'button::name': 8,
+ 'button::onblur': 2,
+ 'button::onfocus': 2,
+ 'button::tabindex': 0,
+ 'button::type': 0,
+ 'button::value': 0,
+ 'canvas::height': 0,
+ 'canvas::width': 0,
+ 'caption::align': 0,
+ 'col::align': 0,
+ 'col::char': 0,
+ 'col::charoff': 0,
+ 'col::span': 0,
+ 'col::valign': 0,
+ 'col::width': 0,
+ 'colgroup::align': 0,
+ 'colgroup::char': 0,
+ 'colgroup::charoff': 0,
+ 'colgroup::span': 0,
+ 'colgroup::valign': 0,
+ 'colgroup::width': 0,
+ 'command::checked': 0,
+ 'command::command': 5,
+ 'command::disabled': 0,
+ 'command::icon': 1,
+ 'command::label': 0,
+ 'command::radiogroup': 0,
+ 'command::type': 0,
+ 'data::value': 0,
+ 'del::cite': 1,
+ 'del::datetime': 0,
+ 'details::open': 0,
+ 'dir::compact': 0,
+ 'div::align': 0,
+ 'dl::compact': 0,
+ 'fieldset::disabled': 0,
+ 'font::color': 0,
+ 'font::face': 0,
+ 'font::size': 0,
+ 'form::accept': 0,
+ 'form::action': 1,
+ 'form::autocomplete': 0,
+ 'form::enctype': 0,
+ 'form::method': 0,
+ 'form::name': 7,
+ 'form::novalidate': 0,
+ 'form::onreset': 2,
+ 'form::onsubmit': 2,
+ 'form::target': 10,
+ 'h1::align': 0,
+ 'h2::align': 0,
+ 'h3::align': 0,
+ 'h4::align': 0,
+ 'h5::align': 0,
+ 'h6::align': 0,
+ 'hr::align': 0,
+ 'hr::noshade': 0,
+ 'hr::size': 0,
+ 'hr::width': 0,
+ 'iframe::align': 0,
+ 'iframe::frameborder': 0,
+ 'iframe::height': 0,
+ 'iframe::marginheight': 0,
+ 'iframe::marginwidth': 0,
+ 'iframe::width': 0,
+ 'img::align': 0,
+ 'img::alt': 0,
+ 'img::border': 0,
+ 'img::height': 0,
+ 'img::hspace': 0,
+ 'img::ismap': 0,
+ 'img::name': 7,
+ 'img::src': 1,
+ 'img::usemap': 11,
+ 'img::vspace': 0,
+ 'img::width': 0,
+ 'input::accept': 0,
+ 'input::accesskey': 0,
+ 'input::align': 0,
+ 'input::alt': 0,
+ 'input::autocomplete': 0,
+ 'input::checked': 0,
+ 'input::disabled': 0,
+ 'input::inputmode': 0,
+ 'input::ismap': 0,
+ 'input::list': 5,
+ 'input::max': 0,
+ 'input::maxlength': 0,
+ 'input::min': 0,
+ 'input::multiple': 0,
+ 'input::name': 8,
+ 'input::onblur': 2,
+ 'input::onchange': 2,
+ 'input::onfocus': 2,
+ 'input::onselect': 2,
+ 'input::placeholder': 0,
+ 'input::readonly': 0,
+ 'input::required': 0,
+ 'input::size': 0,
+ 'input::src': 1,
+ 'input::step': 0,
+ 'input::tabindex': 0,
+ 'input::type': 0,
+ 'input::usemap': 11,
+ 'input::value': 0,
+ 'ins::cite': 1,
+ 'ins::datetime': 0,
+ 'label::accesskey': 0,
+ 'label::for': 5,
+ 'label::onblur': 2,
+ 'label::onfocus': 2,
+ 'legend::accesskey': 0,
+ 'legend::align': 0,
+ 'li::type': 0,
+ 'li::value': 0,
+ 'map::name': 7,
+ 'menu::compact': 0,
+ 'menu::label': 0,
+ 'menu::type': 0,
+ 'meter::high': 0,
+ 'meter::low': 0,
+ 'meter::max': 0,
+ 'meter::min': 0,
+ 'meter::value': 0,
+ 'ol::compact': 0,
+ 'ol::reversed': 0,
+ 'ol::start': 0,
+ 'ol::type': 0,
+ 'optgroup::disabled': 0,
+ 'optgroup::label': 0,
+ 'option::disabled': 0,
+ 'option::label': 0,
+ 'option::selected': 0,
+ 'option::value': 0,
+ 'output::for': 6,
+ 'output::name': 8,
+ 'p::align': 0,
+ 'pre::width': 0,
+ 'progress::max': 0,
+ 'progress::min': 0,
+ 'progress::value': 0,
+ 'q::cite': 1,
+ 'select::autocomplete': 0,
+ 'select::disabled': 0,
+ 'select::multiple': 0,
+ 'select::name': 8,
+ 'select::onblur': 2,
+ 'select::onchange': 2,
+ 'select::onfocus': 2,
+ 'select::required': 0,
+ 'select::size': 0,
+ 'select::tabindex': 0,
+ 'source::type': 0,
+ 'table::align': 0,
+ 'table::bgcolor': 0,
+ 'table::border': 0,
+ 'table::cellpadding': 0,
+ 'table::cellspacing': 0,
+ 'table::frame': 0,
+ 'table::rules': 0,
+ 'table::summary': 0,
+ 'table::width': 0,
+ 'tbody::align': 0,
+ 'tbody::char': 0,
+ 'tbody::charoff': 0,
+ 'tbody::valign': 0,
+ 'td::abbr': 0,
+ 'td::align': 0,
+ 'td::axis': 0,
+ 'td::bgcolor': 0,
+ 'td::char': 0,
+ 'td::charoff': 0,
+ 'td::colspan': 0,
+ 'td::headers': 6,
+ 'td::height': 0,
+ 'td::nowrap': 0,
+ 'td::rowspan': 0,
+ 'td::scope': 0,
+ 'td::valign': 0,
+ 'td::width': 0,
+ 'textarea::accesskey': 0,
+ 'textarea::autocomplete': 0,
+ 'textarea::cols': 0,
+ 'textarea::disabled': 0,
+ 'textarea::inputmode': 0,
+ 'textarea::name': 8,
+ 'textarea::onblur': 2,
+ 'textarea::onchange': 2,
+ 'textarea::onfocus': 2,
+ 'textarea::onselect': 2,
+ 'textarea::placeholder': 0,
+ 'textarea::readonly': 0,
+ 'textarea::required': 0,
+ 'textarea::rows': 0,
+ 'textarea::tabindex': 0,
+ 'textarea::wrap': 0,
+ 'tfoot::align': 0,
+ 'tfoot::char': 0,
+ 'tfoot::charoff': 0,
+ 'tfoot::valign': 0,
+ 'th::abbr': 0,
+ 'th::align': 0,
+ 'th::axis': 0,
+ 'th::bgcolor': 0,
+ 'th::char': 0,
+ 'th::charoff': 0,
+ 'th::colspan': 0,
+ 'th::headers': 6,
+ 'th::height': 0,
+ 'th::nowrap': 0,
+ 'th::rowspan': 0,
+ 'th::scope': 0,
+ 'th::valign': 0,
+ 'th::width': 0,
+ 'thead::align': 0,
+ 'thead::char': 0,
+ 'thead::charoff': 0,
+ 'thead::valign': 0,
+ 'tr::align': 0,
+ 'tr::bgcolor': 0,
+ 'tr::char': 0,
+ 'tr::charoff': 0,
+ 'tr::valign': 0,
+ 'track::default': 0,
+ 'track::kind': 0,
+ 'track::label': 0,
+ 'track::srclang': 0,
+ 'ul::compact': 0,
+ 'ul::type': 0,
+ 'video::controls': 0,
+ 'video::height': 0,
+ 'video::loop': 0,
+ 'video::mediagroup': 5,
+ 'video::muted': 0,
+ 'video::poster': 1,
+ 'video::preload': 0,
+ 'video::width': 0
+};
+html4.eflags = {
+ 'OPTIONAL_ENDTAG': 1,
+ 'EMPTY': 2,
+ 'CDATA': 4,
+ 'RCDATA': 8,
+ 'UNSAFE': 16,
+ 'FOLDABLE': 32,
+ 'SCRIPT': 64,
+ 'STYLE': 128,
+ 'VIRTUALIZED': 256
+};
+html4.ELEMENTS = {
+ 'a': 0,
+ 'abbr': 0,
+ 'acronym': 0,
+ 'address': 0,
+ 'applet': 272,
+ 'area': 2,
+ 'article': 0,
+ 'aside': 0,
+ 'audio': 0,
+ 'b': 0,
+ 'base': 274,
+ 'basefont': 274,
+ 'bdi': 0,
+ 'bdo': 0,
+ 'big': 0,
+ 'blockquote': 0,
+ 'body': 305,
+ 'br': 2,
+ 'button': 0,
+ 'canvas': 0,
+ 'caption': 0,
+ 'center': 0,
+ 'cite': 0,
+ 'code': 0,
+ 'col': 2,
+ 'colgroup': 1,
+ 'command': 2,
+ 'data': 0,
+ 'datalist': 0,
+ 'dd': 1,
+ 'del': 0,
+ 'details': 0,
+ 'dfn': 0,
+ 'dialog': 272,
+ 'dir': 0,
+ 'div': 0,
+ 'dl': 0,
+ 'dt': 1,
+ 'em': 0,
+ 'fieldset': 0,
+ 'figcaption': 0,
+ 'figure': 0,
+ 'font': 0,
+ 'footer': 0,
+ 'form': 0,
+ 'frame': 274,
+ 'frameset': 272,
+ 'h1': 0,
+ 'h2': 0,
+ 'h3': 0,
+ 'h4': 0,
+ 'h5': 0,
+ 'h6': 0,
+ 'head': 305,
+ 'header': 0,
+ 'hgroup': 0,
+ 'hr': 2,
+ 'html': 305,
+ 'i': 0,
+ 'iframe': 4,
+ 'img': 2,
+ 'input': 2,
+ 'ins': 0,
+ 'isindex': 274,
+ 'kbd': 0,
+ 'keygen': 274,
+ 'label': 0,
+ 'legend': 0,
+ 'li': 1,
+ 'link': 274,
+ 'map': 0,
+ 'mark': 0,
+ 'menu': 0,
+ 'meta': 274,
+ 'meter': 0,
+ 'nav': 0,
+ 'nobr': 0,
+ 'noembed': 276,
+ 'noframes': 276,
+ 'noscript': 276,
+ 'object': 272,
+ 'ol': 0,
+ 'optgroup': 0,
+ 'option': 1,
+ 'output': 0,
+ 'p': 1,
+ 'param': 274,
+ 'pre': 0,
+ 'progress': 0,
+ 'q': 0,
+ 's': 0,
+ 'samp': 0,
+ 'script': 84,
+ 'section': 0,
+ 'select': 0,
+ 'small': 0,
+ 'source': 2,
+ 'span': 0,
+ 'strike': 0,
+ 'strong': 0,
+ 'style': 148,
+ 'sub': 0,
+ 'summary': 0,
+ 'sup': 0,
+ 'table': 0,
+ 'tbody': 1,
+ 'td': 1,
+ 'textarea': 8,
+ 'tfoot': 1,
+ 'th': 1,
+ 'thead': 1,
+ 'time': 0,
+ 'title': 280,
+ 'tr': 1,
+ 'track': 2,
+ 'tt': 0,
+ 'u': 0,
+ 'ul': 0,
+ 'var': 0,
+ 'video': 0,
+ 'wbr': 2
+};
+html4.ELEMENT_DOM_INTERFACES = {
+ 'a': 'HTMLAnchorElement',
+ 'abbr': 'HTMLElement',
+ 'acronym': 'HTMLElement',
+ 'address': 'HTMLElement',
+ 'applet': 'HTMLAppletElement',
+ 'area': 'HTMLAreaElement',
+ 'article': 'HTMLElement',
+ 'aside': 'HTMLElement',
+ 'audio': 'HTMLAudioElement',
+ 'b': 'HTMLElement',
+ 'base': 'HTMLBaseElement',
+ 'basefont': 'HTMLBaseFontElement',
+ 'bdi': 'HTMLElement',
+ 'bdo': 'HTMLElement',
+ 'big': 'HTMLElement',
+ 'blockquote': 'HTMLQuoteElement',
+ 'body': 'HTMLBodyElement',
+ 'br': 'HTMLBRElement',
+ 'button': 'HTMLButtonElement',
+ 'canvas': 'HTMLCanvasElement',
+ 'caption': 'HTMLTableCaptionElement',
+ 'center': 'HTMLElement',
+ 'cite': 'HTMLElement',
+ 'code': 'HTMLElement',
+ 'col': 'HTMLTableColElement',
+ 'colgroup': 'HTMLTableColElement',
+ 'command': 'HTMLCommandElement',
+ 'data': 'HTMLElement',
+ 'datalist': 'HTMLDataListElement',
+ 'dd': 'HTMLElement',
+ 'del': 'HTMLModElement',
+ 'details': 'HTMLDetailsElement',
+ 'dfn': 'HTMLElement',
+ 'dialog': 'HTMLDialogElement',
+ 'dir': 'HTMLDirectoryElement',
+ 'div': 'HTMLDivElement',
+ 'dl': 'HTMLDListElement',
+ 'dt': 'HTMLElement',
+ 'em': 'HTMLElement',
+ 'fieldset': 'HTMLFieldSetElement',
+ 'figcaption': 'HTMLElement',
+ 'figure': 'HTMLElement',
+ 'font': 'HTMLFontElement',
+ 'footer': 'HTMLElement',
+ 'form': 'HTMLFormElement',
+ 'frame': 'HTMLFrameElement',
+ 'frameset': 'HTMLFrameSetElement',
+ 'h1': 'HTMLHeadingElement',
+ 'h2': 'HTMLHeadingElement',
+ 'h3': 'HTMLHeadingElement',
+ 'h4': 'HTMLHeadingElement',
+ 'h5': 'HTMLHeadingElement',
+ 'h6': 'HTMLHeadingElement',
+ 'head': 'HTMLHeadElement',
+ 'header': 'HTMLElement',
+ 'hgroup': 'HTMLElement',
+ 'hr': 'HTMLHRElement',
+ 'html': 'HTMLHtmlElement',
+ 'i': 'HTMLElement',
+ 'iframe': 'HTMLIFrameElement',
+ 'img': 'HTMLImageElement',
+ 'input': 'HTMLInputElement',
+ 'ins': 'HTMLModElement',
+ 'isindex': 'HTMLUnknownElement',
+ 'kbd': 'HTMLElement',
+ 'keygen': 'HTMLKeygenElement',
+ 'label': 'HTMLLabelElement',
+ 'legend': 'HTMLLegendElement',
+ 'li': 'HTMLLIElement',
+ 'link': 'HTMLLinkElement',
+ 'map': 'HTMLMapElement',
+ 'mark': 'HTMLElement',
+ 'menu': 'HTMLMenuElement',
+ 'meta': 'HTMLMetaElement',
+ 'meter': 'HTMLMeterElement',
+ 'nav': 'HTMLElement',
+ 'nobr': 'HTMLElement',
+ 'noembed': 'HTMLElement',
+ 'noframes': 'HTMLElement',
+ 'noscript': 'HTMLElement',
+ 'object': 'HTMLObjectElement',
+ 'ol': 'HTMLOListElement',
+ 'optgroup': 'HTMLOptGroupElement',
+ 'option': 'HTMLOptionElement',
+ 'output': 'HTMLOutputElement',
+ 'p': 'HTMLParagraphElement',
+ 'param': 'HTMLParamElement',
+ 'pre': 'HTMLPreElement',
+ 'progress': 'HTMLProgressElement',
+ 'q': 'HTMLQuoteElement',
+ 's': 'HTMLElement',
+ 'samp': 'HTMLElement',
+ 'script': 'HTMLScriptElement',
+ 'section': 'HTMLElement',
+ 'select': 'HTMLSelectElement',
+ 'small': 'HTMLElement',
+ 'source': 'HTMLSourceElement',
+ 'span': 'HTMLSpanElement',
+ 'strike': 'HTMLElement',
+ 'strong': 'HTMLElement',
+ 'style': 'HTMLStyleElement',
+ 'sub': 'HTMLElement',
+ 'summary': 'HTMLElement',
+ 'sup': 'HTMLElement',
+ 'table': 'HTMLTableElement',
+ 'tbody': 'HTMLTableSectionElement',
+ 'td': 'HTMLTableDataCellElement',
+ 'textarea': 'HTMLTextAreaElement',
+ 'tfoot': 'HTMLTableSectionElement',
+ 'th': 'HTMLTableHeaderCellElement',
+ 'thead': 'HTMLTableSectionElement',
+ 'time': 'HTMLTimeElement',
+ 'title': 'HTMLTitleElement',
+ 'tr': 'HTMLTableRowElement',
+ 'track': 'HTMLTrackElement',
+ 'tt': 'HTMLElement',
+ 'u': 'HTMLElement',
+ 'ul': 'HTMLUListElement',
+ 'var': 'HTMLElement',
+ 'video': 'HTMLVideoElement',
+ 'wbr': 'HTMLElement'
+};
+html4.ueffects = {
+ 'NOT_LOADED': 0,
+ 'SAME_DOCUMENT': 1,
+ 'NEW_DOCUMENT': 2
+};
+html4.URIEFFECTS = {
+ 'a::href': 2,
+ 'area::href': 2,
+ 'blockquote::cite': 0,
+ 'command::icon': 1,
+ 'del::cite': 0,
+ 'form::action': 2,
+ 'img::src': 1,
+ 'input::src': 1,
+ 'ins::cite': 0,
+ 'q::cite': 0,
+ 'video::poster': 1
+};
+html4.ltypes = {
+ 'UNSANDBOXED': 2,
+ 'SANDBOXED': 1,
+ 'DATA': 0
+};
+html4.LOADERTYPES = {
+ 'a::href': 2,
+ 'area::href': 2,
+ 'blockquote::cite': 2,
+ 'command::icon': 1,
+ 'del::cite': 2,
+ 'form::action': 2,
+ 'img::src': 1,
+ 'input::src': 1,
+ 'ins::cite': 2,
+ 'q::cite': 2,
+ 'video::poster': 1
+};
+// Copyright (C) 2006 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview
+ * An HTML sanitizer that can satisfy a variety of security policies.
+ *
+ *