["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "clipPath", "defs", "desc", "discard", "ellipse", "feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDistantLight", "feDropShadow", "feFlood", "feFuncA", "feFuncB", "feFuncG", "feFuncR", "feGaussianBlur", "feImage", "feMerge", "feMergeNode", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence", "filter", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "mask", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"], self::HTML_NAMESPACE => ["a", "abbr", "acronym", "address", "applet", "area", "article", "aside", "audio", "b", "base", "basefont", "bdi", "bdo", "bgsound", "big", "blink", "blockquote", "body", "br", "button", "canvas", "caption", "center", "cite", "code", "col", "colgroup", "data", "datalist", "dd", "del", "details", "dfn", "dialog", "dir", "div", "dl", "dt", "em", "embed", "fieldset", "figcaption", "figure", "font", "footer", "form", "frame", "frameset", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "i", "iframe", "img", "input", "ins", "isindex", "kbd", "keygen", "label", "legend", "li", "link", "listing", "main", "map", "mark", "marquee", "menu", "menuitem", "meta", "meter", "multicol", "nav", "nextid", "nobr", "noembed", "noframes", "noscript", "object", "ol", "optgroup", "option", "output", "p", "param", "picture", "plaintext", "pre", "progress", "q", "rb", "rp", "rt", "rtc", "ruby", "s", "samp", "script", "search", "section", "select", "slot", "small", "source", "spacer", "span", "strike", "strong", "style", "sub", "summary", "sup", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "title", "tr", "track", "tt", "u", "ul", "var", "video", "wbr", "xmp"]]; /** @var array The set of known attributes, used to determine what the `allowUnknownMarkup` setting applies to */ protected const KNOWN_ATTRIBUTES = [self::NULL_NAMESPACE => ['abbr' => [self::HTML_NAMESPACE => ["td", "th"]], 'accept' => [self::HTML_NAMESPACE => ["form", "input"]], 'accept-charset' => [self::HTML_NAMESPACE => ["form"]], 'accesskey' => [self::HTML_NAMESPACE => ["*"]], 'accumulate' => [self::SVG_NAMESPACE => ["animate", "animateMotion", "animateTransform"]], 'action' => [self::HTML_NAMESPACE => ["button", "form"]], 'additive' => [self::SVG_NAMESPACE => ["animate", "animateMotion", "animateTransform"]], 'align' => [self::HTML_NAMESPACE => ["caption", "col", "div", "embed", "h1", "h2", "h3", "h4", "h5", "h6", "hr", "iframe", "img", "input", "legend", "object", "p", "table", "tbody", "td", "th", "tr"]], 'alignment-baseline' => [self::SVG_NAMESPACE => ["*"]], 'alink' => [self::HTML_NAMESPACE => ["body"]], 'allow' => [self::HTML_NAMESPACE => ["iframe"]], 'allowfullscreen' => [self::HTML_NAMESPACE => ["iframe"]], 'allowtransparency' => [self::HTML_NAMESPACE => ["iframe"]], 'alt' => [self::HTML_NAMESPACE => ["area", "img", "input"]], 'amplitude' => [self::SVG_NAMESPACE => ["feFuncA", "feFuncB", "feFuncG", "feFuncR"]], 'archive' => [self::HTML_NAMESPACE => ["object"]], 'aria-activedescendant' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-atomic' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-autocomplete' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-busy' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-checked' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-colcount' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-colindex' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-colspan' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-controls' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-current' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-describedby' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-details' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-disabled' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-dropeffect' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-errormessage' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-expanded' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-flowto' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-grabbed' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-haspopup' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-hidden' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-invalid' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-keyshortcuts' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-label' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-labelledby' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-level' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-live' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-modal' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-multiline' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-multiselectable' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-orientation' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-owns' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-placeholder' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-posinset' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-pressed' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-readonly' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-relevant' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-required' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-roledescription' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-rowcount' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-rowindex' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-rowspan' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-selected' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-setsize' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-sort' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-valuemax' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-valuemin' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-valuenow' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'aria-valuetext' => [self::HTML_NAMESPACE => ["*"], self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"]], 'as' => [self::HTML_NAMESPACE => ["link"]], 'async' => [self::HTML_NAMESPACE => ["script"]], 'attributeName' => [self::SVG_NAMESPACE => ["animate", "animateTransform", "set"]], 'autocapitalize' => [self::HTML_NAMESPACE => ["*"]], 'autocomplete' => [self::HTML_NAMESPACE => ["button", "fieldset", "form", "input", "object", "output", "select", "textarea"]], 'autofocus' => [self::HTML_NAMESPACE => ["*"]], 'autoplay' => [self::HTML_NAMESPACE => ["audio", "video"]], 'axis' => [self::HTML_NAMESPACE => ["td", "th"]], 'azimuth' => [self::SVG_NAMESPACE => ["feDistantLight"]], 'background' => [self::HTML_NAMESPACE => ["body", "table", "tbody", "td", "tfoot", "th", "thead", "tr"]], 'baseFrequency' => [self::SVG_NAMESPACE => ["feTurbulence"]], 'baseline-shift' => [self::SVG_NAMESPACE => ["*"]], 'begin' => [self::SVG_NAMESPACE => ["animate", "animateMotion", "animateTransform", "discard", "set"]], 'behavior' => [self::HTML_NAMESPACE => ["marquee"]], 'bgcolor' => [self::HTML_NAMESPACE => ["body", "table", "td", "th", "tr"]], 'bias' => [self::SVG_NAMESPACE => ["feConvolveMatrix"]], 'blocking' => [self::HTML_NAMESPACE => ["link", "script", "style"]], 'border' => [self::HTML_NAMESPACE => ["img", "input", "object", "table"]], 'bordercolor' => [self::HTML_NAMESPACE => ["table"]], 'bottommargin' => [self::HTML_NAMESPACE => ["body"]], 'by' => [self::SVG_NAMESPACE => ["animate", "animateMotion", "animateTransform"]], 'calcMode' => [self::SVG_NAMESPACE => ["animate", "animateMotion", "animateTransform"]], 'cellpadding' => [self::HTML_NAMESPACE => ["table"]], 'cellspacing' => [self::HTML_NAMESPACE => ["table"]], 'char' => [self::HTML_NAMESPACE => ["col", "tbody", "td", "th", "tr"]], 'charoff' => [self::HTML_NAMESPACE => ["col", "tbody", "td", "th", "tr"]], 'charset' => [self::HTML_NAMESPACE => ["a", "link", "meta", "script"]], 'checked' => [self::HTML_NAMESPACE => ["input"]], 'cite' => [self::HTML_NAMESPACE => ["blockquote", "del", "ins", "q"]], 'class' => [self::HTML_NAMESPACE => ["*"]], 'classid' => [self::HTML_NAMESPACE => ["object"]], 'clear' => [self::HTML_NAMESPACE => ["br"]], 'clip-path' => [self::SVG_NAMESPACE => ["*"]], 'clip-rule' => [self::SVG_NAMESPACE => ["*"]], 'clipPathUnits' => [self::SVG_NAMESPACE => ["clipPath"]], 'code' => [self::HTML_NAMESPACE => ["object"]], 'codebase' => [self::HTML_NAMESPACE => ["object"]], 'codetype' => [self::HTML_NAMESPACE => ["object"]], 'color' => [self::SVG_NAMESPACE => ["*"], self::HTML_NAMESPACE => ["hr", "link"]], 'color-interpolation' => [self::SVG_NAMESPACE => ["*"]], 'color-interpolation-filters' => [self::SVG_NAMESPACE => ["*"]], 'color-rendering' => [self::SVG_NAMESPACE => ["*"]], 'cols' => [self::HTML_NAMESPACE => ["textarea"]], 'colspan' => [self::HTML_NAMESPACE => ["td", "th"]], 'compact' => [self::HTML_NAMESPACE => ["dl", "menu", "ol", "ul"]], 'content' => [self::HTML_NAMESPACE => ["meta"]], 'contenteditable' => [self::HTML_NAMESPACE => ["*"]], 'contextmenu' => [self::HTML_NAMESPACE => ["*"]], 'controls' => [self::HTML_NAMESPACE => ["audio", "video"]], 'coords' => [self::HTML_NAMESPACE => ["a", "area"]], 'crossorigin' => [self::SVG_NAMESPACE => ["feImage", "image", "script"], self::HTML_NAMESPACE => ["audio", "img", "link", "script", "video"]], 'cursor' => [self::SVG_NAMESPACE => ["*"]], 'cx' => [self::SVG_NAMESPACE => ["circle", "ellipse", "radialGradient"]], 'cy' => [self::SVG_NAMESPACE => ["circle", "ellipse", "radialGradient"]], 'd' => [self::SVG_NAMESPACE => ["path"]], 'data' => [self::HTML_NAMESPACE => ["object"]], 'datafld' => [self::HTML_NAMESPACE => ["a", "button", "div", "fieldset", "frame", "iframe", "img", "input", "label", "legend", "marquee", "object", "select", "span", "textarea"]], 'dataformatas' => [self::HTML_NAMESPACE => ["button", "div", "input", "label", "legend", "marquee", "object", "option", "select", "span", "table"]], 'datapagesize' => [self::HTML_NAMESPACE => ["table"]], 'datasrc' => [self::HTML_NAMESPACE => ["a", "button", "div", "frame", "iframe", "img", "input", "label", "legend", "marquee", "object", "option", "select", "span", "table", "textarea"]], 'datetime' => [self::HTML_NAMESPACE => ["del", "ins", "time"]], 'declare' => [self::HTML_NAMESPACE => ["object"]], 'decoding' => [self::HTML_NAMESPACE => ["img"]], 'default' => [self::HTML_NAMESPACE => ["track"]], 'defer' => [self::HTML_NAMESPACE => ["script"]], 'diffuseConstant' => [self::SVG_NAMESPACE => ["feDiffuseLighting"]], 'dir' => [self::HTML_NAMESPACE => ["*"]], 'direction' => [self::SVG_NAMESPACE => ["*"], self::HTML_NAMESPACE => ["marquee"]], 'dirname' => [self::HTML_NAMESPACE => ["button", "fieldset", "input", "object", "output", "select", "textarea"]], 'disabled' => [self::HTML_NAMESPACE => ["button", "fieldset", "fieldset", "input", "link", "object", "optgroup", "option", "output", "select", "textarea"]], 'display' => [self::SVG_NAMESPACE => ["*"]], 'divisor' => [self::SVG_NAMESPACE => ["feConvolveMatrix"]], 'dominant-baseline' => [self::SVG_NAMESPACE => ["*"]], 'download' => [self::SVG_NAMESPACE => ["a"], self::HTML_NAMESPACE => ["a", "area"]], 'draggable' => [self::HTML_NAMESPACE => ["*"]], 'dropzone' => [self::HTML_NAMESPACE => ["*"]], 'dur' => [self::SVG_NAMESPACE => ["animate", "animateMotion", "animateTransform", "set"]], 'dx' => [self::SVG_NAMESPACE => ["feDropShadow", "feOffset", "text", "tspan"]], 'dy' => [self::SVG_NAMESPACE => ["feDropShadow", "feOffset", "text", "tspan"]], 'edgeMode' => [self::SVG_NAMESPACE => ["feGaussianBlur"]], 'elevation' => [self::SVG_NAMESPACE => ["feDistantLight"]], 'enctype' => [self::HTML_NAMESPACE => ["button", "form"]], 'end' => [self::SVG_NAMESPACE => ["animate", "animateMotion", "animateTransform", "set"]], 'enterkeyhint' => [self::HTML_NAMESPACE => ["*"]], 'event' => [self::HTML_NAMESPACE => ["script"]], 'exponent' => [self::SVG_NAMESPACE => ["feFuncA", "feFuncB", "feFuncG", "feFuncR"]], 'fetchpriority' => [self::HTML_NAMESPACE => ["img", "link", "script"]], 'fill' => [self::SVG_NAMESPACE => ["*"]], 'fill-opacity' => [self::SVG_NAMESPACE => ["*"]], 'fill-rule' => [self::SVG_NAMESPACE => ["*"]], 'filter' => [self::SVG_NAMESPACE => ["*"]], 'filterUnits' => [self::SVG_NAMESPACE => ["filter"]], 'flood-color' => [self::SVG_NAMESPACE => ["*"]], 'flood-opacity' => [self::SVG_NAMESPACE => ["*"]], 'font-family' => [self::SVG_NAMESPACE => ["*"]], 'font-size' => [self::SVG_NAMESPACE => ["*"]], 'font-size-adjust' => [self::SVG_NAMESPACE => ["*"]], 'font-stretch' => [self::SVG_NAMESPACE => ["*"]], 'font-style' => [self::SVG_NAMESPACE => ["*"]], 'font-variant' => [self::SVG_NAMESPACE => ["*"]], 'font-weight' => [self::SVG_NAMESPACE => ["*"]], 'for' => [self::HTML_NAMESPACE => ["label", "output", "script"]], 'form' => [self::HTML_NAMESPACE => ["button", "fieldset", "input", "object", "output", "select", "textarea"]], 'formaction' => [self::HTML_NAMESPACE => ["button", "form"]], 'formenctype' => [self::HTML_NAMESPACE => ["button", "form"]], 'formmethod' => [self::HTML_NAMESPACE => ["button", "form"]], 'formnovalidate' => [self::HTML_NAMESPACE => ["button", "form"]], 'formtarget' => [self::HTML_NAMESPACE => ["button", "form"]], 'fr' => [self::SVG_NAMESPACE => ["radialGradient"]], 'frame' => [self::HTML_NAMESPACE => ["table"]], 'frameborder' => [self::HTML_NAMESPACE => ["iframe"]], 'framespacing' => [self::HTML_NAMESPACE => ["iframe"]], 'from' => [self::SVG_NAMESPACE => ["animate", "animateMotion", "animateTransform"]], 'fx' => [self::SVG_NAMESPACE => ["radialGradient"]], 'fy' => [self::SVG_NAMESPACE => ["radialGradient"]], 'glyph-orientation-horizontal' => [self::SVG_NAMESPACE => ["*"]], 'glyph-orientation-vertical' => [self::SVG_NAMESPACE => ["*"]], 'gradientTransform' => [self::SVG_NAMESPACE => ["linearGradient", "radialGradient"]], 'gradientUnits' => [self::SVG_NAMESPACE => ["linearGradient", "radialGradient"]], 'headers' => [self::HTML_NAMESPACE => ["td", "th"]], 'height' => [self::SVG_NAMESPACE => ["feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDropShadow", "feFlood", "feGaussianBlur", "feImage", "feMerge", "feMorphology", "feOffset", "feSpecularLighting", "feTile", "feTurbulence", "filter", "foreignObject", "image", "mask", "pattern", "rect", "svg", "symbol", "use"], self::HTML_NAMESPACE => ["canvas", "embed", "iframe", "img", "object", "source", "table", "tbody", "td", "th", "tr", "video"]], 'hidden' => [self::HTML_NAMESPACE => ["*"]], 'high' => [self::HTML_NAMESPACE => ["meter"]], 'href' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "discard", "feImage", "image", "linearGradient", "mpath", "pattern", "radialGradient", "script", "set", "textPath", "use"], self::HTML_NAMESPACE => ["a", "area", "base", "link"]], 'hreflang' => [self::SVG_NAMESPACE => ["a"], self::HTML_NAMESPACE => ["a", "area", "area", "link"]], 'hspace' => [self::HTML_NAMESPACE => ["embed", "iframe", "img", "input", "object"]], 'http-equiv' => [self::HTML_NAMESPACE => ["meta"]], 'id' => [self::HTML_NAMESPACE => ["*"]], 'image-rendering' => [self::SVG_NAMESPACE => ["*"]], 'imagesizes' => [self::HTML_NAMESPACE => ["link"]], 'imagesrcset' => [self::HTML_NAMESPACE => ["link"]], 'in' => [self::SVG_NAMESPACE => ["feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDropShadow", "feGaussianBlur", "feMergeNode", "feMorphology", "feOffset", "feSpecularLighting", "feTile"]], 'in2' => [self::SVG_NAMESPACE => ["feBlend", "feComposite", "feDisplacementMap"]], 'inputmode' => [self::HTML_NAMESPACE => ["*"]], 'integrity' => [self::HTML_NAMESPACE => ["link", "script"]], 'intercept' => [self::SVG_NAMESPACE => ["feFuncA", "feFuncB", "feFuncG", "feFuncR"]], 'is' => [self::HTML_NAMESPACE => ["*"]], 'ismap' => [self::HTML_NAMESPACE => ["img", "input"]], 'itemid' => [self::HTML_NAMESPACE => ["*"]], 'itemprop' => [self::HTML_NAMESPACE => ["*"]], 'itemref' => [self::HTML_NAMESPACE => ["*"]], 'itemscope' => [self::HTML_NAMESPACE => ["*"]], 'itemtype' => [self::HTML_NAMESPACE => ["*"]], 'k1' => [self::SVG_NAMESPACE => ["feComposite"]], 'k2' => [self::SVG_NAMESPACE => ["feComposite"]], 'k3' => [self::SVG_NAMESPACE => ["feComposite"]], 'k4' => [self::SVG_NAMESPACE => ["feComposite"]], 'kernelMatrix' => [self::SVG_NAMESPACE => ["feConvolveMatrix", "feConvolveMatrix", "feDiffuseLighting", "feSpecularLighting"]], 'keyPoints' => [self::SVG_NAMESPACE => ["animateMotion"]], 'keySplines' => [self::SVG_NAMESPACE => ["animate", "animateMotion", "animateTransform"]], 'keyTimes' => [self::SVG_NAMESPACE => ["animate", "animateMotion", "animateTransform"]], 'kind' => [self::HTML_NAMESPACE => ["track"]], 'label' => [self::HTML_NAMESPACE => ["menu", "optgroup", "option", "track"]], 'lang' => [self::HTML_NAMESPACE => ["*"]], 'language' => [self::HTML_NAMESPACE => ["script"]], 'leftmargin' => [self::HTML_NAMESPACE => ["body"]], 'lengthAdjust' => [self::SVG_NAMESPACE => ["text", "textPath", "tspan"]], 'letter-spacing' => [self::SVG_NAMESPACE => ["*"]], 'lighting-color' => [self::SVG_NAMESPACE => ["*"]], 'limitingConeAngle' => [self::SVG_NAMESPACE => ["feSpotLight"]], 'link' => [self::HTML_NAMESPACE => ["body"]], 'list' => [self::HTML_NAMESPACE => ["input"]], 'loading' => [self::HTML_NAMESPACE => ["iframe", "img"]], 'longdesc' => [self::HTML_NAMESPACE => ["iframe", "img"]], 'loop' => [self::HTML_NAMESPACE => ["audio", "marquee", "video"]], 'low' => [self::HTML_NAMESPACE => ["meter"]], 'lowsrc' => [self::HTML_NAMESPACE => ["img"]], 'manifest' => [self::HTML_NAMESPACE => ["html"]], 'marginheight' => [self::HTML_NAMESPACE => ["body", "iframe"]], 'marginwidth' => [self::HTML_NAMESPACE => ["body", "iframe"]], 'marker-end' => [self::SVG_NAMESPACE => ["*"]], 'marker-mid' => [self::SVG_NAMESPACE => ["*"]], 'marker-start' => [self::SVG_NAMESPACE => ["*"]], 'markerHeight' => [self::SVG_NAMESPACE => ["marker"]], 'markerUnits' => [self::SVG_NAMESPACE => ["marker"]], 'markerWidth' => [self::SVG_NAMESPACE => ["marker"]], 'mask' => [self::SVG_NAMESPACE => ["*"]], 'maskContentUnits' => [self::SVG_NAMESPACE => ["mask"]], 'maskUnits' => [self::SVG_NAMESPACE => ["mask"]], 'max' => [self::SVG_NAMESPACE => ["animate", "animateMotion", "animateTransform", "set"], self::HTML_NAMESPACE => ["input", "meter", "progress"]], 'maxlength' => [self::HTML_NAMESPACE => ["input", "textarea"]], 'media' => [self::SVG_NAMESPACE => ["style"], self::HTML_NAMESPACE => ["link", "meta", "source", "style"]], 'method' => [self::SVG_NAMESPACE => ["textPath"], self::HTML_NAMESPACE => ["button", "form"]], 'methods' => [self::HTML_NAMESPACE => ["a", "link"]], 'min' => [self::SVG_NAMESPACE => ["animate", "animateMotion", "animateTransform", "set"], self::HTML_NAMESPACE => ["input", "meter"]], 'minlength' => [self::HTML_NAMESPACE => ["input", "textarea"]], 'mode' => [self::SVG_NAMESPACE => ["feBlend"]], 'multiple' => [self::HTML_NAMESPACE => ["input", "select"]], 'muted' => [self::HTML_NAMESPACE => ["audio", "video"]], 'name' => [self::HTML_NAMESPACE => ["a", "button", "embed", "fieldset", "form", "iframe", "img", "input", "map", "meta", "object", "option", "output", "select", "slot", "textarea"]], 'nohref' => [self::HTML_NAMESPACE => ["area"]], 'nomodule' => [self::HTML_NAMESPACE => ["script"]], 'nonce' => [self::HTML_NAMESPACE => ["*"]], 'noshade' => [self::HTML_NAMESPACE => ["hr"]], 'novalidate' => [self::HTML_NAMESPACE => ["button", "form"]], 'nowrap' => [self::HTML_NAMESPACE => ["td", "th"]], 'numOctaves' => [self::SVG_NAMESPACE => ["feTurbulence"]], 'offset' => [self::SVG_NAMESPACE => ["feFuncA", "feFuncB", "feFuncG", "feFuncR", "stop"]], 'onabort' => [self::SVG_NAMESPACE => ["svg"]], 'onafterprint' => [self::SVG_NAMESPACE => ["*"]], 'onbeforeprint' => [self::SVG_NAMESPACE => ["*"]], 'onbegin' => [self::SVG_NAMESPACE => ["animate", "animateMotion", "animateTransform", "set"]], 'oncancel' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'oncanplay' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'oncanplaythrough' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onchange' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onclick' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onclose' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'oncopy' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'oncuechange' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'oncut' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'ondblclick' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'ondrag' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'ondragend' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'ondragenter' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'ondragexit' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'ondragleave' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'ondragover' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'ondragstart' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'ondrop' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'ondurationchange' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onemptied' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onend' => [self::SVG_NAMESPACE => ["animate", "animateMotion", "animateTransform", "set"]], 'onended' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onerror' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onfocus' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onfocusin' => [self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "defs", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video"]], 'onfocusout' => [self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "defs", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video"]], 'onhashchange' => [self::SVG_NAMESPACE => ["*"]], 'oninput' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'oninvalid' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onkeydown' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onkeypress' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onkeyup' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onload' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onloadeddata' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onloadedmetadata' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onloadstart' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onmessage' => [self::SVG_NAMESPACE => ["*"]], 'onmousedown' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onmouseenter' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onmouseleave' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onmousemove' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onmouseout' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onmouseover' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onmouseup' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onmousewheel' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onoffline' => [self::SVG_NAMESPACE => ["*"]], 'ononline' => [self::SVG_NAMESPACE => ["*"]], 'onpagehide' => [self::SVG_NAMESPACE => ["*"]], 'onpageshow' => [self::SVG_NAMESPACE => ["*"]], 'onpaste' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onpause' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onplay' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onplaying' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onpopstate' => [self::SVG_NAMESPACE => ["*"]], 'onprogress' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onratechange' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onrepeat' => [self::SVG_NAMESPACE => ["animate", "animateMotion", "animateTransform", "set"]], 'onreset' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onresize' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onscroll' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onseeked' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onseeking' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onselect' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onshow' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"], self::HTML_NAMESPACE => ["*"]], 'onstalled' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onstorage' => [self::SVG_NAMESPACE => ["*"]], 'onsubmit' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onsuspend' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'ontimeupdate' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'ontoggle' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onunload' => [self::SVG_NAMESPACE => ["*"]], 'onvolumechange' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'onwaiting' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "defs", "desc", "ellipse", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'opacity' => [self::SVG_NAMESPACE => ["*"]], 'open' => [self::HTML_NAMESPACE => ["details", "dialog"]], 'operator' => [self::SVG_NAMESPACE => ["feComposite", "feMorphology"]], 'optimum' => [self::HTML_NAMESPACE => ["meter"]], 'order' => [self::SVG_NAMESPACE => ["feConvolveMatrix"]], 'orient' => [self::SVG_NAMESPACE => ["marker"]], 'origin' => [self::SVG_NAMESPACE => ["animateMotion"]], 'overflow' => [self::SVG_NAMESPACE => ["*"]], 'paint-order' => [self::SVG_NAMESPACE => ["*"]], 'path' => [self::SVG_NAMESPACE => ["animateMotion", "textPath"]], 'pathLength' => [self::SVG_NAMESPACE => ["circle", "ellipse", "line", "path", "polygon", "polyline", "rect"]], 'pattern' => [self::HTML_NAMESPACE => ["input"]], 'patternContentUnits' => [self::SVG_NAMESPACE => ["pattern"]], 'patternTransform' => [self::SVG_NAMESPACE => ["pattern"]], 'patternUnits' => [self::SVG_NAMESPACE => ["pattern"]], 'ping' => [self::SVG_NAMESPACE => ["a"], self::HTML_NAMESPACE => ["a", "area"]], 'placeholder' => [self::HTML_NAMESPACE => ["input", "textarea"]], 'playbackorder' => [self::SVG_NAMESPACE => ["svg"]], 'playsinline' => [self::HTML_NAMESPACE => ["video"]], 'pointer-events' => [self::SVG_NAMESPACE => ["*"]], 'points' => [self::SVG_NAMESPACE => ["polygon", "polyline"]], 'pointsAtX' => [self::SVG_NAMESPACE => ["feSpotLight"]], 'pointsAtY' => [self::SVG_NAMESPACE => ["feSpotLight"]], 'pointsAtZ' => [self::SVG_NAMESPACE => ["feSpotLight"]], 'popover' => [self::HTML_NAMESPACE => ["*"]], 'popovertarget' => [self::HTML_NAMESPACE => ["*"]], 'popovertargetaction' => [self::HTML_NAMESPACE => ["*"]], 'poster' => [self::HTML_NAMESPACE => ["video"]], 'preload' => [self::HTML_NAMESPACE => ["audio", "video"]], 'preserveAlpha' => [self::SVG_NAMESPACE => ["feConvolveMatrix"]], 'preserveAspectRatio' => [self::SVG_NAMESPACE => ["canvas", "feImage", "image", "marker", "pattern", "svg", "symbol", "view"]], 'primitiveUnits' => [self::SVG_NAMESPACE => ["filter"]], 'profile' => [self::HTML_NAMESPACE => ["head"]], 'r' => [self::SVG_NAMESPACE => ["circle", "radialGradient"]], 'radius' => [self::SVG_NAMESPACE => ["feMorphology"]], 'readonly' => [self::HTML_NAMESPACE => ["form-associated custom elements", "input", "textarea"]], 'refX' => [self::SVG_NAMESPACE => ["marker", "symbol"]], 'refY' => [self::SVG_NAMESPACE => ["marker", "symbol"]], 'referrerpolicy' => [self::SVG_NAMESPACE => ["a"], self::HTML_NAMESPACE => ["a", "area", "iframe", "img", "link", "script"]], 'rel' => [self::SVG_NAMESPACE => ["a"], self::HTML_NAMESPACE => ["a", "area", "form", "link"]], 'repeatCount' => [self::SVG_NAMESPACE => ["animate", "animateMotion", "animateTransform", "set"]], 'repeatDur' => [self::SVG_NAMESPACE => ["animate", "animateMotion", "animateTransform", "set"]], 'required' => [self::HTML_NAMESPACE => ["input", "select", "textarea"]], 'requiredExtensions' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "clipPath", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "mask", "path", "polygon", "polyline", "rect", "set", "svg", "switch", "text", "textPath", "tspan", "unknown", "use", "video"]], 'restart' => [self::SVG_NAMESPACE => ["animate", "animateMotion", "animateTransform", "set"]], 'result' => [self::SVG_NAMESPACE => ["feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDropShadow", "feFlood", "feGaussianBlur", "feImage", "feMerge", "feMorphology", "feOffset", "feSpecularLighting", "feTile", "feTurbulence"]], 'rev' => [self::HTML_NAMESPACE => ["a", "link"]], 'reversed' => [self::HTML_NAMESPACE => ["ol"]], 'rightmargin' => [self::HTML_NAMESPACE => ["body"]], 'role' => [self::SVG_NAMESPACE => ["a", "audio", "canvas", "circle", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "path", "polygon", "polyline", "rect", "svg", "switch", "symbol", "text", "textPath", "tspan", "unknown", "use", "video", "view"], self::HTML_NAMESPACE => ["*"]], 'rotate' => [self::SVG_NAMESPACE => ["animateMotion", "text", "tspan"]], 'rows' => [self::HTML_NAMESPACE => ["textarea"]], 'rowspan' => [self::HTML_NAMESPACE => ["td", "th"]], 'rules' => [self::HTML_NAMESPACE => ["table"]], 'rx' => [self::SVG_NAMESPACE => ["ellipse", "rect"]], 'ry' => [self::SVG_NAMESPACE => ["ellipse", "rect"]], 'sandbox' => [self::HTML_NAMESPACE => ["iframe"]], 'scale' => [self::SVG_NAMESPACE => ["feDisplacementMap"]], 'scheme' => [self::HTML_NAMESPACE => ["meta"]], 'scope' => [self::HTML_NAMESPACE => ["td", "th"]], 'scrolling' => [self::HTML_NAMESPACE => ["iframe"]], 'seed' => [self::SVG_NAMESPACE => ["feTurbulence"]], 'selected' => [self::HTML_NAMESPACE => ["option"]], 'shape' => [self::HTML_NAMESPACE => ["a", "area"]], 'shape-rendering' => [self::SVG_NAMESPACE => ["*"]], 'side' => [self::SVG_NAMESPACE => ["textPath"]], 'size' => [self::HTML_NAMESPACE => ["hr", "input", "select"]], 'sizes' => [self::HTML_NAMESPACE => ["img", "link", "source"]], 'slope' => [self::SVG_NAMESPACE => ["feFuncA", "feFuncB", "feFuncG", "feFuncR"]], 'slot' => [self::HTML_NAMESPACE => ["*"]], 'spacing' => [self::SVG_NAMESPACE => ["textPath"]], 'span' => [self::HTML_NAMESPACE => ["col", "colgroup"]], 'specularConstant' => [self::SVG_NAMESPACE => ["feSpecularLighting"]], 'specularExponent' => [self::SVG_NAMESPACE => ["feSpecularLighting", "feSpotLight"]], 'spellcheck' => [self::HTML_NAMESPACE => ["*"]], 'spreadMethod' => [self::SVG_NAMESPACE => ["linearGradient", "radialGradient"]], 'src' => [self::HTML_NAMESPACE => ["audio", "embed", "iframe", "img", "input", "script", "source", "track", "video"]], 'srcdoc' => [self::HTML_NAMESPACE => ["iframe"]], 'srclang' => [self::HTML_NAMESPACE => ["track"]], 'srcset' => [self::HTML_NAMESPACE => ["img", "source"]], 'standby' => [self::HTML_NAMESPACE => ["object"]], 'start' => [self::HTML_NAMESPACE => ["ol"]], 'startOffset' => [self::SVG_NAMESPACE => ["textPath"]], 'stdDeviation' => [self::SVG_NAMESPACE => ["feDropShadow", "feGaussianBlur"]], 'step' => [self::HTML_NAMESPACE => ["input"]], 'stitchTiles' => [self::SVG_NAMESPACE => ["feTurbulence"]], 'stop-color' => [self::SVG_NAMESPACE => ["*"]], 'stop-opacity' => [self::SVG_NAMESPACE => ["*"]], 'stroke' => [self::SVG_NAMESPACE => ["*"]], 'stroke-dasharray' => [self::SVG_NAMESPACE => ["*"]], 'stroke-dashoffset' => [self::SVG_NAMESPACE => ["*"]], 'stroke-linecap' => [self::SVG_NAMESPACE => ["*"]], 'stroke-linejoin' => [self::SVG_NAMESPACE => ["*"]], 'stroke-miterlimit' => [self::SVG_NAMESPACE => ["*"]], 'stroke-opacity' => [self::SVG_NAMESPACE => ["*"]], 'stroke-width' => [self::SVG_NAMESPACE => ["*"]], 'style' => [self::HTML_NAMESPACE => ["*"]], 'summary' => [self::HTML_NAMESPACE => ["table"]], 'surfaceScale' => [self::SVG_NAMESPACE => ["feDiffuseLighting", "feSpecularLighting"]], 'systemLanguage' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "clipPath", "discard", "ellipse", "foreignObject", "g", "iframe", "image", "line", "mask", "path", "polygon", "polyline", "rect", "set", "svg", "switch", "text", "textPath", "tspan", "unknown", "use", "video"]], 'tabindex' => [self::HTML_NAMESPACE => ["*"]], 'tableValues' => [self::SVG_NAMESPACE => ["feFuncA", "feFuncB", "feFuncG", "feFuncR"]], 'target' => [self::SVG_NAMESPACE => ["a"], self::HTML_NAMESPACE => ["a", "area", "base", "button", "form", "link"]], 'targetX' => [self::SVG_NAMESPACE => ["feConvolveMatrix"]], 'targetY' => [self::SVG_NAMESPACE => ["feConvolveMatrix"]], 'text' => [self::HTML_NAMESPACE => ["body"]], 'text-anchor' => [self::SVG_NAMESPACE => ["*"]], 'text-decoration' => [self::SVG_NAMESPACE => ["*"]], 'text-overflow' => [self::SVG_NAMESPACE => ["*"]], 'text-rendering' => [self::SVG_NAMESPACE => ["*"]], 'textLength' => [self::SVG_NAMESPACE => ["text", "textPath", "tspan"]], 'timelinebegin' => [self::SVG_NAMESPACE => ["svg"]], 'title' => [self::HTML_NAMESPACE => ["*"]], 'to' => [self::SVG_NAMESPACE => ["animate", "animateMotion", "animateTransform", "set"]], 'topmargin' => [self::HTML_NAMESPACE => ["body"]], 'transform' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "clipPath", "defs", "desc", "discard", "ellipse", "feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDistantLight", "feDropShadow", "feFlood", "feFuncA", "feFuncB", "feFuncG", "feFuncR", "feGaussianBlur", "feImage", "feMerge", "feMergeNode", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence", "filter", "foreignObject", "g", "iframe", "image", "line", "marker", "mask", "metadata", "mpath", "path", "polygon", "polyline", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]], 'translate' => [self::HTML_NAMESPACE => ["*"]], 'truespeed' => [self::HTML_NAMESPACE => ["marquee"]], 'type' => [self::SVG_NAMESPACE => ["a", "animateTransform", "feColorMatrix", "feFuncA", "feFuncB", "feFuncG", "feFuncR", "feTurbulence", "script", "style"], self::HTML_NAMESPACE => ["a", "area", "area", "button", "embed", "input", "li", "link", "menu", "object", "ol", "script", "source", "style", "ul"]], 'typemustmatch' => [self::HTML_NAMESPACE => ["object"]], 'unicode-bidi' => [self::SVG_NAMESPACE => ["*"]], 'urn' => [self::HTML_NAMESPACE => ["a", "link"]], 'usemap' => [self::HTML_NAMESPACE => ["img", "input", "object"]], 'valign' => [self::HTML_NAMESPACE => ["col", "tbody", "td", "th", "tr"]], 'value' => [self::HTML_NAMESPACE => ["button", "data", "input", "li", "meter", "option", "progress"]], 'values' => [self::SVG_NAMESPACE => ["animate", "animateMotion", "animateTransform", "feColorMatrix"]], 'vector-effect' => [self::SVG_NAMESPACE => ["*"]], 'version' => [self::HTML_NAMESPACE => ["html"]], 'viewBox' => [self::SVG_NAMESPACE => ["marker", "pattern", "svg", "symbol", "view"]], 'visibility' => [self::SVG_NAMESPACE => ["*"]], 'vlink' => [self::HTML_NAMESPACE => ["body"]], 'vspace' => [self::HTML_NAMESPACE => ["embed", "iframe", "img", "input", "object"]], 'white-space' => [self::SVG_NAMESPACE => ["*"]], 'width' => [self::SVG_NAMESPACE => ["feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDropShadow", "feFlood", "feGaussianBlur", "feImage", "feMerge", "feMorphology", "feOffset", "feSpecularLighting", "feTile", "feTurbulence", "filter", "foreignObject", "image", "mask", "pattern", "rect", "svg", "symbol", "use"], self::HTML_NAMESPACE => ["canvas", "col", "embed", "hr", "iframe", "img", "object", "pre", "source", "table", "td", "th", "video"]], 'word-spacing' => [self::SVG_NAMESPACE => ["*"]], 'wrap' => [self::HTML_NAMESPACE => ["textarea"]], 'writing-mode' => [self::SVG_NAMESPACE => ["*"]], 'x' => [self::SVG_NAMESPACE => ["feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDropShadow", "feFlood", "feGaussianBlur", "feImage", "feMerge", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence", "filter", "foreignObject", "image", "mask", "pattern", "rect", "svg", "symbol", "text", "tspan", "use"]], 'x1' => [self::SVG_NAMESPACE => ["line", "linearGradient"]], 'x2' => [self::SVG_NAMESPACE => ["line", "linearGradient"]], 'xChannelSelector' => [self::SVG_NAMESPACE => ["feDisplacementMap"]], 'y' => [self::SVG_NAMESPACE => ["feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDropShadow", "feFlood", "feGaussianBlur", "feImage", "feMerge", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence", "filter", "foreignObject", "image", "mask", "pattern", "rect", "svg", "symbol", "text", "tspan", "use"]], 'y1' => [self::SVG_NAMESPACE => ["line", "linearGradient"]], 'y2' => [self::SVG_NAMESPACE => ["line", "linearGradient"]], 'yChannelSelector' => [self::SVG_NAMESPACE => ["feDisplacementMap"]], 'z' => [self::SVG_NAMESPACE => ["fePointLight", "feSpotLight"]], 'zoomAndPan' => [self::SVG_NAMESPACE => ["svg", "view"]]], self::XLINK_NAMESPACE => ['href' => [self::SVG_NAMESPACE => ["a", "image", "linearGradient", "pattern", "radialGradient", "script", "textPath", "use", "feImage"]], 'title' => [self::SVG_NAMESPACE => ["a", "image", "linearGradient", "pattern", "radialGradient", "script", "textPath", "use"]]], self::XML_NAMESPACE => ['space' => [self::SVG_NAMESPACE => ["a", "animate", "animateMotion", "animateTransform", "audio", "canvas", "circle", "clipPath", "defs", "desc", "discard", "ellipse", "feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDistantLight", "feDropShadow", "feFlood", "feFuncA", "feFuncB", "feFuncG", "feFuncR", "feGaussianBlur", "feImage", "feMerge", "feMergeNode", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence", "filter", "foreignObject", "g", "iframe", "image", "line", "linearGradient", "marker", "mask", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "script", "set", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tspan", "unknown", "use", "video", "view"]]]]; /** @var array The baseline list of allowed attributes */ protected const BASELINE_ATTR = [ self::HTML_NAMESPACE => [ 'abbr' => true, 'accept' => true, 'accept-charset' => true, 'accesskey' => true, 'action' => true, 'align' => true, 'alink' => true, 'allow' => true, 'allowfullscreen' => true, 'allowpaymentrequest' => true, 'alt' => true, 'anchor' => true, 'archive' => true, 'as' => true, 'async' => true, 'autocapitalize' => true, 'autocomplete' => true, 'autocorrect' => true, 'autofocus' => true, 'autopictureinpicture' => true, 'autoplay' => true, 'axis' => true, 'background' => true, 'behavior' => true, 'bgcolor' => true, 'border' => true, 'bordercolor' => true, 'capture' => true, 'cellpadding' => true, 'cellspacing' => true, 'challenge' => true, 'char' => true, 'charoff' => true, 'charset' => true, 'checked' => true, 'cite' => true, 'class' => true, 'classid' => true, 'clear' => true, 'code' => true, 'codebase' => true, 'codetype' => true, 'color' => true, 'cols' => true, 'colspan' => true, 'compact' => true, 'content' => true, 'contenteditable' => true, 'controls' => true, 'controlslist' => true, 'conversiondestination' => true, 'coords' => true, 'crossorigin' => true, 'csp' => true, 'data' => true, 'datetime' => true, 'declare' => true, 'decoding' => true, 'default' => true, 'defer' => true, 'dir' => true, 'direction' => true, 'dirname' => true, 'disabled' => true, 'disablepictureinpicture' => true, 'disableremoteplayback' => true, 'disallowdocumentaccess' => true, 'download' => true, 'draggable' => true, 'elementtiming' => true, 'enctype' => true, 'end' => true, 'enterkeyhint' => true, 'event' => true, 'exportparts' => true, 'face' => true, 'for' => true, 'form' => true, 'formaction' => true, 'formenctype' => true, 'formmethod' => true, 'formnovalidate' => true, 'formtarget' => true, 'frame' => true, 'frameborder' => true, 'headers' => true, 'height' => true, 'hidden' => true, 'high' => true, 'href' => true, 'hreflang' => true, 'hreftranslate' => true, 'hspace' => true, 'http-equiv' => true, 'id' => true, 'imagesizes' => true, 'imagesrcset' => true, 'importance' => true, 'impressiondata' => true, 'impressionexpiry' => true, 'incremental' => true, 'inert' => true, 'inputmode' => true, 'integrity' => true, 'invisible' => true, 'is' => true, 'ismap' => true, 'keytype' => true, 'kind' => true, 'label' => true, 'lang' => true, 'language' => true, 'latencyhint' => true, 'leftmargin' => true, 'link' => true, 'list' => true, 'loading' => true, 'longdesc' => true, 'loop' => true, 'low' => true, 'lowsrc' => true, 'manifest' => true, 'marginheight' => true, 'marginwidth' => true, 'max' => true, 'maxlength' => true, 'mayscript' => true, 'media' => true, 'method' => true, 'min' => true, 'minlength' => true, 'multiple' => true, 'muted' => true, 'name' => true, 'nohref' => true, 'nomodule' => true, 'nonce' => true, 'noresize' => true, 'noshade' => true, 'novalidate' => true, 'nowrap' => true, 'object' => true, 'open' => true, 'optimum' => true, 'part' => true, 'pattern' => true, 'ping' => true, 'placeholder' => true, 'playsinline' => true, 'policy' => true, 'poster' => true, 'preload' => true, 'pseudo' => true, 'readonly' => true, 'referrerpolicy' => true, 'rel' => true, 'reportingorigin' => true, 'required' => true, 'resources' => true, 'rev' => true, 'reversed' => true, 'role' => true, 'rows' => true, 'rowspan' => true, 'rules' => true, 'sandbox' => true, 'scheme' => true, 'scope' => true, 'scopes' => true, 'scrollamount' => true, 'scrolldelay' => true, 'scrolling' => true, 'select' => true, 'selected' => true, 'shadowroot' => true, 'shadowrootdelegatesfocus' => true, 'shape' => true, 'size' => true, 'sizes' => true, 'slot' => true, 'span' => true, 'spellcheck' => true, 'src' => true, 'srcdoc' => true, 'srclang' => true, 'srcset' => true, 'standby' => true, 'start' => true, 'step' => true, 'style' => true, 'summary' => true, 'tabindex' => true, 'target' => true, 'text' => true, 'title' => true, 'topmargin' => true, 'translate' => true, 'truespeed' => true, 'trusttoken' => true, 'type' => true, 'usemap' => true, 'valign' => true, 'value' => true, 'valuetype' => true, 'version' => true, 'virtualkeyboardpolicy' => true, 'vlink' => true, 'vspace' => true, 'webkitdirectory' => true, 'width' => true, 'wrap' => true, ], ]; /** @var array The default configuration structure */ protected const DEFAULT_CONF = [ 'allowElements' => [ self::HTML_NAMESPACE => [ 'a' => true, 'abbr' => true, 'acronym' => true, 'address' => true, 'area' => true, 'article' => true, 'aside' => true, 'audio' => true, 'b' => true, 'bdi' => true, 'bdo' => true, 'bgsound' => true, 'big' => true, 'blockquote' => true, 'body' => true, 'br' => true, 'button' => true, 'canvas' => true, 'caption' => true, 'center' => true, 'cite' => true, 'code' => true, 'col' => true, 'colgroup' => true, 'datalist' => true, 'dd' => true, 'del' => true, 'details' => true, 'dfn' => true, 'dialog' => true, 'dir' => true, 'div' => true, 'dl' => true, 'dt' => true, 'em' => true, 'fieldset' => true, 'figcaption' => true, 'figure' => true, 'font' => true, 'footer' => true, 'form' => true, 'h1' => true, 'h2' => true, 'h3' => true, 'h4' => true, 'h5' => true, 'h6' => true, 'head' => true, 'header' => true, 'hgroup' => true, 'hr' => true, 'html' => true, 'i' => true, 'img' => true, 'input' => true, 'ins' => true, 'kbd' => true, 'keygen' => true, 'label' => true, 'layer' => true, 'legend' => true, 'li' => true, 'link' => true, 'listing' => true, 'main' => true, 'map' => true, 'mark' => true, 'marquee' => true, 'menu' => true, 'meta' => true, 'meter' => true, 'nav' => true, 'nobr' => true, 'ol' => true, 'optgroup' => true, 'option' => true, 'output' => true, 'p' => true, 'picture' => true, 'popup' => true, 'pre' => true, 'progress' => true, 'q' => true, 'rb' => true, 'rp' => true, 'rt' => true, 'rtc' => true, 'ruby' => true, 's' => true, 'samp' => true, 'search' => true, 'section' => true, 'select' => true, 'selectmenu' => true, 'small' => true, 'source' => true, 'span' => true, 'strike' => true, 'strong' => true, 'style' => true, 'sub' => true, 'summary' => true, 'sup' => true, 'table' => true, 'tbody' => true, 'td' => true, 'tfoot' => true, 'th' => true, 'thead' => true, 'time' => true, 'tr' => true, 'track' => true, 'tt' => true, 'u' => true, 'ul' => true, 'var' => true, 'video' => true, 'wbr' => true, ] ], 'allowAttributes' => [ self::NULL_NAMESPACE => [ 'abbr' => "*", 'accept' => "*", 'accept-charset' => "*", 'accesskey' => "*", 'action' => "*", 'align' => "*", 'alink' => "*", 'allow' => "*", 'allowfullscreen' => "*", 'alt' => "*", 'anchor' => "*", 'archive' => "*", 'as' => "*", 'async' => "*", 'autocapitalize' => "*", 'autocomplete' => "*", 'autocorrect' => "*", 'autofocus' => "*", 'autopictureinpicture' => "*", 'autoplay' => "*", 'axis' => "*", 'background' => "*", 'behavior' => "*", 'bgcolor' => "*", 'border' => "*", 'bordercolor' => "*", 'capture' => "*", 'cellpadding' => "*", 'cellspacing' => "*", 'challenge' => "*", 'char' => "*", 'charoff' => "*", 'charset' => "*", 'checked' => "*", 'cite' => "*", 'class' => "*", 'classid' => "*", 'clear' => "*", 'code' => "*", 'codebase' => "*", 'codetype' => "*", 'color' => "*", 'cols' => "*", 'colspan' => "*", 'compact' => "*", 'content' => "*", 'contenteditable' => "*", 'controls' => "*", 'controlslist' => "*", 'conversiondestination' => "*", 'coords' => "*", 'crossorigin' => "*", 'csp' => "*", 'data' => "*", 'datetime' => "*", 'declare' => "*", 'decoding' => "*", 'default' => "*", 'defer' => "*", 'dir' => "*", 'direction' => "*", 'dirname' => "*", 'disabled' => "*", 'disablepictureinpicture' => "*", 'disableremoteplayback' => "*", 'disallowdocumentaccess' => "*", 'download' => "*", 'draggable' => "*", 'elementtiming' => "*", 'enctype' => "*", 'end' => "*", 'enterkeyhint' => "*", 'event' => "*", 'exportparts' => "*", 'face' => "*", 'for' => "*", 'form' => "*", 'formaction' => "*", 'formenctype' => "*", 'formmethod' => "*", 'formnovalidate' => "*", 'formtarget' => "*", 'frame' => "*", 'frameborder' => "*", 'headers' => "*", 'height' => "*", 'hidden' => "*", 'high' => "*", 'href' => "*", 'hreflang' => "*", 'hreftranslate' => "*", 'hspace' => "*", 'http-equiv' => "*", 'id' => "*", 'imagesizes' => "*", 'imagesrcset' => "*", 'importance' => "*", 'impressiondata' => "*", 'impressionexpiry' => "*", 'incremental' => "*", 'inert' => "*", 'inputmode' => "*", 'integrity' => "*", 'invisible' => "*", 'is' => "*", 'ismap' => "*", 'keytype' => "*", 'kind' => "*", 'label' => "*", 'lang' => "*", 'language' => "*", 'latencyhint' => "*", 'leftmargin' => "*", 'link' => "*", 'list' => "*", 'loading' => "*", 'longdesc' => "*", 'loop' => "*", 'low' => "*", 'lowsrc' => "*", 'manifest' => "*", 'marginheight' => "*", 'marginwidth' => "*", 'max' => "*", 'maxlength' => "*", 'mayscript' => "*", 'media' => "*", 'method' => "*", 'min' => "*", 'minlength' => "*", 'multiple' => "*", 'muted' => "*", 'name' => "*", 'nohref' => "*", 'nomodule' => "*", 'nonce' => "*", 'noresize' => "*", 'noshade' => "*", 'novalidate' => "*", 'nowrap' => "*", 'object' => "*", 'open' => "*", 'optimum' => "*", 'part' => "*", 'pattern' => "*", 'ping' => "*", 'placeholder' => "*", 'playsinline' => "*", 'policy' => "*", 'poster' => "*", 'preload' => "*", 'pseudo' => "*", 'readonly' => "*", 'referrerpolicy' => "*", 'rel' => "*", 'reportingorigin' => "*", 'required' => "*", 'resources' => "*", 'rev' => "*", 'reversed' => "*", 'role' => "*", 'rows' => "*", 'rowspan' => "*", 'rules' => "*", 'sandbox' => "*", 'scheme' => "*", 'scope' => "*", 'scopes' => "*", 'scrollamount' => "*", 'scrolldelay' => "*", 'scrolling' => "*", 'select' => "*", 'selected' => "*", 'shadowroot' => "*", 'shadowrootdelegatesfocus' => "*", 'shape' => "*", 'size' => "*", 'sizes' => "*", 'slot' => "*", 'span' => "*", 'spellcheck' => "*", 'src' => "*", 'srcdoc' => "*", 'srclang' => "*", 'srcset' => "*", 'standby' => "*", 'start' => "*", 'step' => "*", 'style' => "*", 'summary' => "*", 'tabindex' => "*", 'target' => "*", 'text' => "*", 'title' => "*", 'topmargin' => "*", 'translate' => "*", 'truespeed' => "*", 'trusttoken' => "*", 'type' => "*", 'usemap' => "*", 'valign' => "*", 'value' => "*", 'valuetype' => "*", 'version' => "*", 'virtualkeyboardpolicy' => "*", 'vlink' => "*", 'vspace' => "*", 'webkitdirectory' => "*", 'width' => "*", 'wrap' => "*", ], ], 'allowCustomElements' => false, 'allowUnknownMarkup' => false, 'allowComments' => false, 'allowProcessingInstructions' => false, 'nullNamespaceAsHtml' => true, ]; /** @var array The parsed configuration, as used for processing */ protected $config; /** Initializes a sanitizer with the provided configuration, or the default configuration if no configuration is provided * * The configuration array may contain any of the following keys: * * - `allowElements`: an indexed array of elements to retain in the tree. Elements not in this list will be treated as if they were included in the `blockElements` list * - `blockElements`: an indexed array of elements to remove from the tree while retaining their children * - `dropElements`: an indexed array of elements to remove from the tree along with their children * - `allowAttributes`: an indexed array of attributes to allow on certain elements. Attributes not in this list will be dropped * - `dropAttributes`: an indexed array of attributes to remove from certain elements * - `allowCustomElements`: Whether to allow custom elements, false by default. For the purposes of this implementation these are HTML elements with names containing dashed. If true, elements are still subject to the allow, block, and drop lists * - `allowUnknownMarkup`: Whether to allow non-standard elements which are not custom elements, false by default. If true, elements are still subject to the allow, block, and drop lists * - `allowComments`: Whether to retain comments, false by default * - `allowProcessingInstructions`: Whether to retain processing instructions, false by default. Processing instructions do not normally appear in HTML documents. This option is an extension to the specification * - `nullNamespaceAsHtml`: Whether to interpret elements from the tree in the null namespace as being in the HTML namespace, true by default. Per standard behaviour HTML elements have a namespace URI, but not all PHP-based parsers do this. This may be set to false when sanitizing XML documents. This option is an extension to the specification * * The entries in element lists may be strings, in which case these are interpreted as local names in the HTML namespace, or an array with the following keys: * * - `name`: The localName of the element * - `namespace`: The namespaceURI of the element, a string or null. If omitted the HTML namespace is assumed * * The entries in attribute lists are arrays with the following keys * * - `name`: The localName of the attribute * - `namespace`: The namespaceURI of the attribute. If omitted the null namespace is assumed * - `elements`: An indexed array of elements on which to allow the attribute, in the same format as other element lists. The string `"*"` may be supplied instead of an array to mean all elements * * @param array $config A configuration to use instead of the default one */ public function __construct(array $config = null) { if ($config === null) { // use the default configuration if none is specified $this->config = self::DEFAULT_CONF; } else { // otherwise validate the configuration; the specification provides // no clue is to what happens when the configuration is invalid, // so we'll just have to do our best $out = []; // start with the element lists foreach (["allowElements", "blockElements", "dropElements"] as $opt) { if (isset($config[$opt]) && is_array($config[$opt])) { foreach ($config[$opt] as $el) { if (is_string($el) && strlen($el)) { // strings are assumed to be in the HTML namespace $ns = self::HTML_NAMESPACE; $name = $el; } elseif (is_array($el) && strlen($el['name'] ?? "")) { $name = $el['name']; if (!array_key_exists("namespace", $el)) { // the namespace key being missing means the HTML namespace $ns = self::HTML_NAMESPACE; } elseif (!isset($el['namespace'])) { // the null namespace is also possible (but will never match in HTML documents) $ns = self::NULL_NAMESPACE; } elseif (is_string($el['namespace'])) { // only use the namespace if it's a string $ns = $el['namespace']; } else { // ignore any other value for the namespace (this is invalid) continue; } } // create any structures which might be missing if (!isset($out[$opt])) { $out[$opt] = []; } if (!isset($out[$opt][$ns])) { $out[$opt][$ns] = []; } // add the element $out[$opt][$ns][$name] = true; } } } // continue with attribute lists foreach (["allowAttributes", "dropAttributes"] as $opt) { if (isset($config[$opt]) && is_array($config[$opt])) { foreach ($config[$opt] as $attr) { if (is_array($attr) && strlen($attr['name'] ?? "" && isset($attr['elements']))) { $name = $attr['name']; if (!isset($attr['namespace'])) { // the null namespace is assumed $ns = self::NULL_NAMESPACE; } elseif (is_string($attr['namespace'])) { // only use the namespace if it's a string $ns = $attr['namespace']; } else { // ignore any other value for the namespace (this is invalid) continue; } // now check the list of elements if ($attr['elements'] === "*") { // the special string "*" means any element $list = "*"; } elseif (is_array($attr['elements'])) { // otherwise the element list is like the element lists handled above $list = []; foreach ($attr['elements'] as $el) { if (is_string($el) && strlen($el)) { // strings are assumed to be in the HTML namespace $eNs = self::HTML_NAMESPACE; $eName = $el; } elseif (is_array($el) && strlen($el['name'] ?? "")) { $eName = $el['name']; if (!array_key_exists("namespace", $el)) { // the namespace key being missing means the HTML namespace $eNs = self::HTML_NAMESPACE; } elseif (!isset($el['namespace'])) { // the null namespace is also possible (but will never match in HTML documents) $eNs = self::NULL_NAMESPACE; } elseif (is_string($el['namespace'])) { // only use the namespace if it's a string $eNs = $el['namespace']; } else { // ignore any other value for the namespace (this is invalid) continue; } } // create any structures which might be missing if (!isset($list[$eNs])) { $list[$eNs] = []; } // add the element $list[$eNs][$eName] = true; } } else { // ignore any other value for the elements list (this is invalid) continue; } if (!$list) { // an empty element list is non-functional, so we can skip the attribute continue; } // create any structures which might be missing if (!isset($out[$opt])) { $out[$opt] = []; } if (!isset($out[$opt][$ns])) { $out[$opt][$ns] = []; } // add the attribute $out[$opt][$ns][$name] = $list; } } } } // finally handle the boolean options foreach (["allowCustomElements", "allowUnknownMarkup", "allowComments", "allowProcessingInstructions", "nullNamespaceAsHtml"] as $opt) { if (isset($config[$opt])) { $out[$opt] = (bool) $config[$opt]; } } // use the normalized configuration $this->config = $out; } } /** Returns a normalized representation of the effective configuration */ public function getConfiguration(): array { return $this->exportConfiguration($this->config); } /** Returns the default configuration */ public function getDefaultConfiguration(): array { return $this->exportConfiguration(self::DEFAULT_CONF); } /** Converts a configuration from the internal representation to the external representation */ protected function exportConfiguration(array $config): array { $out = []; // start with the element lists foreach (["allowElements", "blockElements", "dropElements"] as $opt) { if (isset($config[$opt])) { $out[$opt] = []; ksort($config[$opt]); foreach ($config[$opt] as $ns => $set) { ksort($set); foreach ($set as $el => $t) { if ($ns === self::HTML_NAMESPACE) { $out[$opt][] = $el; } else { $out[$opt][] = ['name' => $el, 'namespace' => $ns]; } } } } } // continue with attribute lists foreach (["allowAttributes", "dropAttributes"] as $opt) { if (isset($config[$opt])) { $out[$opt] = []; ksort($config[$opt]); foreach ($config[$opt] as $ns => $set) { ksort($set); foreach ($set as $attr => $elems) { $list = []; ksort($elems); foreach ($elems as $eNs => $eSet) { ksort($eSet); foreach ($eSet as $el => $t) { if ($eNs === self::HTML_NAMESPACE) { $list[] = $el; } else { $list[] = ['name' => $el, 'namespace' => $eNs]; } } } if ($ns === self::NULL_NAMESPACE) { $out[$opt][] = ['name' => $attr, 'elements' => $list]; } else { $out[$opt][] = ['name' => $attr, 'namespace' => $ns, 'elements' => $list]; } } } } } // finally handle the boolean options foreach (["allowCustomElements", "allowUnknownMarkup", "allowComments", "allowProcessingInstructions", "nullNamespaceAsHtml"] as $opt) { if (isset($config[$opt])) { $out[$opt] = $config[$opt]; } } // return the transformed configuration return $out; } /** Sanitizes a document or document fragment according to the loaded configuration * * The returned document fragment contains clones of all valid nodes, leaving the original input untouched * * @param \DOMDocument|\DOMDocumentFragment $input The document or document fragment to sanitize */ public function sanitize(\DOMNode $input): \DOMDocumentFragment { if (!($input instanceof \DOMDocument || $input instanceof \DOMDocumentFragment)) { throw new \InvalidArgumentException("Argument \$input must be of type \DOMDocument|\DOMDocumentFragment"); } # To sanitize a given input of type Document or DocumentFragment # run these steps: # Let fragment be the result of running the create a document fragment # algorithm on input. $fragment = $this->createDocumentFragment($input); # Run the sanitize a document fragment algorithm on fragment. $this->sanitizeDocumentFragment($fragment); # Return fragment. return $fragment; } /** Creates a copy of the input as a document fragment, which can then be safely manipulated * * @param \DOMDocument|\DOMDocumentFragment $input The input to clone */ protected function createDocumentFragment(\DOMNode $input): \DOMDocumentFragment { assert($input instanceof \DOMDocument || $input instanceof \DOMDocumentFragment, new \Exception("Parameter \$input must be of type \DOMDocument|\DOMDocumentFragment")); # To create a document fragment named fragment from an input of type # Document or DocumentFragment, run these steps: # Let node be null. $node = null; # Switch based on input’s type: # If input is of type DocumentFragment, then: # Set node to input. # If input is of type Document, then: # Set node to input’s documentElement. if ($input instanceof \DOMDocumentFragment) { $node = $input; } elseif ($input instanceof \DOMDocument) { $node = $input->documentElement; } # Let clone be the result of running clone a node on node with the # clone children flag set. $clone = $node->cloneNode(true); # Let fragment be a new DocumentFragment whose node document is node’s # node document. $fragment = $node->ownerDocument->createDocumentFragment(); # Append the node clone to fragment. $fragment->appendChild($clone); # Return fragment. return $fragment; } /** Iterates over a document fragment and sanitizes its nodes * * @param \DOMDocumentFragment $fragment The document fragment to sanitize */ protected function sanitizeDocumentFragment(\DOMDocumentFragment $fragment): void { # To sanitize a document fragment named fragment with a Sanitizer # sanitizer run these steps: # Let m be a map that maps nodes to a sanitize action. # Let nodes be a list containing the inclusive descendants of fragment, in tree order. // Basically we won't be doing things this way. Rather than treating // all of the fragment's nodes as a flat list, we'll walk the // fragment and decide as we go, till have visited every node $node = $fragment->firstChild; # For each node in nodes: while ($node) { # Let action be the result of running the sanitize a node algorithm on node with sanitizer. $action = $this->sanitizeNode($node); assert(in_array($action, [self::ACTION_BLOCK, self::ACTION_DROP, self::ACTION_KEEP]), new \Exception("The result of sanitizing a node must be one of the three actions")); # Set m[node] to action. # For each node in nodes: // Again, we're taking action one node at a time; m[node] is simply $action if ($action === self::ACTION_DROP) { # If m[node] is drop, remove node. $victim = $node; $node = $this->nextNode($node, false); $victim->parentNode->removeChild($victim); } else if ($action === self::ACTION_BLOCK) { # If m[node] is block, create a DocumentFragment fragment, # append all of node’s children to fragment, and replace # node within node’s parent with fragment. // This is a bit confusing because the variable name "fragment" // is re-used; this is a different fragment from the input // to this function $victim = $node; $node = $this->nextNode($node, true); $frag = $victim->ownerDocument->createDocumentFragment(); while ($victim->firstChild) { $frag->appendChild($victim->firstChild); } $victim->parentNode->replaceChild($victim, $frag); } else { # If m[node] is keep, do nothing. $node = $this->nextNode($node, true); } } } /** Examines a node and returns one of the sanitization actions * * Attributes may be removed as part of this function * * @param \DOMNode $node The node to examine */ protected function sanitizeNode(\DOMNode $node): int { # To sanitize a node named node with sanitizer run these steps: # Assert: node is not a Document or DocumentFragment or Attr # or DocumentType node. assert(!in_array(get_class($node), ["DOMDocument", "DOMDocumentFragment", "DOMAttr", "DOMDocumentType"]), new \Exception("Invalid node Type ".get_class($node))); if ($node instanceof \DOMElement) { # If node is an element node: # Let element be node. $element = $node; # For each attr in element’s attribute list: foreach ($element->attributes as $attr) { # Let attr action be the result of running the sanitize action # for an attribute algorithm on attr and element. $attrAction = $this->sanitizeAttribute($attr); # If attr action is different from keep, remove an attribute # supplying attr. if ($attrAction !== self::ACTION_KEEP) { $element->removeAttributeNode($attr); } } # Run the steps to handle funky elements on element. $this->handleFunkyElement($element); # Let action be the result of running the sanitize action for an # element on element. # Return action. return $this->sanitizeElement($element); } elseif ($node instanceof \DOMComment) { # If node is a Comment node: # Let config be sanitizer’s configuration dictionary, or the default configuration if no configuration dictionary was given. # If config’s allow comments option exists and |config|[allowComments] is true: Return keep. if ($this->config['allowComments'] ?? self::DEFAULT_CONF['allowComments']) { return self::ACTION_KEEP; } # Return drop. return self::ACTION_DROP; } elseif ($node instanceof \DOMText) { # If node is a Text node: Return keep. return self::ACTION_KEEP; } else { # Assert: node is a ProcessingInstruction # Return drop. //DEVIATION: we allow processing instructions by configuration just like comments if ($this->config['allowProcessingInstructions'] ?? self::DEFAULT_CONF['allowProcessingInstructions']) { return self::ACTION_KEEP; } return self::ACTION_DROP; } } protected function sanitizeAttribute(\DOMAttr $attr): int { # To determine the sanitize action for an attribute given a Sanitizer # configuration dictionary config, run these steps: # Let kind be attribute’s attribute kind. $ns = $attr->namespaceURI; $name = $attr->localName; $eNs = $attr->ownerElement->namespaceURI; $eName = $attr->ownerElement->localName; $set = self::KNOWN_ATTRIBUTES[$ns][$name][$eNs] ?? []; if (!array_intersect($set, [$eName, "*"])) { # The attribute kind of an attribute is one of regular # or unknown. Let attribute kind be: # - unknown, if the [HTML] specification does not assign any # meaning to attribute’s name. $kind = self::KIND_UNKNOWN; } else { # - regular, otherwise. $kind = self::KIND_REGULAR; } if ($kind === self::KIND_UNKNOWN && ($this->config['allowUnknownMarkup'] ?? self::DEFAULT_CONF['allowUnknownMarkup'])) { # If kind is unknown and if config["allowUnknownMarkup"] does not exist or it config["allowUnknownMarkup"] is false: Return drop. return self::ACTION_DROP; } elseif ($kind === self::KIND_REGULAR) {} # If kind is regular and attribute’s local name does not match any name in the baseline attribute allow list: Return drop. # If attribute matches any attribute match list in config’s attribute drop list: Return drop. # If attribute allow list exists in config: # Then let allow list be |config|["allowAttributes"]. # Otherwise: Let allow list be the default configuration's attribute allow list. # If attribute does not match any attribute match list in allow list: Return drop. # Return keep. } /** Finds the next node in tree order after $node, if any * * @param \DOMNode $node The context node * @param bool $considerChildren Whether or not child nodes are valid next nodes */ protected function nextNode(\DOMNode $node, bool $considerChildren): ?\DOMNode { if ($node->hasChildNodes() && $considerChildren) { return $node->firstChild; } $next = $node->nextSibling; while (!$next) { $node = $node->parentNode; if (!$node) { return null; } $next = $node->nextSibling; } return $next; } }