<?php
/*

 * == Aimy Extensions Comment Start ==
 *
 * HTML5-PHP is released under the MIT license. The original html5lib library
 * was also released under the MIT license.
 *
 * The X11 License (aka. MIT License) is compatible with the GNU GPL.
 *
 * See http://www.gnu.org/licenses/license-list.html#X11License for details.
 *
 * == Aimy Extensions Comment End ==

## HTML5-PHP License

Copyright (c) 2013 The Authors of HTML5-PHP

Matt Butcher - mattbutcher@google.com
Matt Farina - matt@mattfarina.com
Asmir Mustafic - goetas@gmail.com

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

## HTML5Lib License

Portions of this are based on html5lib's PHP version, which was a
sub-project of html5lib. The following is the list of contributors from
html5lib:

html5lib:

Copyright (c) 2006-2009 The Authors

Contributors:
James Graham - jg307@cam.ac.uk
Anne van Kesteren - annevankesteren@gmail.com
Lachlan Hunt - lachlan.hunt@lachy.id.au
Matt McDonald - kanashii@kanashii.ca
Sam Ruby - rubys@intertwingly.net
Ian Hickson (Google) - ian@hixie.ch
Thomas Broyer - t.broyer@ltgt.net
Jacques Distler - distler@golem.ph.utexas.edu
Henri Sivonen - hsivonen@iki.fi
Adam Barth - abarth@webkit.org
Eric Seidel - eric@webkit.org
The Mozilla Foundation (contributions from Henri Sivonen since 2008)
David Flanagan (Mozilla) - dflanagan@mozilla.com

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 namespace AimySpeedOptimization\Masterminds; defined('_JEXEC') or die(); use AimySpeedOptimization\Masterminds\HTML5\Parser\DOMTreeBuilder; use AimySpeedOptimization\Masterminds\HTML5\Parser\Scanner; use AimySpeedOptimization\Masterminds\HTML5\Parser\Tokenizer; use AimySpeedOptimization\Masterminds\HTML5\Serializer\OutputRules; use AimySpeedOptimization\Masterminds\HTML5\Serializer\Traverser; class HTML5 { private $defaultOptions = array( 'encode_entities' => false, 'disable_html_ns' => false, ); protected $errors = array(); public function __construct(array $defaultOptions = array()) { $this->defaultOptions = array_merge($this->defaultOptions, $defaultOptions); } public function getOptions() { return $this->defaultOptions; } public function load($file, array $options = array()) { if (is_resource($file)) { return $this->parse(stream_get_contents($file), $options); } return $this->parse(file_get_contents($file), $options); } public function loadHTML($string, array $options = array()) { return $this->parse($string, $options); } public function loadHTMLFile($file, array $options = array()) { return $this->load($file, $options); } public function loadHTMLFragment($string, array $options = array()) { return $this->parseFragment($string, $options); } public function getErrors() { return $this->errors; } public function hasErrors() { return count($this->errors) > 0; } public function parse($input, array $options = array()) { $this->errors = array(); $options = array_merge($this->defaultOptions, $options); $events = new DOMTreeBuilder(false, $options); $scanner = new Scanner($input, !empty($options['encoding']) ? $options['encoding'] : 'UTF-8'); $parser = new Tokenizer($scanner, $events, !empty($options['xmlNamespaces']) ? Tokenizer::CONFORMANT_XML : Tokenizer::CONFORMANT_HTML); $parser->parse(); $this->errors = $events->getErrors(); return $events->document(); } public function parseFragment($input, array $options = array()) { $options = array_merge($this->defaultOptions, $options); $events = new DOMTreeBuilder(true, $options); $scanner = new Scanner($input, !empty($options['encoding']) ? $options['encoding'] : 'UTF-8'); $parser = new Tokenizer($scanner, $events, !empty($options['xmlNamespaces']) ? Tokenizer::CONFORMANT_XML : Tokenizer::CONFORMANT_HTML); $parser->parse(); $this->errors = $events->getErrors(); return $events->fragment(); } public function save($dom, $file, $options = array()) { $close = true; if (is_resource($file)) { $stream = $file; $close = false; } else { $stream = fopen($file, 'wb'); } $options = array_merge($this->defaultOptions, $options); $rules = new OutputRules($stream, $options); $trav = new Traverser($dom, $stream, $rules, $options); $trav->walk(); $rules->unsetTraverser(); if ($close) { fclose($stream); } } public function saveHTML($dom, $options = array()) { $stream = fopen('php://temp', 'wb'); $this->save($dom, $stream, array_merge($this->defaultOptions, $options)); $html = stream_get_contents($stream, -1, 0); fclose($stream); return $html; } } namespace AimySpeedOptimization\Masterminds\HTML5; class Elements { const KNOWN_ELEMENT = 1; const TEXT_RAW = 2; const TEXT_RCDATA = 4; const VOID_TAG = 8; const AUTOCLOSE_P = 16; const TEXT_PLAINTEXT = 32; const BLOCK_TAG = 64; const BLOCK_ONLY_INLINE = 128; public static $optionalEndElementsParentsToClose = array( 'tr' => array('td', 'tr'), 'td' => array('td', 'th'), 'th' => array('td', 'th'), 'tfoot' => array('td', 'th', 'tr', 'tbody', 'thead'), 'tbody' => array('td', 'th', 'tr', 'thead'), ); public static $html5 = array( 'a' => 1, 'abbr' => 1, 'address' => 65, 'area' => 9, 'article' => 81, 'aside' => 81, 'audio' => 1, 'b' => 1, 'base' => 9, 'bdi' => 1, 'bdo' => 1, 'blockquote' => 81, 'body' => 1, 'br' => 9, 'button' => 1, 'canvas' => 65, 'caption' => 1, 'cite' => 1, 'code' => 1, 'col' => 9, 'colgroup' => 1, 'command' => 9, 'datalist' => 1, 'dd' => 65, 'del' => 1, 'details' => 17, 'dfn' => 1, 'dialog' => 17, 'div' => 81, 'dl' => 81, 'dt' => 1, 'em' => 1, 'embed' => 9, 'fieldset' => 81, 'figcaption' => 81, 'figure' => 81, 'footer' => 81, 'form' => 81, 'h1' => 81, 'h2' => 81, 'h3' => 81, 'h4' => 81, 'h5' => 81, 'h6' => 81, 'head' => 1, 'header' => 81, 'hgroup' => 81, 'hr' => 73, 'html' => 1, 'i' => 1, 'iframe' => 3, 'img' => 9, 'input' => 9, 'kbd' => 1, 'ins' => 1, 'keygen' => 9, 'label' => 1, 'legend' => 1, 'li' => 1, 'link' => 9, 'map' => 1, 'mark' => 1, 'menu' => 17, 'meta' => 9, 'meter' => 1, 'nav' => 17, 'noscript' => 65, 'object' => 1, 'ol' => 81, 'optgroup' => 1, 'option' => 1, 'output' => 65, 'p' => 209, 'param' => 9, 'pre' => 81, 'progress' => 1, 'q' => 1, 'rp' => 1, 'rt' => 1, 'ruby' => 1, 's' => 1, 'samp' => 1, 'script' => 3, 'section' => 81, 'select' => 1, 'small' => 1, 'source' => 9, 'span' => 1, 'strong' => 1, 'style' => 3, 'sub' => 1, 'summary' => 17, 'sup' => 1, 'table' => 65, 'tbody' => 1, 'td' => 1, 'textarea' => 5, 'tfoot' => 65, 'th' => 1, 'thead' => 1, 'time' => 1, 'title' => 5, 'tr' => 1, 'track' => 9, 'u' => 1, 'ul' => 81, 'var' => 1, 'video' => 1, 'wbr' => 9, 'basefont' => 8, 'bgsound' => 8, 'noframes' => 2, 'frame' => 9, 'frameset' => 1, 'center' => 16, 'dir' => 16, 'listing' => 16, 'plaintext' => 48, 'applet' => 0, 'marquee' => 0, 'isindex' => 8, 'xmp' => 20, 'noembed' => 2, ); public static $mathml = array( 'maction' => 1, 'maligngroup' => 1, 'malignmark' => 1, 'math' => 1, 'menclose' => 1, 'merror' => 1, 'mfenced' => 1, 'mfrac' => 1, 'mglyph' => 1, 'mi' => 1, 'mlabeledtr' => 1, 'mlongdiv' => 1, 'mmultiscripts' => 1, 'mn' => 1, 'mo' => 1, 'mover' => 1, 'mpadded' => 1, 'mphantom' => 1, 'mroot' => 1, 'mrow' => 1, 'ms' => 1, 'mscarries' => 1, 'mscarry' => 1, 'msgroup' => 1, 'msline' => 1, 'mspace' => 1, 'msqrt' => 1, 'msrow' => 1, 'mstack' => 1, 'mstyle' => 1, 'msub' => 1, 'msup' => 1, 'msubsup' => 1, 'mtable' => 1, 'mtd' => 1, 'mtext' => 1, 'mtr' => 1, 'munder' => 1, 'munderover' => 1, ); public static $svg = array( 'a' => 1, 'altGlyph' => 1, 'altGlyphDef' => 1, 'altGlyphItem' => 1, 'animate' => 1, 'animateColor' => 1, 'animateMotion' => 1, 'animateTransform' => 1, 'circle' => 1, 'clipPath' => 1, 'color-profile' => 1, 'cursor' => 1, 'defs' => 1, 'desc' => 1, 'ellipse' => 1, 'feBlend' => 1, 'feColorMatrix' => 1, 'feComponentTransfer' => 1, 'feComposite' => 1, 'feConvolveMatrix' => 1, 'feDiffuseLighting' => 1, 'feDisplacementMap' => 1, 'feDistantLight' => 1, 'feFlood' => 1, 'feFuncA' => 1, 'feFuncB' => 1, 'feFuncG' => 1, 'feFuncR' => 1, 'feGaussianBlur' => 1, 'feImage' => 1, 'feMerge' => 1, 'feMergeNode' => 1, 'feMorphology' => 1, 'feOffset' => 1, 'fePointLight' => 1, 'feSpecularLighting' => 1, 'feSpotLight' => 1, 'feTile' => 1, 'feTurbulence' => 1, 'filter' => 1, 'font' => 1, 'font-face' => 1, 'font-face-format' => 1, 'font-face-name' => 1, 'font-face-src' => 1, 'font-face-uri' => 1, 'foreignObject' => 1, 'g' => 1, 'glyph' => 1, 'glyphRef' => 1, 'hkern' => 1, 'image' => 1, 'line' => 1, 'linearGradient' => 1, 'marker' => 1, 'mask' => 1, 'metadata' => 1, 'missing-glyph' => 1, 'mpath' => 1, 'path' => 1, 'pattern' => 1, 'polygon' => 1, 'polyline' => 1, 'radialGradient' => 1, 'rect' => 1, 'script' => 3, 'set' => 1, 'stop' => 1, 'style' => 3, 'svg' => 1, 'switch' => 1, 'symbol' => 1, 'text' => 1, 'textPath' => 1, 'title' => 1, 'tref' => 1, 'tspan' => 1, 'use' => 1, 'view' => 1, 'vkern' => 1, ); public static $svgCaseSensitiveAttributeMap = array( 'attributename' => 'attributeName', 'attributetype' => 'attributeType', 'basefrequency' => 'baseFrequency', 'baseprofile' => 'baseProfile', 'calcmode' => 'calcMode', 'clippathunits' => 'clipPathUnits', 'contentscripttype' => 'contentScriptType', 'contentstyletype' => 'contentStyleType', 'diffuseconstant' => 'diffuseConstant', 'edgemode' => 'edgeMode', 'externalresourcesrequired' => 'externalResourcesRequired', 'filterres' => 'filterRes', 'filterunits' => 'filterUnits', 'glyphref' => 'glyphRef', 'gradienttransform' => 'gradientTransform', 'gradientunits' => 'gradientUnits', 'kernelmatrix' => 'kernelMatrix', 'kernelunitlength' => 'kernelUnitLength', 'keypoints' => 'keyPoints', 'keysplines' => 'keySplines', 'keytimes' => 'keyTimes', 'lengthadjust' => 'lengthAdjust', 'limitingconeangle' => 'limitingConeAngle', 'markerheight' => 'markerHeight', 'markerunits' => 'markerUnits', 'markerwidth' => 'markerWidth', 'maskcontentunits' => 'maskContentUnits', 'maskunits' => 'maskUnits', 'numoctaves' => 'numOctaves', 'pathlength' => 'pathLength', 'patterncontentunits' => 'patternContentUnits', 'patterntransform' => 'patternTransform', 'patternunits' => 'patternUnits', 'pointsatx' => 'pointsAtX', 'pointsaty' => 'pointsAtY', 'pointsatz' => 'pointsAtZ', 'preservealpha' => 'preserveAlpha', 'preserveaspectratio' => 'preserveAspectRatio', 'primitiveunits' => 'primitiveUnits', 'refx' => 'refX', 'refy' => 'refY', 'repeatcount' => 'repeatCount', 'repeatdur' => 'repeatDur', 'requiredextensions' => 'requiredExtensions', 'requiredfeatures' => 'requiredFeatures', 'specularconstant' => 'specularConstant', 'specularexponent' => 'specularExponent', 'spreadmethod' => 'spreadMethod', 'startoffset' => 'startOffset', 'stddeviation' => 'stdDeviation', 'stitchtiles' => 'stitchTiles', 'surfacescale' => 'surfaceScale', 'systemlanguage' => 'systemLanguage', 'tablevalues' => 'tableValues', 'targetx' => 'targetX', 'targety' => 'targetY', 'textlength' => 'textLength', 'viewbox' => 'viewBox', 'viewtarget' => 'viewTarget', 'xchannelselector' => 'xChannelSelector', 'ychannelselector' => 'yChannelSelector', 'zoomandpan' => 'zoomAndPan', ); public static $svgCaseSensitiveElementMap = array( 'altglyph' => 'altGlyph', 'altglyphdef' => 'altGlyphDef', 'altglyphitem' => 'altGlyphItem', 'animatecolor' => 'animateColor', 'animatemotion' => 'animateMotion', 'animatetransform' => 'animateTransform', 'clippath' => 'clipPath', 'feblend' => 'feBlend', 'fecolormatrix' => 'feColorMatrix', 'fecomponenttransfer' => 'feComponentTransfer', 'fecomposite' => 'feComposite', 'feconvolvematrix' => 'feConvolveMatrix', 'fediffuselighting' => 'feDiffuseLighting', 'fedisplacementmap' => 'feDisplacementMap', 'fedistantlight' => 'feDistantLight', 'feflood' => 'feFlood', 'fefunca' => 'feFuncA', 'fefuncb' => 'feFuncB', 'fefuncg' => 'feFuncG', 'fefuncr' => 'feFuncR', 'fegaussianblur' => 'feGaussianBlur', 'feimage' => 'feImage', 'femerge' => 'feMerge', 'femergenode' => 'feMergeNode', 'femorphology' => 'feMorphology', 'feoffset' => 'feOffset', 'fepointlight' => 'fePointLight', 'fespecularlighting' => 'feSpecularLighting', 'fespotlight' => 'feSpotLight', 'fetile' => 'feTile', 'feturbulence' => 'feTurbulence', 'foreignobject' => 'foreignObject', 'glyphref' => 'glyphRef', 'lineargradient' => 'linearGradient', 'radialgradient' => 'radialGradient', 'textpath' => 'textPath', ); public static function isA($name, $mask) { return (static::element($name) & $mask) === $mask; } public static function isHtml5Element($name) { return isset(static::$html5[strtolower($name)]); } public static function isMathMLElement($name) { return isset(static::$mathml[$name]); } public static function isSvgElement($name) { return isset(static::$svg[$name]); } public static function isElement($name) { return static::isHtml5Element($name) || static::isMathMLElement($name) || static::isSvgElement($name); } public static function element($name) { if (isset(static::$html5[$name])) { return static::$html5[$name]; } if (isset(static::$svg[$name])) { return static::$svg[$name]; } if (isset(static::$mathml[$name])) { return static::$mathml[$name]; } return 0; } public static function normalizeSvgElement($name) { $name = strtolower($name); if (isset(static::$svgCaseSensitiveElementMap[$name])) { $name = static::$svgCaseSensitiveElementMap[$name]; } return $name; } public static function normalizeSvgAttribute($name) { $name = strtolower($name); if (isset(static::$svgCaseSensitiveAttributeMap[$name])) { $name = static::$svgCaseSensitiveAttributeMap[$name]; } return $name; } public static function normalizeMathMlAttribute($name) { $name = strtolower($name); if ('definitionurl' === $name) { $name = 'definitionURL'; } return $name; } } namespace AimySpeedOptimization\Masterminds\HTML5; class Entities { public static $byName = array( 'Aacute' => 'Á', 'Aacut' => 'Á', 'aacute' => 'á', 'aacut' => 'á', 'Abreve' => 'Ă', 'abreve' => 'ă', 'ac' => '∾', 'acd' => '∿', 'acE' => '∾̳', 'Acirc' => 'Â', 'Acir' => 'Â', 'acirc' => 'â', 'acir' => 'â', 'acute' => '´', 'acut' => '´', 'Acy' => 'А', 'acy' => 'а', 'AElig' => 'Æ', 'AEli' => 'Æ', 'aelig' => 'æ', 'aeli' => 'æ', 'af' => '⁡', 'Afr' => '𝔄', 'afr' => '𝔞', 'Agrave' => 'À', 'Agrav' => 'À', 'agrave' => 'à', 'agrav' => 'à', 'alefsym' => 'ℵ', 'aleph' => 'ℵ', 'Alpha' => 'Α', 'alpha' => 'α', 'Amacr' => 'Ā', 'amacr' => 'ā', 'amalg' => '⨿', 'AMP' => '&', 'AM' => '&', 'amp' => '&', 'am' => '&', 'And' => '⩓', 'and' => '∧', 'andand' => '⩕', 'andd' => '⩜', 'andslope' => '⩘', 'andv' => '⩚', 'ang' => '∠', 'ange' => '⦤', 'angle' => '∠', 'angmsd' => '∡', 'angmsdaa' => '⦨', 'angmsdab' => '⦩', 'angmsdac' => '⦪', 'angmsdad' => '⦫', 'angmsdae' => '⦬', 'angmsdaf' => '⦭', 'angmsdag' => '⦮', 'angmsdah' => '⦯', 'angrt' => '∟', 'angrtvb' => '⊾', 'angrtvbd' => '⦝', 'angsph' => '∢', 'angst' => 'Å', 'angzarr' => '⍼', 'Aogon' => 'Ą', 'aogon' => 'ą', 'Aopf' => '𝔸', 'aopf' => '𝕒', 'ap' => '≈', 'apacir' => '⩯', 'apE' => '⩰', 'ape' => '≊', 'apid' => '≋', 'apos' => '\'', 'ApplyFunction' => '⁡', 'approx' => '≈', 'approxeq' => '≊', 'Aring' => 'Å', 'Arin' => 'Å', 'aring' => 'å', 'arin' => 'å', 'Ascr' => '𝒜', 'ascr' => '𝒶', 'Assign' => '≔', 'ast' => '*', 'asymp' => '≈', 'asympeq' => '≍', 'Atilde' => 'Ã', 'Atild' => 'Ã', 'atilde' => 'ã', 'atild' => 'ã', 'Auml' => 'Ä', 'Aum' => 'Ä', 'auml' => 'ä', 'aum' => 'ä', 'awconint' => '∳', 'awint' => '⨑', 'backcong' => '≌', 'backepsilon' => '϶', 'backprime' => '‵', 'backsim' => '∽', 'backsimeq' => '⋍', 'Backslash' => '∖', 'Barv' => '⫧', 'barvee' => '⊽', 'Barwed' => '⌆', 'barwed' => '⌅', 'barwedge' => '⌅', 'bbrk' => '⎵', 'bbrktbrk' => '⎶', 'bcong' => '≌', 'Bcy' => 'Б', 'bcy' => 'б', 'bdquo' => '„', 'becaus' => '∵', 'Because' => '∵', 'because' => '∵', 'bemptyv' => '⦰', 'bepsi' => '϶', 'bernou' => 'ℬ', 'Bernoullis' => 'ℬ', 'Beta' => 'Β', 'beta' => 'β', 'beth' => 'ℶ', 'between' => '≬', 'Bfr' => '𝔅', 'bfr' => '𝔟', 'bigcap' => '⋂', 'bigcirc' => '◯', 'bigcup' => '⋃', 'bigodot' => '⨀', 'bigoplus' => '⨁', 'bigotimes' => '⨂', 'bigsqcup' => '⨆', 'bigstar' => '★', 'bigtriangledown' => '▽', 'bigtriangleup' => '△', 'biguplus' => '⨄', 'bigvee' => '⋁', 'bigwedge' => '⋀', 'bkarow' => '⤍', 'blacklozenge' => '⧫', 'blacksquare' => '▪', 'blacktriangle' => '▴', 'blacktriangledown' => '▾', 'blacktriangleleft' => '◂', 'blacktriangleright' => '▸', 'blank' => '␣', 'blk12' => '▒', 'blk14' => '░', 'blk34' => '▓', 'block' => '█', 'bne' => '=⃥', 'bnequiv' => '≡⃥', 'bNot' => '⫭', 'bnot' => '⌐', 'Bopf' => '𝔹', 'bopf' => '𝕓', 'bot' => '⊥', 'bottom' => '⊥', 'bowtie' => '⋈', 'boxbox' => '⧉', 'boxDL' => '╗', 'boxDl' => '╖', 'boxdL' => '╕', 'boxdl' => '┐', 'boxDR' => '╔', 'boxDr' => '╓', 'boxdR' => '╒', 'boxdr' => '┌', 'boxH' => '═', 'boxh' => '─', 'boxHD' => '╦', 'boxHd' => '╤', 'boxhD' => '╥', 'boxhd' => '┬', 'boxHU' => '╩', 'boxHu' => '╧', 'boxhU' => '╨', 'boxhu' => '┴', 'boxminus' => '⊟', 'boxplus' => '⊞', 'boxtimes' => '⊠', 'boxUL' => '╝', 'boxUl' => '╜', 'boxuL' => '╛', 'boxul' => '┘', 'boxUR' => '╚', 'boxUr' => '╙', 'boxuR' => '╘', 'boxur' => '└', 'boxV' => '║', 'boxv' => '│', 'boxVH' => '╬', 'boxVh' => '╫', 'boxvH' => '╪', 'boxvh' => '┼', 'boxVL' => '╣', 'boxVl' => '╢', 'boxvL' => '╡', 'boxvl' => '┤', 'boxVR' => '╠', 'boxVr' => '╟', 'boxvR' => '╞', 'boxvr' => '├', 'bprime' => '‵', 'Breve' => '˘', 'breve' => '˘', 'brvbar' => '¦', 'brvba' => '¦', 'Bscr' => 'ℬ', 'bscr' => '𝒷', 'bsemi' => '⁏', 'bsim' => '∽', 'bsime' => '⋍', 'bsol' => '\\', 'bsolb' => '⧅', 'bsolhsub' => '⟈', 'bull' => '•', 'bullet' => '•', 'bump' => '≎', 'bumpE' => '⪮', 'bumpe' => '≏', 'Bumpeq' => '≎', 'bumpeq' => '≏', 'Cacute' => 'Ć', 'cacute' => 'ć', 'Cap' => '⋒', 'cap' => '∩', 'capand' => '⩄', 'capbrcup' => '⩉', 'capcap' => '⩋', 'capcup' => '⩇', 'capdot' => '⩀', 'CapitalDifferentialD' => 'ⅅ', 'caps' => '∩︀', 'caret' => '⁁', 'caron' => 'ˇ', 'Cayleys' => 'ℭ', 'ccaps' => '⩍', 'Ccaron' => 'Č', 'ccaron' => 'č', 'Ccedil' => 'Ç', 'Ccedi' => 'Ç', 'ccedil' => 'ç', 'ccedi' => 'ç', 'Ccirc' => 'Ĉ', 'ccirc' => 'ĉ', 'Cconint' => '∰', 'ccups' => '⩌', 'ccupssm' => '⩐', 'Cdot' => 'Ċ', 'cdot' => 'ċ', 'cedil' => '¸', 'cedi' => '¸', 'Cedilla' => '¸', 'cemptyv' => '⦲', 'cent' => '¢', 'cen' => '¢', 'CenterDot' => '·', 'centerdot' => '·', 'Cfr' => 'ℭ', 'cfr' => '𝔠', 'CHcy' => 'Ч', 'chcy' => 'ч', 'check' => '✓', 'checkmark' => '✓', 'Chi' => 'Χ', 'chi' => 'χ', 'cir' => '○', 'circ' => 'ˆ', 'circeq' => '≗', 'circlearrowleft' => '↺', 'circlearrowright' => '↻', 'circledast' => '⊛', 'circledcirc' => '⊚', 'circleddash' => '⊝', 'CircleDot' => '⊙', 'circledR' => '®', 'circledS' => 'Ⓢ', 'CircleMinus' => '⊖', 'CirclePlus' => '⊕', 'CircleTimes' => '⊗', 'cirE' => '⧃', 'cire' => '≗', 'cirfnint' => '⨐', 'cirmid' => '⫯', 'cirscir' => '⧂', 'ClockwiseContourIntegral' => '∲', 'CloseCurlyDoubleQuote' => '”', 'CloseCurlyQuote' => '’', 'clubs' => '♣', 'clubsuit' => '♣', 'Colon' => '∷', 'colon' => ':', 'Colone' => '⩴', 'colone' => '≔', 'coloneq' => '≔', 'comma' => ',', 'commat' => '@', 'comp' => '∁', 'compfn' => '∘', 'complement' => '∁', 'complexes' => 'ℂ', 'cong' => '≅', 'congdot' => '⩭', 'Congruent' => '≡', 'Conint' => '∯', 'conint' => '∮', 'ContourIntegral' => '∮', 'Copf' => 'ℂ', 'copf' => '𝕔', 'coprod' => '∐', 'Coproduct' => '∐', 'COPY' => '©', 'COP' => '©', 'copy' => '©', 'cop' => '©', 'copysr' => '℗', 'CounterClockwiseContourIntegral' => '∳', 'crarr' => '↵', 'Cross' => '⨯', 'cross' => '✗', 'Cscr' => '𝒞', 'cscr' => '𝒸', 'csub' => '⫏', 'csube' => '⫑', 'csup' => '⫐', 'csupe' => '⫒', 'ctdot' => '⋯', 'cudarrl' => '⤸', 'cudarrr' => '⤵', 'cuepr' => '⋞', 'cuesc' => '⋟', 'cularr' => '↶', 'cularrp' => '⤽', 'Cup' => '⋓', 'cup' => '∪', 'cupbrcap' => '⩈', 'CupCap' => '≍', 'cupcap' => '⩆', 'cupcup' => '⩊', 'cupdot' => '⊍', 'cupor' => '⩅', 'cups' => '∪︀', 'curarr' => '↷', 'curarrm' => '⤼', 'curlyeqprec' => '⋞', 'curlyeqsucc' => '⋟', 'curlyvee' => '⋎', 'curlywedge' => '⋏', 'curren' => '¤', 'curre' => '¤', 'curvearrowleft' => '↶', 'curvearrowright' => '↷', 'cuvee' => '⋎', 'cuwed' => '⋏', 'cwconint' => '∲', 'cwint' => '∱', 'cylcty' => '⌭', 'Dagger' => '‡', 'dagger' => '†', 'daleth' => 'ℸ', 'Darr' => '↡', 'dArr' => '⇓', 'darr' => '↓', 'dash' => '‐', 'Dashv' => '⫤', 'dashv' => '⊣', 'dbkarow' => '⤏', 'dblac' => '˝', 'Dcaron' => 'Ď', 'dcaron' => 'ď', 'Dcy' => 'Д', 'dcy' => 'д', 'DD' => 'ⅅ', 'dd' => 'ⅆ', 'ddagger' => '‡', 'ddarr' => '⇊', 'DDotrahd' => '⤑', 'ddotseq' => '⩷', 'deg' => '°', 'de' => '°', 'Del' => '∇', 'Delta' => 'Δ', 'delta' => 'δ', 'demptyv' => '⦱', 'dfisht' => '⥿', 'Dfr' => '𝔇', 'dfr' => '𝔡', 'dHar' => '⥥', 'dharl' => '⇃', 'dharr' => '⇂', 'DiacriticalAcute' => '´', 'DiacriticalDot' => '˙', 'DiacriticalDoubleAcute' => '˝', 'DiacriticalGrave' => '`', 'DiacriticalTilde' => '˜', 'diam' => '⋄', 'Diamond' => '⋄', 'diamond' => '⋄', 'diamondsuit' => '♦', 'diams' => '♦', 'die' => '¨', 'DifferentialD' => 'ⅆ', 'digamma' => 'ϝ', 'disin' => '⋲', 'div' => '÷', 'divide' => '÷', 'divid' => '÷', 'divideontimes' => '⋇', 'divonx' => '⋇', 'DJcy' => 'Ђ', 'djcy' => 'ђ', 'dlcorn' => '⌞', 'dlcrop' => '⌍', 'dollar' => '$', 'Dopf' => '𝔻', 'dopf' => '𝕕', 'Dot' => '¨', 'dot' => '˙', 'DotDot' => '⃜', 'doteq' => '≐', 'doteqdot' => '≑', 'DotEqual' => '≐', 'dotminus' => '∸', 'dotplus' => '∔', 'dotsquare' => '⊡', 'doublebarwedge' => '⌆', 'DoubleContourIntegral' => '∯', 'DoubleDot' => '¨', 'DoubleDownArrow' => '⇓', 'DoubleLeftArrow' => '⇐', 'DoubleLeftRightArrow' => '⇔', 'DoubleLeftTee' => '⫤', 'DoubleLongLeftArrow' => '⟸', 'DoubleLongLeftRightArrow' => '⟺', 'DoubleLongRightArrow' => '⟹', 'DoubleRightArrow' => '⇒', 'DoubleRightTee' => '⊨', 'DoubleUpArrow' => '⇑', 'DoubleUpDownArrow' => '⇕', 'DoubleVerticalBar' => '∥', 'DownArrow' => '↓', 'Downarrow' => '⇓', 'downarrow' => '↓', 'DownArrowBar' => '⤓', 'DownArrowUpArrow' => '⇵', 'DownBreve' => '̑', 'downdownarrows' => '⇊', 'downharpoonleft' => '⇃', 'downharpoonright' => '⇂', 'DownLeftRightVector' => '⥐', 'DownLeftTeeVector' => '⥞', 'DownLeftVector' => '↽', 'DownLeftVectorBar' => '⥖', 'DownRightTeeVector' => '⥟', 'DownRightVector' => '⇁', 'DownRightVectorBar' => '⥗', 'DownTee' => '⊤', 'DownTeeArrow' => '↧', 'drbkarow' => '⤐', 'drcorn' => '⌟', 'drcrop' => '⌌', 'Dscr' => '𝒟', 'dscr' => '𝒹', 'DScy' => 'Ѕ', 'dscy' => 'ѕ', 'dsol' => '⧶', 'Dstrok' => 'Đ', 'dstrok' => 'đ', 'dtdot' => '⋱', 'dtri' => '▿', 'dtrif' => '▾', 'duarr' => '⇵', 'duhar' => '⥯', 'dwangle' => '⦦', 'DZcy' => 'Џ', 'dzcy' => 'џ', 'dzigrarr' => '⟿', 'Eacute' => 'É', 'Eacut' => 'É', 'eacute' => 'é', 'eacut' => 'é', 'easter' => '⩮', 'Ecaron' => 'Ě', 'ecaron' => 'ě', 'ecir' => 'ê', 'Ecirc' => 'Ê', 'Ecir' => 'Ê', 'ecirc' => 'ê', 'ecolon' => '≕', 'Ecy' => 'Э', 'ecy' => 'э', 'eDDot' => '⩷', 'Edot' => 'Ė', 'eDot' => '≑', 'edot' => 'ė', 'ee' => 'ⅇ', 'efDot' => '≒', 'Efr' => '𝔈', 'efr' => '𝔢', 'eg' => '⪚', 'Egrave' => 'È', 'Egrav' => 'È', 'egrave' => 'è', 'egrav' => 'è', 'egs' => '⪖', 'egsdot' => '⪘', 'el' => '⪙', 'Element' => '∈', 'elinters' => '⏧', 'ell' => 'ℓ', 'els' => '⪕', 'elsdot' => '⪗', 'Emacr' => 'Ē', 'emacr' => 'ē', 'empty' => '∅', 'emptyset' => '∅', 'EmptySmallSquare' => '◻', 'emptyv' => '∅', 'EmptyVerySmallSquare' => '▫', 'emsp' => ' ', 'emsp13' => ' ', 'emsp14' => ' ', 'ENG' => 'Ŋ', 'eng' => 'ŋ', 'ensp' => ' ', 'Eogon' => 'Ę', 'eogon' => 'ę', 'Eopf' => '𝔼', 'eopf' => '𝕖', 'epar' => '⋕', 'eparsl' => '⧣', 'eplus' => '⩱', 'epsi' => 'ε', 'Epsilon' => 'Ε', 'epsilon' => 'ε', 'epsiv' => 'ϵ', 'eqcirc' => '≖', 'eqcolon' => '≕', 'eqsim' => '≂', 'eqslantgtr' => '⪖', 'eqslantless' => '⪕', 'Equal' => '⩵', 'equals' => '=', 'EqualTilde' => '≂', 'equest' => '≟', 'Equilibrium' => '⇌', 'equiv' => '≡', 'equivDD' => '⩸', 'eqvparsl' => '⧥', 'erarr' => '⥱', 'erDot' => '≓', 'Escr' => 'ℰ', 'escr' => 'ℯ', 'esdot' => '≐', 'Esim' => '⩳', 'esim' => '≂', 'Eta' => 'Η', 'eta' => 'η', 'ETH' => 'Ð', 'ET' => 'Ð', 'eth' => 'ð', 'et' => 'ð', 'Euml' => 'Ë', 'Eum' => 'Ë', 'euml' => 'ë', 'eum' => 'ë', 'euro' => '€', 'excl' => '!', 'exist' => '∃', 'Exists' => '∃', 'expectation' => 'ℰ', 'ExponentialE' => 'ⅇ', 'exponentiale' => 'ⅇ', 'fallingdotseq' => '≒', 'Fcy' => 'Ф', 'fcy' => 'ф', 'female' => '♀', 'ffilig' => 'ﬃ', 'fflig' => 'ﬀ', 'ffllig' => 'ﬄ', 'Ffr' => '𝔉', 'ffr' => '𝔣', 'filig' => 'ﬁ', 'FilledSmallSquare' => '◼', 'FilledVerySmallSquare' => '▪', 'fjlig' => 'fj', 'flat' => '♭', 'fllig' => 'ﬂ', 'fltns' => '▱', 'fnof' => 'ƒ', 'Fopf' => '𝔽', 'fopf' => '𝕗', 'ForAll' => '∀', 'forall' => '∀', 'fork' => '⋔', 'forkv' => '⫙', 'Fouriertrf' => 'ℱ', 'fpartint' => '⨍', 'frac12' => '½', 'frac1' => '¼', 'frac13' => '⅓', 'frac14' => '¼', 'frac15' => '⅕', 'frac16' => '⅙', 'frac18' => '⅛', 'frac23' => '⅔', 'frac25' => '⅖', 'frac34' => '¾', 'frac3' => '¾', 'frac35' => '⅗', 'frac38' => '⅜', 'frac45' => '⅘', 'frac56' => '⅚', 'frac58' => '⅝', 'frac78' => '⅞', 'frasl' => '⁄', 'frown' => '⌢', 'Fscr' => 'ℱ', 'fscr' => '𝒻', 'gacute' => 'ǵ', 'Gamma' => 'Γ', 'gamma' => 'γ', 'Gammad' => 'Ϝ', 'gammad' => 'ϝ', 'gap' => '⪆', 'Gbreve' => 'Ğ', 'gbreve' => 'ğ', 'Gcedil' => 'Ģ', 'Gcirc' => 'Ĝ', 'gcirc' => 'ĝ', 'Gcy' => 'Г', 'gcy' => 'г', 'Gdot' => 'Ġ', 'gdot' => 'ġ', 'gE' => '≧', 'ge' => '≥', 'gEl' => '⪌', 'gel' => '⋛', 'geq' => '≥', 'geqq' => '≧', 'geqslant' => '⩾', 'ges' => '⩾', 'gescc' => '⪩', 'gesdot' => '⪀', 'gesdoto' => '⪂', 'gesdotol' => '⪄', 'gesl' => '⋛︀', 'gesles' => '⪔', 'Gfr' => '𝔊', 'gfr' => '𝔤', 'Gg' => '⋙', 'gg' => '≫', 'ggg' => '⋙', 'gimel' => 'ℷ', 'GJcy' => 'Ѓ', 'gjcy' => 'ѓ', 'gl' => '≷', 'gla' => '⪥', 'glE' => '⪒', 'glj' => '⪤', 'gnap' => '⪊', 'gnapprox' => '⪊', 'gnE' => '≩', 'gne' => '⪈', 'gneq' => '⪈', 'gneqq' => '≩', 'gnsim' => '⋧', 'Gopf' => '𝔾', 'gopf' => '𝕘', 'grave' => '`', 'GreaterEqual' => '≥', 'GreaterEqualLess' => '⋛', 'GreaterFullEqual' => '≧', 'GreaterGreater' => '⪢', 'GreaterLess' => '≷', 'GreaterSlantEqual' => '⩾', 'GreaterTilde' => '≳', 'Gscr' => '𝒢', 'gscr' => 'ℊ', 'gsim' => '≳', 'gsime' => '⪎', 'gsiml' => '⪐', 'GT' => '>', 'G' => '>', 'Gt' => '≫', 'gt' => '>', 'g' => '>', 'gtcc' => '⪧', 'gtcir' => '⩺', 'gtdot' => '⋗', 'gtlPar' => '⦕', 'gtquest' => '⩼', 'gtrapprox' => '⪆', 'gtrarr' => '⥸', 'gtrdot' => '⋗', 'gtreqless' => '⋛', 'gtreqqless' => '⪌', 'gtrless' => '≷', 'gtrsim' => '≳', 'gvertneqq' => '≩︀', 'gvnE' => '≩︀', 'Hacek' => 'ˇ', 'hairsp' => ' ', 'half' => '½', 'hamilt' => 'ℋ', 'HARDcy' => 'Ъ', 'hardcy' => 'ъ', 'hArr' => '⇔', 'harr' => '↔', 'harrcir' => '⥈', 'harrw' => '↭', 'Hat' => '^', 'hbar' => 'ℏ', 'Hcirc' => 'Ĥ', 'hcirc' => 'ĥ', 'hearts' => '♥', 'heartsuit' => '♥', 'hellip' => '…', 'hercon' => '⊹', 'Hfr' => 'ℌ', 'hfr' => '𝔥', 'HilbertSpace' => 'ℋ', 'hksearow' => '⤥', 'hkswarow' => '⤦', 'hoarr' => '⇿', 'homtht' => '∻', 'hookleftarrow' => '↩', 'hookrightarrow' => '↪', 'Hopf' => 'ℍ', 'hopf' => '𝕙', 'horbar' => '―', 'HorizontalLine' => '─', 'Hscr' => 'ℋ', 'hscr' => '𝒽', 'hslash' => 'ℏ', 'Hstrok' => 'Ħ', 'hstrok' => 'ħ', 'HumpDownHump' => '≎', 'HumpEqual' => '≏', 'hybull' => '⁃', 'hyphen' => '‐', 'Iacute' => 'Í', 'Iacut' => 'Í', 'iacute' => 'í', 'iacut' => 'í', 'ic' => '⁣', 'Icirc' => 'Î', 'Icir' => 'Î', 'icirc' => 'î', 'icir' => 'î', 'Icy' => 'И', 'icy' => 'и', 'Idot' => 'İ', 'IEcy' => 'Е', 'iecy' => 'е', 'iexcl' => '¡', 'iexc' => '¡', 'iff' => '⇔', 'Ifr' => 'ℑ', 'ifr' => '𝔦', 'Igrave' => 'Ì', 'Igrav' => 'Ì', 'igrave' => 'ì', 'igrav' => 'ì', 'ii' => 'ⅈ', 'iiiint' => '⨌', 'iiint' => '∭', 'iinfin' => '⧜', 'iiota' => '℩', 'IJlig' => 'Ĳ', 'ijlig' => 'ĳ', 'Im' => 'ℑ', 'Imacr' => 'Ī', 'imacr' => 'ī', 'image' => 'ℑ', 'ImaginaryI' => 'ⅈ', 'imagline' => 'ℐ', 'imagpart' => 'ℑ', 'imath' => 'ı', 'imof' => '⊷', 'imped' => 'Ƶ', 'Implies' => '⇒', 'in' => '∈', 'incare' => '℅', 'infin' => '∞', 'infintie' => '⧝', 'inodot' => 'ı', 'Int' => '∬', 'int' => '∫', 'intcal' => '⊺', 'integers' => 'ℤ', 'Integral' => '∫', 'intercal' => '⊺', 'Intersection' => '⋂', 'intlarhk' => '⨗', 'intprod' => '⨼', 'InvisibleComma' => '⁣', 'InvisibleTimes' => '⁢', 'IOcy' => 'Ё', 'iocy' => 'ё', 'Iogon' => 'Į', 'iogon' => 'į', 'Iopf' => '𝕀', 'iopf' => '𝕚', 'Iota' => 'Ι', 'iota' => 'ι', 'iprod' => '⨼', 'iquest' => '¿', 'iques' => '¿', 'Iscr' => 'ℐ', 'iscr' => '𝒾', 'isin' => '∈', 'isindot' => '⋵', 'isinE' => '⋹', 'isins' => '⋴', 'isinsv' => '⋳', 'isinv' => '∈', 'it' => '⁢', 'Itilde' => 'Ĩ', 'itilde' => 'ĩ', 'Iukcy' => 'І', 'iukcy' => 'і', 'Iuml' => 'Ï', 'Ium' => 'Ï', 'iuml' => 'ï', 'ium' => 'ï', 'Jcirc' => 'Ĵ', 'jcirc' => 'ĵ', 'Jcy' => 'Й', 'jcy' => 'й', 'Jfr' => '𝔍', 'jfr' => '𝔧', 'jmath' => 'ȷ', 'Jopf' => '𝕁', 'jopf' => '𝕛', 'Jscr' => '𝒥', 'jscr' => '𝒿', 'Jsercy' => 'Ј', 'jsercy' => 'ј', 'Jukcy' => 'Є', 'jukcy' => 'є', 'Kappa' => 'Κ', 'kappa' => 'κ', 'kappav' => 'ϰ', 'Kcedil' => 'Ķ', 'kcedil' => 'ķ', 'Kcy' => 'К', 'kcy' => 'к', 'Kfr' => '𝔎', 'kfr' => '𝔨', 'kgreen' => 'ĸ', 'KHcy' => 'Х', 'khcy' => 'х', 'KJcy' => 'Ќ', 'kjcy' => 'ќ', 'Kopf' => '𝕂', 'kopf' => '𝕜', 'Kscr' => '𝒦', 'kscr' => '𝓀', 'lAarr' => '⇚', 'Lacute' => 'Ĺ', 'lacute' => 'ĺ', 'laemptyv' => '⦴', 'lagran' => 'ℒ', 'Lambda' => 'Λ', 'lambda' => 'λ', 'Lang' => '⟪', 'lang' => '⟨', 'langd' => '⦑', 'langle' => '⟨', 'lap' => '⪅', 'Laplacetrf' => 'ℒ', 'laquo' => '«', 'laqu' => '«', 'Larr' => '↞', 'lArr' => '⇐', 'larr' => '←', 'larrb' => '⇤', 'larrbfs' => '⤟', 'larrfs' => '⤝', 'larrhk' => '↩', 'larrlp' => '↫', 'larrpl' => '⤹', 'larrsim' => '⥳', 'larrtl' => '↢', 'lat' => '⪫', 'lAtail' => '⤛', 'latail' => '⤙', 'late' => '⪭', 'lates' => '⪭︀', 'lBarr' => '⤎', 'lbarr' => '⤌', 'lbbrk' => '❲', 'lbrace' => '{', 'lbrack' => '[', 'lbrke' => '⦋', 'lbrksld' => '⦏', 'lbrkslu' => '⦍', 'Lcaron' => 'Ľ', 'lcaron' => 'ľ', 'Lcedil' => 'Ļ', 'lcedil' => 'ļ', 'lceil' => '⌈', 'lcub' => '{', 'Lcy' => 'Л', 'lcy' => 'л', 'ldca' => '⤶', 'ldquo' => '“', 'ldquor' => '„', 'ldrdhar' => '⥧', 'ldrushar' => '⥋', 'ldsh' => '↲', 'lE' => '≦', 'le' => '≤', 'LeftAngleBracket' => '⟨', 'LeftArrow' => '←', 'Leftarrow' => '⇐', 'leftarrow' => '←', 'LeftArrowBar' => '⇤', 'LeftArrowRightArrow' => '⇆', 'leftarrowtail' => '↢', 'LeftCeiling' => '⌈', 'LeftDoubleBracket' => '⟦', 'LeftDownTeeVector' => '⥡', 'LeftDownVector' => '⇃', 'LeftDownVectorBar' => '⥙', 'LeftFloor' => '⌊', 'leftharpoondown' => '↽', 'leftharpoonup' => '↼', 'leftleftarrows' => '⇇', 'LeftRightArrow' => '↔', 'Leftrightarrow' => '⇔', 'leftrightarrow' => '↔', 'leftrightarrows' => '⇆', 'leftrightharpoons' => '⇋', 'leftrightsquigarrow' => '↭', 'LeftRightVector' => '⥎', 'LeftTee' => '⊣', 'LeftTeeArrow' => '↤', 'LeftTeeVector' => '⥚', 'leftthreetimes' => '⋋', 'LeftTriangle' => '⊲', 'LeftTriangleBar' => '⧏', 'LeftTriangleEqual' => '⊴', 'LeftUpDownVector' => '⥑', 'LeftUpTeeVector' => '⥠', 'LeftUpVector' => '↿', 'LeftUpVectorBar' => '⥘', 'LeftVector' => '↼', 'LeftVectorBar' => '⥒', 'lEg' => '⪋', 'leg' => '⋚', 'leq' => '≤', 'leqq' => '≦', 'leqslant' => '⩽', 'les' => '⩽', 'lescc' => '⪨', 'lesdot' => '⩿', 'lesdoto' => '⪁', 'lesdotor' => '⪃', 'lesg' => '⋚︀', 'lesges' => '⪓', 'lessapprox' => '⪅', 'lessdot' => '⋖', 'lesseqgtr' => '⋚', 'lesseqqgtr' => '⪋', 'LessEqualGreater' => '⋚', 'LessFullEqual' => '≦', 'LessGreater' => '≶', 'lessgtr' => '≶', 'LessLess' => '⪡', 'lesssim' => '≲', 'LessSlantEqual' => '⩽', 'LessTilde' => '≲', 'lfisht' => '⥼', 'lfloor' => '⌊', 'Lfr' => '𝔏', 'lfr' => '𝔩', 'lg' => '≶', 'lgE' => '⪑', 'lHar' => '⥢', 'lhard' => '↽', 'lharu' => '↼', 'lharul' => '⥪', 'lhblk' => '▄', 'LJcy' => 'Љ', 'ljcy' => 'љ', 'Ll' => '⋘', 'll' => '≪', 'llarr' => '⇇', 'llcorner' => '⌞', 'Lleftarrow' => '⇚', 'llhard' => '⥫', 'lltri' => '◺', 'Lmidot' => 'Ŀ', 'lmidot' => 'ŀ', 'lmoust' => '⎰', 'lmoustache' => '⎰', 'lnap' => '⪉', 'lnapprox' => '⪉', 'lnE' => '≨', 'lne' => '⪇', 'lneq' => '⪇', 'lneqq' => '≨', 'lnsim' => '⋦', 'loang' => '⟬', 'loarr' => '⇽', 'lobrk' => '⟦', 'LongLeftArrow' => '⟵', 'Longleftarrow' => '⟸', 'longleftarrow' => '⟵', 'LongLeftRightArrow' => '⟷', 'Longleftrightarrow' => '⟺', 'longleftrightarrow' => '⟷', 'longmapsto' => '⟼', 'LongRightArrow' => '⟶', 'Longrightarrow' => '⟹', 'longrightarrow' => '⟶', 'looparrowleft' => '↫', 'looparrowright' => '↬', 'lopar' => '⦅', 'Lopf' => '𝕃', 'lopf' => '𝕝', 'loplus' => '⨭', 'lotimes' => '⨴', 'lowast' => '∗', 'lowbar' => '_', 'LowerLeftArrow' => '↙', 'LowerRightArrow' => '↘', 'loz' => '◊', 'lozenge' => '◊', 'lozf' => '⧫', 'lpar' => '(', 'lparlt' => '⦓', 'lrarr' => '⇆', 'lrcorner' => '⌟', 'lrhar' => '⇋', 'lrhard' => '⥭', 'lrm' => '‎', 'lrtri' => '⊿', 'lsaquo' => '‹', 'Lscr' => 'ℒ', 'lscr' => '𝓁', 'Lsh' => '↰', 'lsh' => '↰', 'lsim' => '≲', 'lsime' => '⪍', 'lsimg' => '⪏', 'lsqb' => '[', 'lsquo' => '‘', 'lsquor' => '‚', 'Lstrok' => 'Ł', 'lstrok' => 'ł', 'LT' => '<', 'L' => '<', 'Lt' => '≪', 'lt' => '<', 'l' => '<', 'ltcc' => '⪦', 'ltcir' => '⩹', 'ltdot' => '⋖', 'lthree' => '⋋', 'ltimes' => '⋉', 'ltlarr' => '⥶', 'ltquest' => '⩻', 'ltri' => '◃', 'ltrie' => '⊴', 'ltrif' => '◂', 'ltrPar' => '⦖', 'lurdshar' => '⥊', 'luruhar' => '⥦', 'lvertneqq' => '≨︀', 'lvnE' => '≨︀', 'macr' => '¯', 'mac' => '¯', 'male' => '♂', 'malt' => '✠', 'maltese' => '✠', 'Map' => '⤅', 'map' => '↦', 'mapsto' => '↦', 'mapstodown' => '↧', 'mapstoleft' => '↤', 'mapstoup' => '↥', 'marker' => '▮', 'mcomma' => '⨩', 'Mcy' => 'М', 'mcy' => 'м', 'mdash' => '—', 'mDDot' => '∺', 'measuredangle' => '∡', 'MediumSpace' => ' ', 'Mellintrf' => 'ℳ', 'Mfr' => '𝔐', 'mfr' => '𝔪', 'mho' => '℧', 'micro' => 'µ', 'micr' => 'µ', 'mid' => '∣', 'midast' => '*', 'midcir' => '⫰', 'middot' => '·', 'middo' => '·', 'minus' => '−', 'minusb' => '⊟', 'minusd' => '∸', 'minusdu' => '⨪', 'MinusPlus' => '∓', 'mlcp' => '⫛', 'mldr' => '…', 'mnplus' => '∓', 'models' => '⊧', 'Mopf' => '𝕄', 'mopf' => '𝕞', 'mp' => '∓', 'Mscr' => 'ℳ', 'mscr' => '𝓂', 'mstpos' => '∾', 'Mu' => 'Μ', 'mu' => 'μ', 'multimap' => '⊸', 'mumap' => '⊸', 'nabla' => '∇', 'Nacute' => 'Ń', 'nacute' => 'ń', 'nang' => '∠⃒', 'nap' => '≉', 'napE' => '⩰̸', 'napid' => '≋̸', 'napos' => 'ŉ', 'napprox' => '≉', 'natur' => '♮', 'natural' => '♮', 'naturals' => 'ℕ', 'nbsp' => ' ', 'nbs' => ' ', 'nbump' => '≎̸', 'nbumpe' => '≏̸', 'ncap' => '⩃', 'Ncaron' => 'Ň', 'ncaron' => 'ň', 'Ncedil' => 'Ņ', 'ncedil' => 'ņ', 'ncong' => '≇', 'ncongdot' => '⩭̸', 'ncup' => '⩂', 'Ncy' => 'Н', 'ncy' => 'н', 'ndash' => '–', 'ne' => '≠', 'nearhk' => '⤤', 'neArr' => '⇗', 'nearr' => '↗', 'nearrow' => '↗', 'nedot' => '≐̸', 'NegativeMediumSpace' => '​', 'NegativeThickSpace' => '​', 'NegativeThinSpace' => '​', 'NegativeVeryThinSpace' => '​', 'nequiv' => '≢', 'nesear' => '⤨', 'nesim' => '≂̸', 'NestedGreaterGreater' => '≫', 'NestedLessLess' => '≪', 'NewLine' => '
', 'nexist' => '∄', 'nexists' => '∄', 'Nfr' => '𝔑', 'nfr' => '𝔫', 'ngE' => '≧̸', 'nge' => '≱', 'ngeq' => '≱', 'ngeqq' => '≧̸', 'ngeqslant' => '⩾̸', 'nges' => '⩾̸', 'nGg' => '⋙̸', 'ngsim' => '≵', 'nGt' => '≫⃒', 'ngt' => '≯', 'ngtr' => '≯', 'nGtv' => '≫̸', 'nhArr' => '⇎', 'nharr' => '↮', 'nhpar' => '⫲', 'ni' => '∋', 'nis' => '⋼', 'nisd' => '⋺', 'niv' => '∋', 'NJcy' => 'Њ', 'njcy' => 'њ', 'nlArr' => '⇍', 'nlarr' => '↚', 'nldr' => '‥', 'nlE' => '≦̸', 'nle' => '≰', 'nLeftarrow' => '⇍', 'nleftarrow' => '↚', 'nLeftrightarrow' => '⇎', 'nleftrightarrow' => '↮', 'nleq' => '≰', 'nleqq' => '≦̸', 'nleqslant' => '⩽̸', 'nles' => '⩽̸', 'nless' => '≮', 'nLl' => '⋘̸', 'nlsim' => '≴', 'nLt' => '≪⃒', 'nlt' => '≮', 'nltri' => '⋪', 'nltrie' => '⋬', 'nLtv' => '≪̸', 'nmid' => '∤', 'NoBreak' => '⁠', 'NonBreakingSpace' => ' ', 'Nopf' => 'ℕ', 'nopf' => '𝕟', 'Not' => '⫬', 'not' => '¬', 'no' => '¬', 'NotCongruent' => '≢', 'NotCupCap' => '≭', 'NotDoubleVerticalBar' => '∦', 'NotElement' => '∉', 'NotEqual' => '≠', 'NotEqualTilde' => '≂̸', 'NotExists' => '∄', 'NotGreater' => '≯', 'NotGreaterEqual' => '≱', 'NotGreaterFullEqual' => '≧̸', 'NotGreaterGreater' => '≫̸', 'NotGreaterLess' => '≹', 'NotGreaterSlantEqual' => '⩾̸', 'NotGreaterTilde' => '≵', 'NotHumpDownHump' => '≎̸', 'NotHumpEqual' => '≏̸', 'notin' => '∉', 'notindot' => '⋵̸', 'notinE' => '⋹̸', 'notinva' => '∉', 'notinvb' => '⋷', 'notinvc' => '⋶', 'NotLeftTriangle' => '⋪', 'NotLeftTriangleBar' => '⧏̸', 'NotLeftTriangleEqual' => '⋬', 'NotLess' => '≮', 'NotLessEqual' => '≰', 'NotLessGreater' => '≸', 'NotLessLess' => '≪̸', 'NotLessSlantEqual' => '⩽̸', 'NotLessTilde' => '≴', 'NotNestedGreaterGreater' => '⪢̸', 'NotNestedLessLess' => '⪡̸', 'notni' => '∌', 'notniva' => '∌', 'notnivb' => '⋾', 'notnivc' => '⋽', 'NotPrecedes' => '⊀', 'NotPrecedesEqual' => '⪯̸', 'NotPrecedesSlantEqual' => '⋠', 'NotReverseElement' => '∌', 'NotRightTriangle' => '⋫', 'NotRightTriangleBar' => '⧐̸', 'NotRightTriangleEqual' => '⋭', 'NotSquareSubset' => '⊏̸', 'NotSquareSubsetEqual' => '⋢', 'NotSquareSuperset' => '⊐̸', 'NotSquareSupersetEqual' => '⋣', 'NotSubset' => '⊂⃒', 'NotSubsetEqual' => '⊈', 'NotSucceeds' => '⊁', 'NotSucceedsEqual' => '⪰̸', 'NotSucceedsSlantEqual' => '⋡', 'NotSucceedsTilde' => '≿̸', 'NotSuperset' => '⊃⃒', 'NotSupersetEqual' => '⊉', 'NotTilde' => '≁', 'NotTildeEqual' => '≄', 'NotTildeFullEqual' => '≇', 'NotTildeTilde' => '≉', 'NotVerticalBar' => '∤', 'npar' => '∦', 'nparallel' => '∦', 'nparsl' => '⫽⃥', 'npart' => '∂̸', 'npolint' => '⨔', 'npr' => '⊀', 'nprcue' => '⋠', 'npre' => '⪯̸', 'nprec' => '⊀', 'npreceq' => '⪯̸', 'nrArr' => '⇏', 'nrarr' => '↛', 'nrarrc' => '⤳̸', 'nrarrw' => '↝̸', 'nRightarrow' => '⇏', 'nrightarrow' => '↛', 'nrtri' => '⋫', 'nrtrie' => '⋭', 'nsc' => '⊁', 'nsccue' => '⋡', 'nsce' => '⪰̸', 'Nscr' => '𝒩', 'nscr' => '𝓃', 'nshortmid' => '∤', 'nshortparallel' => '∦', 'nsim' => '≁', 'nsime' => '≄', 'nsimeq' => '≄', 'nsmid' => '∤', 'nspar' => '∦', 'nsqsube' => '⋢', 'nsqsupe' => '⋣', 'nsub' => '⊄', 'nsubE' => '⫅̸', 'nsube' => '⊈', 'nsubset' => '⊂⃒', 'nsubseteq' => '⊈', 'nsubseteqq' => '⫅̸', 'nsucc' => '⊁', 'nsucceq' => '⪰̸', 'nsup' => '⊅', 'nsupE' => '⫆̸', 'nsupe' => '⊉', 'nsupset' => '⊃⃒', 'nsupseteq' => '⊉', 'nsupseteqq' => '⫆̸', 'ntgl' => '≹', 'Ntilde' => 'Ñ', 'Ntild' => 'Ñ', 'ntilde' => 'ñ', 'ntild' => 'ñ', 'ntlg' => '≸', 'ntriangleleft' => '⋪', 'ntrianglelefteq' => '⋬', 'ntriangleright' => '⋫', 'ntrianglerighteq' => '⋭', 'Nu' => 'Ν', 'nu' => 'ν', 'num' => '#', 'numero' => '№', 'numsp' => ' ', 'nvap' => '≍⃒', 'nVDash' => '⊯', 'nVdash' => '⊮', 'nvDash' => '⊭', 'nvdash' => '⊬', 'nvge' => '≥⃒', 'nvgt' => '>⃒', 'nvHarr' => '⤄', 'nvinfin' => '⧞', 'nvlArr' => '⤂', 'nvle' => '≤⃒', 'nvlt' => '<⃒', 'nvltrie' => '⊴⃒', 'nvrArr' => '⤃', 'nvrtrie' => '⊵⃒', 'nvsim' => '∼⃒', 'nwarhk' => '⤣', 'nwArr' => '⇖', 'nwarr' => '↖', 'nwarrow' => '↖', 'nwnear' => '⤧', 'Oacute' => 'Ó', 'Oacut' => 'Ó', 'oacute' => 'ó', 'oacut' => 'ó', 'oast' => '⊛', 'ocir' => 'ô', 'Ocirc' => 'Ô', 'Ocir' => 'Ô', 'ocirc' => 'ô', 'Ocy' => 'О', 'ocy' => 'о', 'odash' => '⊝', 'Odblac' => 'Ő', 'odblac' => 'ő', 'odiv' => '⨸', 'odot' => '⊙', 'odsold' => '⦼', 'OElig' => 'Œ', 'oelig' => 'œ', 'ofcir' => '⦿', 'Ofr' => '𝔒', 'ofr' => '𝔬', 'ogon' => '˛', 'Ograve' => 'Ò', 'Ograv' => 'Ò', 'ograve' => 'ò', 'ograv' => 'ò', 'ogt' => '⧁', 'ohbar' => '⦵', 'ohm' => 'Ω', 'oint' => '∮', 'olarr' => '↺', 'olcir' => '⦾', 'olcross' => '⦻', 'oline' => '‾', 'olt' => '⧀', 'Omacr' => 'Ō', 'omacr' => 'ō', 'Omega' => 'Ω', 'omega' => 'ω', 'Omicron' => 'Ο', 'omicron' => 'ο', 'omid' => '⦶', 'ominus' => '⊖', 'Oopf' => '𝕆', 'oopf' => '𝕠', 'opar' => '⦷', 'OpenCurlyDoubleQuote' => '“', 'OpenCurlyQuote' => '‘', 'operp' => '⦹', 'oplus' => '⊕', 'Or' => '⩔', 'or' => '∨', 'orarr' => '↻', 'ord' => 'º', 'order' => 'ℴ', 'orderof' => 'ℴ', 'ordf' => 'ª', 'ordm' => 'º', 'origof' => '⊶', 'oror' => '⩖', 'orslope' => '⩗', 'orv' => '⩛', 'oS' => 'Ⓢ', 'Oscr' => '𝒪', 'oscr' => 'ℴ', 'Oslash' => 'Ø', 'Oslas' => 'Ø', 'oslash' => 'ø', 'oslas' => 'ø', 'osol' => '⊘', 'Otilde' => 'Õ', 'Otild' => 'Õ', 'otilde' => 'õ', 'otild' => 'õ', 'Otimes' => '⨷', 'otimes' => '⊗', 'otimesas' => '⨶', 'Ouml' => 'Ö', 'Oum' => 'Ö', 'ouml' => 'ö', 'oum' => 'ö', 'ovbar' => '⌽', 'OverBar' => '‾', 'OverBrace' => '⏞', 'OverBracket' => '⎴', 'OverParenthesis' => '⏜', 'par' => '¶', 'para' => '¶', 'parallel' => '∥', 'parsim' => '⫳', 'parsl' => '⫽', 'part' => '∂', 'PartialD' => '∂', 'Pcy' => 'П', 'pcy' => 'п', 'percnt' => '%', 'period' => '.', 'permil' => '‰', 'perp' => '⊥', 'pertenk' => '‱', 'Pfr' => '𝔓', 'pfr' => '𝔭', 'Phi' => 'Φ', 'phi' => 'φ', 'phiv' => 'ϕ', 'phmmat' => 'ℳ', 'phone' => '☎', 'Pi' => 'Π', 'pi' => 'π', 'pitchfork' => '⋔', 'piv' => 'ϖ', 'planck' => 'ℏ', 'planckh' => 'ℎ', 'plankv' => 'ℏ', 'plus' => '+', 'plusacir' => '⨣', 'plusb' => '⊞', 'pluscir' => '⨢', 'plusdo' => '∔', 'plusdu' => '⨥', 'pluse' => '⩲', 'PlusMinus' => '±', 'plusmn' => '±', 'plusm' => '±', 'plussim' => '⨦', 'plustwo' => '⨧', 'pm' => '±', 'Poincareplane' => 'ℌ', 'pointint' => '⨕', 'Popf' => 'ℙ', 'popf' => '𝕡', 'pound' => '£', 'poun' => '£', 'Pr' => '⪻', 'pr' => '≺', 'prap' => '⪷', 'prcue' => '≼', 'prE' => '⪳', 'pre' => '⪯', 'prec' => '≺', 'precapprox' => '⪷', 'preccurlyeq' => '≼', 'Precedes' => '≺', 'PrecedesEqual' => '⪯', 'PrecedesSlantEqual' => '≼', 'PrecedesTilde' => '≾', 'preceq' => '⪯', 'precnapprox' => '⪹', 'precneqq' => '⪵', 'precnsim' => '⋨', 'precsim' => '≾', 'Prime' => '″', 'prime' => '′', 'primes' => 'ℙ', 'prnap' => '⪹', 'prnE' => '⪵', 'prnsim' => '⋨', 'prod' => '∏', 'Product' => '∏', 'profalar' => '⌮', 'profline' => '⌒', 'profsurf' => '⌓', 'prop' => '∝', 'Proportion' => '∷', 'Proportional' => '∝', 'propto' => '∝', 'prsim' => '≾', 'prurel' => '⊰', 'Pscr' => '𝒫', 'pscr' => '𝓅', 'Psi' => 'Ψ', 'psi' => 'ψ', 'puncsp' => ' ', 'Qfr' => '𝔔', 'qfr' => '𝔮', 'qint' => '⨌', 'Qopf' => 'ℚ', 'qopf' => '𝕢', 'qprime' => '⁗', 'Qscr' => '𝒬', 'qscr' => '𝓆', 'quaternions' => 'ℍ', 'quatint' => '⨖', 'quest' => '?', 'questeq' => '≟', 'QUOT' => '"', 'QUO' => '"', 'quot' => '"', 'quo' => '"', 'rAarr' => '⇛', 'race' => '∽̱', 'Racute' => 'Ŕ', 'racute' => 'ŕ', 'radic' => '√', 'raemptyv' => '⦳', 'Rang' => '⟫', 'rang' => '⟩', 'rangd' => '⦒', 'range' => '⦥', 'rangle' => '⟩', 'raquo' => '»', 'raqu' => '»', 'Rarr' => '↠', 'rArr' => '⇒', 'rarr' => '→', 'rarrap' => '⥵', 'rarrb' => '⇥', 'rarrbfs' => '⤠', 'rarrc' => '⤳', 'rarrfs' => '⤞', 'rarrhk' => '↪', 'rarrlp' => '↬', 'rarrpl' => '⥅', 'rarrsim' => '⥴', 'Rarrtl' => '⤖', 'rarrtl' => '↣', 'rarrw' => '↝', 'rAtail' => '⤜', 'ratail' => '⤚', 'ratio' => '∶', 'rationals' => 'ℚ', 'RBarr' => '⤐', 'rBarr' => '⤏', 'rbarr' => '⤍', 'rbbrk' => '❳', 'rbrace' => '}', 'rbrack' => ']', 'rbrke' => '⦌', 'rbrksld' => '⦎', 'rbrkslu' => '⦐', 'Rcaron' => 'Ř', 'rcaron' => 'ř', 'Rcedil' => 'Ŗ', 'rcedil' => 'ŗ', 'rceil' => '⌉', 'rcub' => '}', 'Rcy' => 'Р', 'rcy' => 'р', 'rdca' => '⤷', 'rdldhar' => '⥩', 'rdquo' => '”', 'rdquor' => '”', 'rdsh' => '↳', 'Re' => 'ℜ', 'real' => 'ℜ', 'realine' => 'ℛ', 'realpart' => 'ℜ', 'reals' => 'ℝ', 'rect' => '▭', 'REG' => '®', 'RE' => '®', 'reg' => '®', 're' => '®', 'ReverseElement' => '∋', 'ReverseEquilibrium' => '⇋', 'ReverseUpEquilibrium' => '⥯', 'rfisht' => '⥽', 'rfloor' => '⌋', 'Rfr' => 'ℜ', 'rfr' => '𝔯', 'rHar' => '⥤', 'rhard' => '⇁', 'rharu' => '⇀', 'rharul' => '⥬', 'Rho' => 'Ρ', 'rho' => 'ρ', 'rhov' => 'ϱ', 'RightAngleBracket' => '⟩', 'RightArrow' => '→', 'Rightarrow' => '⇒', 'rightarrow' => '→', 'RightArrowBar' => '⇥', 'RightArrowLeftArrow' => '⇄', 'rightarrowtail' => '↣', 'RightCeiling' => '⌉', 'RightDoubleBracket' => '⟧', 'RightDownTeeVector' => '⥝', 'RightDownVector' => '⇂', 'RightDownVectorBar' => '⥕', 'RightFloor' => '⌋', 'rightharpoondown' => '⇁', 'rightharpoonup' => '⇀', 'rightleftarrows' => '⇄', 'rightleftharpoons' => '⇌', 'rightrightarrows' => '⇉', 'rightsquigarrow' => '↝', 'RightTee' => '⊢', 'RightTeeArrow' => '↦', 'RightTeeVector' => '⥛', 'rightthreetimes' => '⋌', 'RightTriangle' => '⊳', 'RightTriangleBar' => '⧐', 'RightTriangleEqual' => '⊵', 'RightUpDownVector' => '⥏', 'RightUpTeeVector' => '⥜', 'RightUpVector' => '↾', 'RightUpVectorBar' => '⥔', 'RightVector' => '⇀', 'RightVectorBar' => '⥓', 'ring' => '˚', 'risingdotseq' => '≓', 'rlarr' => '⇄', 'rlhar' => '⇌', 'rlm' => '‏', 'rmoust' => '⎱', 'rmoustache' => '⎱', 'rnmid' => '⫮', 'roang' => '⟭', 'roarr' => '⇾', 'robrk' => '⟧', 'ropar' => '⦆', 'Ropf' => 'ℝ', 'ropf' => '𝕣', 'roplus' => '⨮', 'rotimes' => '⨵', 'RoundImplies' => '⥰', 'rpar' => ')', 'rpargt' => '⦔', 'rppolint' => '⨒', 'rrarr' => '⇉', 'Rrightarrow' => '⇛', 'rsaquo' => '›', 'Rscr' => 'ℛ', 'rscr' => '𝓇', 'Rsh' => '↱', 'rsh' => '↱', 'rsqb' => ']', 'rsquo' => '’', 'rsquor' => '’', 'rthree' => '⋌', 'rtimes' => '⋊', 'rtri' => '▹', 'rtrie' => '⊵', 'rtrif' => '▸', 'rtriltri' => '⧎', 'RuleDelayed' => '⧴', 'ruluhar' => '⥨', 'rx' => '℞', 'Sacute' => 'Ś', 'sacute' => 'ś', 'sbquo' => '‚', 'Sc' => '⪼', 'sc' => '≻', 'scap' => '⪸', 'Scaron' => 'Š', 'scaron' => 'š', 'sccue' => '≽', 'scE' => '⪴', 'sce' => '⪰', 'Scedil' => 'Ş', 'scedil' => 'ş', 'Scirc' => 'Ŝ', 'scirc' => 'ŝ', 'scnap' => '⪺', 'scnE' => '⪶', 'scnsim' => '⋩', 'scpolint' => '⨓', 'scsim' => '≿', 'Scy' => 'С', 'scy' => 'с', 'sdot' => '⋅', 'sdotb' => '⊡', 'sdote' => '⩦', 'searhk' => '⤥', 'seArr' => '⇘', 'searr' => '↘', 'searrow' => '↘', 'sect' => '§', 'sec' => '§', 'semi' => ';', 'seswar' => '⤩', 'setminus' => '∖', 'setmn' => '∖', 'sext' => '✶', 'Sfr' => '𝔖', 'sfr' => '𝔰', 'sfrown' => '⌢', 'sharp' => '♯', 'SHCHcy' => 'Щ', 'shchcy' => 'щ', 'SHcy' => 'Ш', 'shcy' => 'ш', 'ShortDownArrow' => '↓', 'ShortLeftArrow' => '←', 'shortmid' => '∣', 'shortparallel' => '∥', 'ShortRightArrow' => '→', 'ShortUpArrow' => '↑', 'shy' => '­', 'sh' => '­', 'Sigma' => 'Σ', 'sigma' => 'σ', 'sigmaf' => 'ς', 'sigmav' => 'ς', 'sim' => '∼', 'simdot' => '⩪', 'sime' => '≃', 'simeq' => '≃', 'simg' => '⪞', 'simgE' => '⪠', 'siml' => '⪝', 'simlE' => '⪟', 'simne' => '≆', 'simplus' => '⨤', 'simrarr' => '⥲', 'slarr' => '←', 'SmallCircle' => '∘', 'smallsetminus' => '∖', 'smashp' => '⨳', 'smeparsl' => '⧤', 'smid' => '∣', 'smile' => '⌣', 'smt' => '⪪', 'smte' => '⪬', 'smtes' => '⪬︀', 'SOFTcy' => 'Ь', 'softcy' => 'ь', 'sol' => '/', 'solb' => '⧄', 'solbar' => '⌿', 'Sopf' => '𝕊', 'sopf' => '𝕤', 'spades' => '♠', 'spadesuit' => '♠', 'spar' => '∥', 'sqcap' => '⊓', 'sqcaps' => '⊓︀', 'sqcup' => '⊔', 'sqcups' => '⊔︀', 'Sqrt' => '√', 'sqsub' => '⊏', 'sqsube' => '⊑', 'sqsubset' => '⊏', 'sqsubseteq' => '⊑', 'sqsup' => '⊐', 'sqsupe' => '⊒', 'sqsupset' => '⊐', 'sqsupseteq' => '⊒', 'squ' => '□', 'Square' => '□', 'square' => '□', 'SquareIntersection' => '⊓', 'SquareSubset' => '⊏', 'SquareSubsetEqual' => '⊑', 'SquareSuperset' => '⊐', 'SquareSupersetEqual' => '⊒', 'SquareUnion' => '⊔', 'squarf' => '▪', 'squf' => '▪', 'srarr' => '→', 'Sscr' => '𝒮', 'sscr' => '𝓈', 'ssetmn' => '∖', 'ssmile' => '⌣', 'sstarf' => '⋆', 'Star' => '⋆', 'star' => '☆', 'starf' => '★', 'straightepsilon' => 'ϵ', 'straightphi' => 'ϕ', 'strns' => '¯', 'Sub' => '⋐', 'sub' => '⊂', 'subdot' => '⪽', 'subE' => '⫅', 'sube' => '⊆', 'subedot' => '⫃', 'submult' => '⫁', 'subnE' => '⫋', 'subne' => '⊊', 'subplus' => '⪿', 'subrarr' => '⥹', 'Subset' => '⋐', 'subset' => '⊂', 'subseteq' => '⊆', 'subseteqq' => '⫅', 'SubsetEqual' => '⊆', 'subsetneq' => '⊊', 'subsetneqq' => '⫋', 'subsim' => '⫇', 'subsub' => '⫕', 'subsup' => '⫓', 'succ' => '≻', 'succapprox' => '⪸', 'succcurlyeq' => '≽', 'Succeeds' => '≻', 'SucceedsEqual' => '⪰', 'SucceedsSlantEqual' => '≽', 'SucceedsTilde' => '≿', 'succeq' => '⪰', 'succnapprox' => '⪺', 'succneqq' => '⪶', 'succnsim' => '⋩', 'succsim' => '≿', 'SuchThat' => '∋', 'Sum' => '∑', 'sum' => '∑', 'sung' => '♪', 'Sup' => '⋑', 'sup' => '³', 'sup1' => '¹', 'sup2' => '²', 'sup3' => '³', 'supdot' => '⪾', 'supdsub' => '⫘', 'supE' => '⫆', 'supe' => '⊇', 'supedot' => '⫄', 'Superset' => '⊃', 'SupersetEqual' => '⊇', 'suphsol' => '⟉', 'suphsub' => '⫗', 'suplarr' => '⥻', 'supmult' => '⫂', 'supnE' => '⫌', 'supne' => '⊋', 'supplus' => '⫀', 'Supset' => '⋑', 'supset' => '⊃', 'supseteq' => '⊇', 'supseteqq' => '⫆', 'supsetneq' => '⊋', 'supsetneqq' => '⫌', 'supsim' => '⫈', 'supsub' => '⫔', 'supsup' => '⫖', 'swarhk' => '⤦', 'swArr' => '⇙', 'swarr' => '↙', 'swarrow' => '↙', 'swnwar' => '⤪', 'szlig' => 'ß', 'szli' => 'ß', 'Tab' => '	', 'target' => '⌖', 'Tau' => 'Τ', 'tau' => 'τ', 'tbrk' => '⎴', 'Tcaron' => 'Ť', 'tcaron' => 'ť', 'Tcedil' => 'Ţ', 'tcedil' => 'ţ', 'Tcy' => 'Т', 'tcy' => 'т', 'tdot' => '⃛', 'telrec' => '⌕', 'Tfr' => '𝔗', 'tfr' => '𝔱', 'there4' => '∴', 'Therefore' => '∴', 'therefore' => '∴', 'Theta' => 'Θ', 'theta' => 'θ', 'thetasym' => 'ϑ', 'thetav' => 'ϑ', 'thickapprox' => '≈', 'thicksim' => '∼', 'ThickSpace' => '  ', 'thinsp' => ' ', 'ThinSpace' => ' ', 'thkap' => '≈', 'thksim' => '∼', 'THORN' => 'Þ', 'THOR' => 'Þ', 'thorn' => 'þ', 'thor' => 'þ', 'Tilde' => '∼', 'tilde' => '˜', 'TildeEqual' => '≃', 'TildeFullEqual' => '≅', 'TildeTilde' => '≈', 'times' => '×', 'time' => '×', 'timesb' => '⊠', 'timesbar' => '⨱', 'timesd' => '⨰', 'tint' => '∭', 'toea' => '⤨', 'top' => '⊤', 'topbot' => '⌶', 'topcir' => '⫱', 'Topf' => '𝕋', 'topf' => '𝕥', 'topfork' => '⫚', 'tosa' => '⤩', 'tprime' => '‴', 'TRADE' => '™', 'trade' => '™', 'triangle' => '▵', 'triangledown' => '▿', 'triangleleft' => '◃', 'trianglelefteq' => '⊴', 'triangleq' => '≜', 'triangleright' => '▹', 'trianglerighteq' => '⊵', 'tridot' => '◬', 'trie' => '≜', 'triminus' => '⨺', 'TripleDot' => '⃛', 'triplus' => '⨹', 'trisb' => '⧍', 'tritime' => '⨻', 'trpezium' => '⏢', 'Tscr' => '𝒯', 'tscr' => '𝓉', 'TScy' => 'Ц', 'tscy' => 'ц', 'TSHcy' => 'Ћ', 'tshcy' => 'ћ', 'Tstrok' => 'Ŧ', 'tstrok' => 'ŧ', 'twixt' => '≬', 'twoheadleftarrow' => '↞', 'twoheadrightarrow' => '↠', 'Uacute' => 'Ú', 'Uacut' => 'Ú', 'uacute' => 'ú', 'uacut' => 'ú', 'Uarr' => '↟', 'uArr' => '⇑', 'uarr' => '↑', 'Uarrocir' => '⥉', 'Ubrcy' => 'Ў', 'ubrcy' => 'ў', 'Ubreve' => 'Ŭ', 'ubreve' => 'ŭ', 'Ucirc' => 'Û', 'Ucir' => 'Û', 'ucirc' => 'û', 'ucir' => 'û', 'Ucy' => 'У', 'ucy' => 'у', 'udarr' => '⇅', 'Udblac' => 'Ű', 'udblac' => 'ű', 'udhar' => '⥮', 'ufisht' => '⥾', 'Ufr' => '𝔘', 'ufr' => '𝔲', 'Ugrave' => 'Ù', 'Ugrav' => 'Ù', 'ugrave' => 'ù', 'ugrav' => 'ù', 'uHar' => '⥣', 'uharl' => '↿', 'uharr' => '↾', 'uhblk' => '▀', 'ulcorn' => '⌜', 'ulcorner' => '⌜', 'ulcrop' => '⌏', 'ultri' => '◸', 'Umacr' => 'Ū', 'umacr' => 'ū', 'uml' => '¨', 'um' => '¨', 'UnderBar' => '_', 'UnderBrace' => '⏟', 'UnderBracket' => '⎵', 'UnderParenthesis' => '⏝', 'Union' => '⋃', 'UnionPlus' => '⊎', 'Uogon' => 'Ų', 'uogon' => 'ų', 'Uopf' => '𝕌', 'uopf' => '𝕦', 'UpArrow' => '↑', 'Uparrow' => '⇑', 'uparrow' => '↑', 'UpArrowBar' => '⤒', 'UpArrowDownArrow' => '⇅', 'UpDownArrow' => '↕', 'Updownarrow' => '⇕', 'updownarrow' => '↕', 'UpEquilibrium' => '⥮', 'upharpoonleft' => '↿', 'upharpoonright' => '↾', 'uplus' => '⊎', 'UpperLeftArrow' => '↖', 'UpperRightArrow' => '↗', 'Upsi' => 'ϒ', 'upsi' => 'υ', 'upsih' => 'ϒ', 'Upsilon' => 'Υ', 'upsilon' => 'υ', 'UpTee' => '⊥', 'UpTeeArrow' => '↥', 'upuparrows' => '⇈', 'urcorn' => '⌝', 'urcorner' => '⌝', 'urcrop' => '⌎', 'Uring' => 'Ů', 'uring' => 'ů', 'urtri' => '◹', 'Uscr' => '𝒰', 'uscr' => '𝓊', 'utdot' => '⋰', 'Utilde' => 'Ũ', 'utilde' => 'ũ', 'utri' => '▵', 'utrif' => '▴', 'uuarr' => '⇈', 'Uuml' => 'Ü', 'Uum' => 'Ü', 'uuml' => 'ü', 'uum' => 'ü', 'uwangle' => '⦧', 'vangrt' => '⦜', 'varepsilon' => 'ϵ', 'varkappa' => 'ϰ', 'varnothing' => '∅', 'varphi' => 'ϕ', 'varpi' => 'ϖ', 'varpropto' => '∝', 'vArr' => '⇕', 'varr' => '↕', 'varrho' => 'ϱ', 'varsigma' => 'ς', 'varsubsetneq' => '⊊︀', 'varsubsetneqq' => '⫋︀', 'varsupsetneq' => '⊋︀', 'varsupsetneqq' => '⫌︀', 'vartheta' => 'ϑ', 'vartriangleleft' => '⊲', 'vartriangleright' => '⊳', 'Vbar' => '⫫', 'vBar' => '⫨', 'vBarv' => '⫩', 'Vcy' => 'В', 'vcy' => 'в', 'VDash' => '⊫', 'Vdash' => '⊩', 'vDash' => '⊨', 'vdash' => '⊢', 'Vdashl' => '⫦', 'Vee' => '⋁', 'vee' => '∨', 'veebar' => '⊻', 'veeeq' => '≚', 'vellip' => '⋮', 'Verbar' => '‖', 'verbar' => '|', 'Vert' => '‖', 'vert' => '|', 'VerticalBar' => '∣', 'VerticalLine' => '|', 'VerticalSeparator' => '❘', 'VerticalTilde' => '≀', 'VeryThinSpace' => ' ', 'Vfr' => '𝔙', 'vfr' => '𝔳', 'vltri' => '⊲', 'vnsub' => '⊂⃒', 'vnsup' => '⊃⃒', 'Vopf' => '𝕍', 'vopf' => '𝕧', 'vprop' => '∝', 'vrtri' => '⊳', 'Vscr' => '𝒱', 'vscr' => '𝓋', 'vsubnE' => '⫋︀', 'vsubne' => '⊊︀', 'vsupnE' => '⫌︀', 'vsupne' => '⊋︀', 'Vvdash' => '⊪', 'vzigzag' => '⦚', 'Wcirc' => 'Ŵ', 'wcirc' => 'ŵ', 'wedbar' => '⩟', 'Wedge' => '⋀', 'wedge' => '∧', 'wedgeq' => '≙', 'weierp' => '℘', 'Wfr' => '𝔚', 'wfr' => '𝔴', 'Wopf' => '𝕎', 'wopf' => '𝕨', 'wp' => '℘', 'wr' => '≀', 'wreath' => '≀', 'Wscr' => '𝒲', 'wscr' => '𝓌', 'xcap' => '⋂', 'xcirc' => '◯', 'xcup' => '⋃', 'xdtri' => '▽', 'Xfr' => '𝔛', 'xfr' => '𝔵', 'xhArr' => '⟺', 'xharr' => '⟷', 'Xi' => 'Ξ', 'xi' => 'ξ', 'xlArr' => '⟸', 'xlarr' => '⟵', 'xmap' => '⟼', 'xnis' => '⋻', 'xodot' => '⨀', 'Xopf' => '𝕏', 'xopf' => '𝕩', 'xoplus' => '⨁', 'xotime' => '⨂', 'xrArr' => '⟹', 'xrarr' => '⟶', 'Xscr' => '𝒳', 'xscr' => '𝓍', 'xsqcup' => '⨆', 'xuplus' => '⨄', 'xutri' => '△', 'xvee' => '⋁', 'xwedge' => '⋀', 'Yacute' => 'Ý', 'Yacut' => 'Ý', 'yacute' => 'ý', 'yacut' => 'ý', 'YAcy' => 'Я', 'yacy' => 'я', 'Ycirc' => 'Ŷ', 'ycirc' => 'ŷ', 'Ycy' => 'Ы', 'ycy' => 'ы', 'yen' => '¥', 'ye' => '¥', 'Yfr' => '𝔜', 'yfr' => '𝔶', 'YIcy' => 'Ї', 'yicy' => 'ї', 'Yopf' => '𝕐', 'yopf' => '𝕪', 'Yscr' => '𝒴', 'yscr' => '𝓎', 'YUcy' => 'Ю', 'yucy' => 'ю', 'Yuml' => 'Ÿ', 'yuml' => 'ÿ', 'yum' => 'ÿ', 'Zacute' => 'Ź', 'zacute' => 'ź', 'Zcaron' => 'Ž', 'zcaron' => 'ž', 'Zcy' => 'З', 'zcy' => 'з', 'Zdot' => 'Ż', 'zdot' => 'ż', 'zeetrf' => 'ℨ', 'ZeroWidthSpace' => '​', 'Zeta' => 'Ζ', 'zeta' => 'ζ', 'Zfr' => 'ℨ', 'zfr' => '𝔷', 'ZHcy' => 'Ж', 'zhcy' => 'ж', 'zigrarr' => '⇝', 'Zopf' => 'ℤ', 'zopf' => '𝕫', 'Zscr' => '𝒵', 'zscr' => '𝓏', 'zwj' => '‍', 'zwnj' => '‌', ); } namespace AimySpeedOptimization\Masterminds\HTML5; class Exception extends \Exception { } namespace AimySpeedOptimization\Masterminds\HTML5; interface InstructionProcessor { public function process(\DOMElement $element, $name, $data); } namespace AimySpeedOptimization\Masterminds\HTML5\Parser; use AimySpeedOptimization\Masterminds\HTML5\Elements; class Tokenizer { protected $scanner; protected $events; protected $tok; protected $text = ''; protected $carryOn = true; protected $textMode = 0; protected $untilTag = null; const CONFORMANT_XML = 'xml'; const CONFORMANT_HTML = 'html'; protected $mode = self::CONFORMANT_HTML; public function __construct($scanner, $eventHandler, $mode = self::CONFORMANT_HTML) { $this->scanner = $scanner; $this->events = $eventHandler; $this->mode = $mode; } public function parse() { do { $this->consumeData(); } while ($this->carryOn); } public function setTextMode($textmode, $untilTag = null) { $this->textMode = $textmode & (Elements::TEXT_RAW | Elements::TEXT_RCDATA); $this->untilTag = $untilTag; } protected function consumeData() { $tok = $this->scanner->current(); if ('&' === $tok) { $ref = $this->decodeCharacterReference(); $this->buffer($ref); $tok = $this->scanner->current(); } if ('<' === $tok) { $this->flushBuffer(); $tok = $this->scanner->next(); if (false === $tok) { $this->parseError('Illegal tag opening'); } elseif ('!' === $tok) { $this->markupDeclaration(); } elseif ('/' === $tok) { $this->endTag(); } elseif ('?' === $tok) { $this->processingInstruction(); } elseif ($this->is_alpha($tok)) { $this->tagName(); } else { $this->parseError('Illegal tag opening'); $this->characterData(); } $tok = $this->scanner->current(); } if (false === $tok) { $this->eof(); } else { switch ($this->textMode) { case Elements::TEXT_RAW: $this->rawText($tok); break; case Elements::TEXT_RCDATA: $this->rcdata($tok); break; default: if ('<' === $tok || '&' === $tok) { break; } if ("\00" === $tok) { $this->parseError('Received null character.'); $this->text .= $tok; $this->scanner->consume(); break; } $this->text .= $this->scanner->charsUntil("<&\0"); } } return $this->carryOn; } protected function characterData() { $tok = $this->scanner->current(); if (false === $tok) { return false; } switch ($this->textMode) { case Elements::TEXT_RAW: return $this->rawText($tok); case Elements::TEXT_RCDATA: return $this->rcdata($tok); default: if ('<' === $tok || '&' === $tok) { return false; } return $this->text($tok); } } protected function text($tok) { if (false === $tok) { return false; } if ("\00" === $tok) { $this->parseError('Received null character.'); } $this->buffer($tok); $this->scanner->consume(); return true; } protected function rawText($tok) { if (is_null($this->untilTag)) { return $this->text($tok); } $sequence = '</' . $this->untilTag . '>'; $txt = $this->readUntilSequence($sequence); $this->events->text($txt); $this->setTextMode(0); return $this->endTag(); } protected function rcdata($tok) { if (is_null($this->untilTag)) { return $this->text($tok); } $sequence = '</' . $this->untilTag; $txt = ''; $caseSensitive = !Elements::isHtml5Element($this->untilTag); while (false !== $tok && !('<' == $tok && ($this->scanner->sequenceMatches($sequence, $caseSensitive)))) { if ('&' == $tok) { $txt .= $this->decodeCharacterReference(); $tok = $this->scanner->current(); } else { $txt .= $tok; $tok = $this->scanner->next(); } } $len = strlen($sequence); $this->scanner->consume($len); $len += $this->scanner->whitespace(); if ('>' !== $this->scanner->current()) { $this->parseError('Unclosed RCDATA end tag'); } $this->scanner->unconsume($len); $this->events->text($txt); $this->setTextMode(0); return $this->endTag(); } protected function eof() { $this->flushBuffer(); $this->events->eof(); $this->carryOn = false; } protected function markupDeclaration() { $tok = $this->scanner->next(); if ('-' == $tok && '-' == $this->scanner->peek()) { $this->scanner->consume(2); return $this->comment(); } elseif ('D' == $tok || 'd' == $tok) { return $this->doctype(); } elseif ('[' == $tok) { return $this->cdataSection(); } $this->parseError('Expected <!--, <![CDATA[, or <!DOCTYPE. Got <!%s', $tok); $this->bogusComment('<!'); return true; } protected function endTag() { if ('/' != $this->scanner->current()) { return false; } $tok = $this->scanner->next(); if (!$this->is_alpha($tok)) { $this->parseError("Expected tag name, got '%s'", $tok); if ("\0" == $tok || false === $tok) { return false; } return $this->bogusComment('</'); } $name = $this->scanner->charsUntil("\n\f \t>"); $name = self::CONFORMANT_XML === $this->mode ? $name : strtolower($name); $this->scanner->whitespace(); $tok = $this->scanner->current(); if ('>' != $tok) { $this->parseError("Expected >, got '%s'", $tok); $this->scanner->charsUntil('>'); } $this->events->endTag($name); $this->scanner->consume(); return true; } protected function tagName() { $name = $this->scanner->charsWhile(':_-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'); $name = self::CONFORMANT_XML === $this->mode ? $name : strtolower($name); $attributes = array(); $selfClose = false; try { do { $this->scanner->whitespace(); $this->attribute($attributes); } while (!$this->isTagEnd($selfClose)); } catch (ParseError $e) { $selfClose = false; } $mode = $this->events->startTag($name, $attributes, $selfClose); if (is_int($mode)) { $this->setTextMode($mode, $name); } $this->scanner->consume(); return true; } protected function isTagEnd(&$selfClose) { $tok = $this->scanner->current(); if ('/' == $tok) { $this->scanner->consume(); $this->scanner->whitespace(); $tok = $this->scanner->current(); if ('>' == $tok) { $selfClose = true; return true; } if (false === $tok) { $this->parseError('Unexpected EOF inside of tag.'); return true; } $this->parseError("Unexpected '%s' inside of a tag.", $tok); return false; } if ('>' == $tok) { return true; } if (false === $tok) { $this->parseError('Unexpected EOF inside of tag.'); return true; } return false; } protected function attribute(&$attributes) { $tok = $this->scanner->current(); if ('/' == $tok || '>' == $tok || false === $tok) { return false; } if ('<' == $tok) { $this->parseError("Unexpected '<' inside of attributes list."); $this->scanner->unconsume(); throw new ParseError('Start tag inside of attribute.'); } $name = strtolower($this->scanner->charsUntil("/>=\n\f\t ")); if (0 == strlen($name)) { $tok = $this->scanner->current(); $this->parseError('Expected an attribute name, got %s.', $tok); $name = $tok; $this->scanner->consume(); } $isValidAttribute = true; if (preg_match("/[\x1-\x2C\\/\x3B-\x40\x5B-\x5E\x60\x7B-\x7F]/u", $name)) { $this->parseError('Unexpected characters in attribute name: %s', $name); $isValidAttribute = false; } elseif (preg_match('/^[0-9.-]/u', $name)) { $this->parseError('Unexpected character at the begining of attribute name: %s', $name); $isValidAttribute = false; } $this->scanner->whitespace(); $val = $this->attributeValue(); if ($isValidAttribute) { $attributes[$name] = $val; } return true; } protected function attributeValue() { if ('=' != $this->scanner->current()) { return null; } $this->scanner->consume(); $this->scanner->whitespace(); $tok = $this->scanner->current(); switch ($tok) { case "\n": case "\f": case ' ': case "\t": return null; case '"': case "'": $this->scanner->consume(); return $this->quotedAttributeValue($tok); case '>': $this->parseError('Expected attribute value, got tag end.'); return null; case '=': case '`': $this->parseError('Expecting quotes, got %s.', $tok); return $this->unquotedAttributeValue(); default: return $this->unquotedAttributeValue(); } } protected function quotedAttributeValue($quote) { $stoplist = "\f" . $quote; $val = ''; while (true) { $tokens = $this->scanner->charsUntil($stoplist . '&'); if (false !== $tokens) { $val .= $tokens; } else { break; } $tok = $this->scanner->current(); if ('&' == $tok) { $val .= $this->decodeCharacterReference(true); continue; } break; } $this->scanner->consume(); return $val; } protected function unquotedAttributeValue() { $val = ''; $tok = $this->scanner->current(); while (false !== $tok) { switch ($tok) { case "\n": case "\f": case ' ': case "\t": case '>': break 2; case '&': $val .= $this->decodeCharacterReference(true); $tok = $this->scanner->current(); break; case "'": case '"': case '<': case '=': case '`': $this->parseError('Unexpected chars in unquoted attribute value %s', $tok); $val .= $tok; $tok = $this->scanner->next(); break; default: $val .= $this->scanner->charsUntil("\t\n\f >&\"'<=`"); $tok = $this->scanner->current(); } } return $val; } protected function bogusComment($leading = '') { $comment = $leading; $tokens = $this->scanner->charsUntil('>'); if (false !== $tokens) { $comment .= $tokens; } $tok = $this->scanner->current(); if (false !== $tok) { $comment .= $tok; } $this->flushBuffer(); $this->events->comment($comment); $this->scanner->consume(); return true; } protected function comment() { $tok = $this->scanner->current(); $comment = ''; if ('>' == $tok) { $this->parseError("Expected comment data, got '>'"); $this->events->comment(''); $this->scanner->consume(); return true; } if ("\0" == $tok) { $tok = UTF8Utils::FFFD; } while (!$this->isCommentEnd()) { $comment .= $tok; $tok = $this->scanner->next(); } $this->events->comment($comment); $this->scanner->consume(); return true; } protected function isCommentEnd() { $tok = $this->scanner->current(); if (false === $tok) { $this->parseError('Unexpected EOF in a comment.'); return true; } if ('-' != $tok || '-' != $this->scanner->peek()) { return false; } $this->scanner->consume(2); if ('>' == $this->scanner->current()) { return true; } if ('!' == $this->scanner->current() && '>' == $this->scanner->peek()) { $this->scanner->consume(); return true; } $this->scanner->unconsume(2); return false; } protected function doctype() { if ($this->scanner->sequenceMatches('DOCTYPE', false)) { $this->scanner->consume(7); } else { $chars = $this->scanner->charsWhile('DOCTYPEdoctype'); $this->parseError('Expected DOCTYPE, got %s', $chars); return $this->bogusComment('<!' . $chars); } $this->scanner->whitespace(); $tok = $this->scanner->current(); if (false === $tok) { $this->events->doctype('html5', EventHandler::DOCTYPE_NONE, '', true); $this->eof(); return true; } if ("\0" === $tok) { $this->parseError('Unexpected null character in DOCTYPE.'); } $stop = " \n\f>"; $doctypeName = $this->scanner->charsUntil($stop); $doctypeName = strtolower(strtr($doctypeName, "\0", UTF8Utils::FFFD)); $tok = $this->scanner->current(); if (false === $tok) { $this->parseError('Unexpected EOF in DOCTYPE declaration.'); $this->events->doctype($doctypeName, EventHandler::DOCTYPE_NONE, null, true); return true; } if ('>' == $tok) { if (0 == strlen($doctypeName)) { $this->parseError('Expected a DOCTYPE name. Got nothing.'); $this->events->doctype($doctypeName, 0, null, true); $this->scanner->consume(); return true; } $this->events->doctype($doctypeName); $this->scanner->consume(); return true; } $this->scanner->whitespace(); $pub = strtoupper($this->scanner->getAsciiAlpha()); $white = $this->scanner->whitespace(); if (('PUBLIC' == $pub || 'SYSTEM' == $pub) && $white > 0) { $type = 'PUBLIC' == $pub ? EventHandler::DOCTYPE_PUBLIC : EventHandler::DOCTYPE_SYSTEM; $id = $this->quotedString("\0>"); if (false === $id) { $this->events->doctype($doctypeName, $type, $pub, false); return true; } if (false === $this->scanner->current()) { $this->parseError('Unexpected EOF in DOCTYPE'); $this->events->doctype($doctypeName, $type, $id, true); return true; } $this->scanner->whitespace(); if ('>' == $this->scanner->current()) { $this->events->doctype($doctypeName, $type, $id, false); $this->scanner->consume(); return true; } $this->scanner->charsUntil('>'); $this->parseError('Malformed DOCTYPE.'); $this->events->doctype($doctypeName, $type, $id, true); $this->scanner->consume(); return true; } $this->scanner->charsUntil('>'); $this->parseError('Expected PUBLIC or SYSTEM. Got %s.', $pub); $this->events->doctype($doctypeName, 0, null, true); $this->scanner->consume(); return true; } protected function quotedString($stopchars) { $tok = $this->scanner->current(); if ('"' == $tok || "'" == $tok) { $this->scanner->consume(); $ret = $this->scanner->charsUntil($tok . $stopchars); if ($this->scanner->current() == $tok) { $this->scanner->consume(); } else { $this->parseError('Expected %s, got %s', $tok, $this->scanner->current()); } return $ret; } return false; } protected function cdataSection() { $cdata = ''; $this->scanner->consume(); $chars = $this->scanner->charsWhile('CDAT'); if ('CDATA' != $chars || '[' != $this->scanner->current()) { $this->parseError('Expected [CDATA[, got %s', $chars); return $this->bogusComment('<![' . $chars); } $tok = $this->scanner->next(); do { if (false === $tok) { $this->parseError('Unexpected EOF inside CDATA.'); $this->bogusComment('<![CDATA[' . $cdata); return true; } $cdata .= $tok; $tok = $this->scanner->next(); } while (!$this->scanner->sequenceMatches(']]>')); $this->scanner->consume(3); $this->events->cdata($cdata); return true; } protected function processingInstruction() { if ('?' != $this->scanner->current()) { return false; } $tok = $this->scanner->next(); $procName = $this->scanner->getAsciiAlpha(); $white = $this->scanner->whitespace(); if (0 == strlen($procName) || 0 == $white || false == $this->scanner->current()) { $this->parseError("Expected processing instruction name, got $tok"); $this->bogusComment('<?' . $tok . $procName); return true; } $data = ''; while (!('?' == $this->scanner->current() && '>' == $this->scanner->peek())) { $data .= $this->scanner->current(); $tok = $this->scanner->next(); if (false === $tok) { $this->parseError('Unexpected EOF in processing instruction.'); $this->events->processingInstruction($procName, $data); return true; } } $this->scanner->consume(2); $this->events->processingInstruction($procName, $data); return true; } protected function readUntilSequence($sequence) { $buffer = ''; $first = substr($sequence, 0, 1); while (false !== $this->scanner->current()) { $buffer .= $this->scanner->charsUntil($first); if ($this->scanner->sequenceMatches($sequence, false)) { return $buffer; } $buffer .= $this->scanner->current(); $this->scanner->consume(); } $this->parseError('Unexpected EOF during text read.'); return $buffer; } protected function sequenceMatches($sequence, $caseSensitive = true) { @trigger_error(__METHOD__ . ' method is deprecated since version 2.4 and will be removed in 3.0. Use Scanner::sequenceMatches() instead.', E_USER_DEPRECATED); return $this->scanner->sequenceMatches($sequence, $caseSensitive); } protected function flushBuffer() { if ('' === $this->text) { return; } $this->events->text($this->text); $this->text = ''; } protected function buffer($str) { $this->text .= $str; } protected function parseError($msg) { $args = func_get_args(); if (count($args) > 1) { array_shift($args); $msg = vsprintf($msg, $args); } $line = $this->scanner->currentLine(); $col = $this->scanner->columnOffset(); $this->events->parseError($msg, $line, $col); return false; } protected function decodeCharacterReference($inAttribute = false) { $tok = $this->scanner->next(); $start = $this->scanner->position(); if (false === $tok) { return '&'; } if ("\t" === $tok || "\n" === $tok || "\f" === $tok || ' ' === $tok || '&' === $tok || '<' === $tok) { return '&'; } if ('#' === $tok) { $tok = $this->scanner->next(); if (false === $tok) { $this->parseError('Expected &#DEC; &#HEX;, got EOF'); $this->scanner->unconsume(1); return '&'; } if ('x' === $tok || 'X' === $tok) { $tok = $this->scanner->next(); $hex = $this->scanner->getHex(); if (empty($hex)) { $this->parseError('Expected &#xHEX;, got &#x%s', $tok); $this->scanner->unconsume(2); return '&'; } $entity = CharacterReference::lookupHex($hex); } else { $numeric = $this->scanner->getNumeric(); if (false === $numeric) { $this->parseError('Expected &#DIGITS;, got &#%s', $tok); $this->scanner->unconsume(2); return '&'; } $entity = CharacterReference::lookupDecimal($numeric); } } elseif ('=' === $tok && $inAttribute) { return '&'; } else { $cname = $this->scanner->getAsciiAlphaNum(); $entity = CharacterReference::lookupName($cname); if (null === $entity) { if (!$inAttribute || '' === $cname) { $this->parseError("No match in entity table for '%s'", $cname); } $this->scanner->unconsume($this->scanner->position() - $start); return '&'; } } $tok = $this->scanner->current(); if (';' === $tok) { $this->scanner->consume(); return $entity; } $this->scanner->unconsume($this->scanner->position() - $start); $this->parseError('Expected &ENTITY;, got &ENTITY%s (no trailing ;) ', $tok); return '&'; } protected function is_alpha($input) { $code = ord($input); return ($code >= 97 && $code <= 122) || ($code >= 65 && $code <= 90); } } namespace AimySpeedOptimization\Masterminds\HTML5\Parser; class TreeBuildingRules { protected static $tags = array( 'li' => 1, 'dd' => 1, 'dt' => 1, 'rt' => 1, 'rp' => 1, 'tr' => 1, 'th' => 1, 'td' => 1, 'thead' => 1, 'tfoot' => 1, 'tbody' => 1, 'table' => 1, 'optgroup' => 1, 'option' => 1, ); public function hasRules($tagname) { return isset(static::$tags[$tagname]); } public function evaluate($new, $current) { switch ($new->tagName) { case 'li': return $this->handleLI($new, $current); case 'dt': case 'dd': return $this->handleDT($new, $current); case 'rt': case 'rp': return $this->handleRT($new, $current); case 'optgroup': return $this->closeIfCurrentMatches($new, $current, array( 'optgroup', )); case 'option': return $this->closeIfCurrentMatches($new, $current, array( 'option', )); case 'tr': return $this->closeIfCurrentMatches($new, $current, array( 'tr', )); case 'td': case 'th': return $this->closeIfCurrentMatches($new, $current, array( 'th', 'td', )); case 'tbody': case 'thead': case 'tfoot': case 'table': return $this->closeIfCurrentMatches($new, $current, array( 'thead', 'tfoot', 'tbody', )); } return $current; } protected function handleLI($ele, $current) { return $this->closeIfCurrentMatches($ele, $current, array( 'li', )); } protected function handleDT($ele, $current) { return $this->closeIfCurrentMatches($ele, $current, array( 'dt', 'dd', )); } protected function handleRT($ele, $current) { return $this->closeIfCurrentMatches($ele, $current, array( 'rt', 'rp', )); } protected function closeIfCurrentMatches($ele, $current, $match) { if (in_array($current->tagName, $match, true)) { $current->parentNode->appendChild($ele); } else { $current->appendChild($ele); } return $ele; } } namespace AimySpeedOptimization\Masterminds\HTML5\Parser; interface InputStream extends \Iterator { public function currentLine(); public function columnOffset(); public function remainingChars(); public function charsUntil($bytes, $max = null); public function charsWhile($bytes, $max = null); public function unconsume($howMany = 1); public function peek(); } namespace AimySpeedOptimization\Masterminds\HTML5\Parser; class StringInputStream implements InputStream { private $data; private $char; private $EOF; public $errors = array(); public function __construct($data, $encoding = 'UTF-8', $debug = '') { $data = UTF8Utils::convertToUTF8($data, $encoding); if ($debug) { fprintf(STDOUT, $debug, $data, strlen($data)); } $this->errors = UTF8Utils::checkForIllegalCodepoints($data); $data = $this->replaceLinefeeds($data); $this->data = $data; $this->char = 0; $this->EOF = strlen($data); } public function __toString() { return $this->data; } protected function replaceLinefeeds($data) { $crlfTable = array( "\0" => "\xEF\xBF\xBD", "\r\n" => "\n", "\r" => "\n", ); return strtr($data, $crlfTable); } public function currentLine() { if (empty($this->EOF) || 0 === $this->char) { return 1; } return substr_count($this->data, "\n", 0, min($this->char, $this->EOF)) + 1; } public function getCurrentLine() { return $this->currentLine(); } public function columnOffset() { if (0 === $this->char) { return 0; } $backwardFrom = $this->char - 1 - strlen($this->data); $lastLine = strrpos($this->data, "\n", $backwardFrom); if (false !== $lastLine) { $findLengthOf = substr($this->data, $lastLine + 1, $this->char - 1 - $lastLine); } else { $findLengthOf = substr($this->data, 0, $this->char); } return UTF8Utils::countChars($findLengthOf); } public function getColumnOffset() { return $this->columnOffset(); } public function current() : mixed { return $this->data[$this->char]; } public function next() : void { ++$this->char; } public function rewind() : void { $this->char = 0; } public function valid() : bool { return $this->char < $this->EOF; } public function remainingChars() { if ($this->char < $this->EOF) { $data = substr($this->data, $this->char); $this->char = $this->EOF; return $data; } return ''; } public function charsUntil($bytes, $max = null) { if ($this->char >= $this->EOF) { return false; } if (0 === $max || $max) { $len = strcspn($this->data, $bytes, $this->char, $max); } else { $len = strcspn($this->data, $bytes, $this->char); } $string = (string) substr($this->data, $this->char, $len); $this->char += $len; return $string; } public function charsWhile($bytes, $max = null) { if ($this->char >= $this->EOF) { return false; } if (0 === $max || $max) { $len = strspn($this->data, $bytes, $this->char, $max); } else { $len = strspn($this->data, $bytes, $this->char); } $string = (string) substr($this->data, $this->char, $len); $this->char += $len; return $string; } public function unconsume($howMany = 1) { if (($this->char - $howMany) >= 0) { $this->char -= $howMany; } } public function peek() { if (($this->char + 1) <= $this->EOF) { return $this->data[$this->char + 1]; } return false; } public function key() : mixed { return $this->char; } } namespace AimySpeedOptimization\Masterminds\HTML5\Parser; class FileInputStream extends StringInputStream implements InputStream { public function __construct($data, $encoding = 'UTF-8', $debug = '') { $content = file_get_contents($data); parent::__construct($content, $encoding, $debug); } } namespace AimySpeedOptimization\Masterminds\HTML5\Parser; class ParseError extends \Exception { } namespace AimySpeedOptimization\Masterminds\HTML5\Parser; use AimySpeedOptimization\Masterminds\HTML5\Exception; class UTF8Utils { const FFFD = "\xEF\xBF\xBD"; public static function countChars($string) { if (function_exists('mb_strlen')) { return mb_strlen($string, 'utf-8'); } if (function_exists('iconv_strlen')) { return iconv_strlen($string, 'utf-8'); } $count = count_chars($string); return array_sum(array_slice($count, 0, 0x80)) + array_sum(array_slice($count, 0xC2, 0x33)); } public static function convertToUTF8($data, $encoding = 'UTF-8') { if (function_exists('mb_convert_encoding')) { $save = mb_substitute_character(); mb_substitute_character('none'); $data = mb_convert_encoding($data, 'UTF-8', $encoding); mb_substitute_character($save); } elseif (function_exists('iconv') && 'auto' !== $encoding) { $data = @iconv($encoding, 'UTF-8//IGNORE', $data); } else { throw new Exception('Not implemented, please install mbstring or iconv'); } if ("\xEF\xBB\xBF" === substr($data, 0, 3)) { $data = substr($data, 3); } return $data; } public static function checkForIllegalCodepoints($data) { $errors = array(); for ($i = 0, $count = substr_count($data, "\0"); $i < $count; ++$i) { $errors[] = 'null-character'; } $count = preg_match_all( '/(?:
        [\x01-\x08\x0B\x0E-\x1F\x7F] # U+0001 to U+0008, U+000B,  U+000E to U+001F and U+007F
      |
        \xC2[\x80-\x9F] # U+0080 to U+009F
      |
        \xED(?:\xA0[\x80-\xFF]|[\xA1-\xBE][\x00-\xFF]|\xBF[\x00-\xBF]) # U+D800 to U+DFFFF
      |
        \xEF\xB7[\x90-\xAF] # U+FDD0 to U+FDEF
      |
        \xEF\xBF[\xBE\xBF] # U+FFFE and U+FFFF
      |
        [\xF0-\xF4][\x8F-\xBF]\xBF[\xBE\xBF] # U+nFFFE and U+nFFFF (1 <= n <= 10_{16})
      )/x', $data, $matches); for ($i = 0; $i < $count; ++$i) { $errors[] = 'invalid-codepoint'; } return $errors; } } namespace AimySpeedOptimization\Masterminds\HTML5\Parser; interface EventHandler { const DOCTYPE_NONE = 0; const DOCTYPE_PUBLIC = 1; const DOCTYPE_SYSTEM = 2; public function doctype($name, $idType = 0, $id = null, $quirks = false); public function startTag($name, $attributes = array(), $selfClosing = false); public function endTag($name); public function comment($cdata); public function text($cdata); public function eof(); public function parseError($msg, $line, $col); public function cdata($data); public function processingInstruction($name, $data = null); } namespace AimySpeedOptimization\Masterminds\HTML5\Parser; use AimySpeedOptimization\Masterminds\HTML5\Entities; class CharacterReference { protected static $numeric_mask = array( 0x0, 0x2FFFF, 0, 0xFFFF, ); public static function lookupName($name) { return isset(Entities::$byName[$name]) ? Entities::$byName[$name] : null; } public static function lookupDecimal($int) { $entity = '&#' . $int . ';'; return mb_decode_numericentity($entity, static::$numeric_mask, 'utf-8'); } public static function lookupHex($hexdec) { return static::lookupDecimal(hexdec($hexdec)); } } namespace AimySpeedOptimization\Masterminds\HTML5\Parser; use AimySpeedOptimization\Masterminds\HTML5\Elements; use AimySpeedOptimization\Masterminds\HTML5\InstructionProcessor; class DOMTreeBuilder implements EventHandler { const NAMESPACE_HTML = 'http://www.w3.org/1999/xhtml'; const NAMESPACE_MATHML = 'http://www.w3.org/1998/Math/MathML'; const NAMESPACE_SVG = 'http://www.w3.org/2000/svg'; const NAMESPACE_XLINK = 'http://www.w3.org/1999/xlink'; const NAMESPACE_XML = 'http://www.w3.org/XML/1998/namespace'; const NAMESPACE_XMLNS = 'http://www.w3.org/2000/xmlns/'; const OPT_DISABLE_HTML_NS = 'disable_html_ns'; const OPT_TARGET_DOC = 'target_document'; const OPT_IMPLICIT_NS = 'implicit_namespaces'; protected $nsRoots = array( 'html' => self::NAMESPACE_HTML, 'svg' => self::NAMESPACE_SVG, 'math' => self::NAMESPACE_MATHML, ); protected $implicitNamespaces = array( 'xml' => self::NAMESPACE_XML, 'xmlns' => self::NAMESPACE_XMLNS, 'xlink' => self::NAMESPACE_XLINK, ); protected $nsStack = array(); protected $pushes = array(); const IM_INITIAL = 0; const IM_BEFORE_HTML = 1; const IM_BEFORE_HEAD = 2; const IM_IN_HEAD = 3; const IM_IN_HEAD_NOSCRIPT = 4; const IM_AFTER_HEAD = 5; const IM_IN_BODY = 6; const IM_TEXT = 7; const IM_IN_TABLE = 8; const IM_IN_TABLE_TEXT = 9; const IM_IN_CAPTION = 10; const IM_IN_COLUMN_GROUP = 11; const IM_IN_TABLE_BODY = 12; const IM_IN_ROW = 13; const IM_IN_CELL = 14; const IM_IN_SELECT = 15; const IM_IN_SELECT_IN_TABLE = 16; const IM_AFTER_BODY = 17; const IM_IN_FRAMESET = 18; const IM_AFTER_FRAMESET = 19; const IM_AFTER_AFTER_BODY = 20; const IM_AFTER_AFTER_FRAMESET = 21; const IM_IN_SVG = 22; const IM_IN_MATHML = 23; protected $options = array(); protected $stack = array(); protected $current; protected $rules; protected $doc; protected $frag; protected $processor; protected $insertMode = 0; protected $onlyInline; protected $quirks = true; protected $errors = array(); public function __construct($isFragment = false, array $options = array()) { $this->options = $options; if (isset($options[self::OPT_TARGET_DOC])) { $this->doc = $options[self::OPT_TARGET_DOC]; } else { $impl = new \DOMImplementation(); $dt = $impl->createDocumentType('html'); $this->doc = $impl->createDocument(null, '', $dt); $this->doc->encoding = !empty($options['encoding']) ? $options['encoding'] : 'UTF-8'; } $this->errors = array(); $this->current = $this->doc; $this->rules = new TreeBuildingRules(); $implicitNS = array(); if (isset($this->options[self::OPT_IMPLICIT_NS])) { $implicitNS = $this->options[self::OPT_IMPLICIT_NS]; } elseif (isset($this->options['implicitNamespaces'])) { $implicitNS = $this->options['implicitNamespaces']; } array_unshift($this->nsStack, $implicitNS + array('' => self::NAMESPACE_HTML) + $this->implicitNamespaces); if ($isFragment) { $this->insertMode = static::IM_IN_BODY; $this->frag = $this->doc->createDocumentFragment(); $this->current = $this->frag; } } public function document() { return $this->doc; } public function fragment() { return $this->frag; } public function setInstructionProcessor(InstructionProcessor $proc) { $this->processor = $proc; } public function doctype($name, $idType = 0, $id = null, $quirks = false) { $this->quirks = $quirks; if ($this->insertMode > static::IM_INITIAL) { $this->parseError('Illegal placement of DOCTYPE tag. Ignoring: ' . $name); return; } $this->insertMode = static::IM_BEFORE_HTML; } public function startTag($name, $attributes = array(), $selfClosing = false) { $lname = $this->normalizeTagName($name); if (!$this->doc->documentElement && 'html' !== $name && !$this->frag) { $this->startTag('html'); } if ($this->insertMode === static::IM_INITIAL) { $this->quirks = true; $this->parseError('No DOCTYPE specified.'); } if ('image' === $name && !($this->insertMode === static::IM_IN_SVG || $this->insertMode === static::IM_IN_MATHML)) { $name = 'img'; } if ($this->insertMode >= static::IM_IN_BODY && Elements::isA($name, Elements::AUTOCLOSE_P)) { $this->autoclose('p'); } switch ($name) { case 'html': $this->insertMode = static::IM_BEFORE_HEAD; break; case 'head': if ($this->insertMode > static::IM_BEFORE_HEAD) { $this->parseError('Unexpected head tag outside of head context.'); } else { $this->insertMode = static::IM_IN_HEAD; } break; case 'body': $this->insertMode = static::IM_IN_BODY; break; case 'svg': $this->insertMode = static::IM_IN_SVG; break; case 'math': $this->insertMode = static::IM_IN_MATHML; break; case 'noscript': if ($this->insertMode === static::IM_IN_HEAD) { $this->insertMode = static::IM_IN_HEAD_NOSCRIPT; } break; } if ($this->insertMode === static::IM_IN_SVG) { $lname = Elements::normalizeSvgElement($lname); } $pushes = 0; if (isset($this->nsRoots[$lname]) && $this->nsStack[0][''] !== $this->nsRoots[$lname]) { array_unshift($this->nsStack, array( '' => $this->nsRoots[$lname], ) + $this->nsStack[0]); ++$pushes; } $needsWorkaround = false; if (isset($this->options['xmlNamespaces']) && $this->options['xmlNamespaces']) { foreach ($attributes as $aName => $aVal) { if ('xmlns' === $aName) { $needsWorkaround = $aVal; array_unshift($this->nsStack, array( '' => $aVal, ) + $this->nsStack[0]); ++$pushes; } elseif ('xmlns' === (($pos = strpos($aName, ':')) ? substr($aName, 0, $pos) : '')) { array_unshift($this->nsStack, array( substr($aName, $pos + 1) => $aVal, ) + $this->nsStack[0]); ++$pushes; } } } if ($this->onlyInline && Elements::isA($lname, Elements::BLOCK_TAG)) { $this->autoclose($this->onlyInline); $this->onlyInline = null; } if ($this->current instanceof \DOMElement && isset(Elements::$optionalEndElementsParentsToClose[$lname])) { foreach (Elements::$optionalEndElementsParentsToClose[$lname] as $parentElName) { if ($this->current instanceof \DOMElement && $this->current->tagName === $parentElName) { $this->autoclose($parentElName); } } } try { $prefix = ($pos = strpos($lname, ':')) ? substr($lname, 0, $pos) : ''; if (false !== $needsWorkaround) { $xml = "<$lname xmlns=\"$needsWorkaround\" " . (strlen($prefix) && isset($this->nsStack[0][$prefix]) ? ("xmlns:$prefix=\"" . $this->nsStack[0][$prefix] . '"') : '') . '/>'; $frag = new \DOMDocument('1.0', 'UTF-8'); $frag->loadXML($xml); $ele = $this->doc->importNode($frag->documentElement, true); } else { if (!isset($this->nsStack[0][$prefix]) || ('' === $prefix && isset($this->options[self::OPT_DISABLE_HTML_NS]) && $this->options[self::OPT_DISABLE_HTML_NS])) { $ele = $this->doc->createElement($lname); } else { $ele = $this->doc->createElementNS($this->nsStack[0][$prefix], $lname); } } } catch (\DOMException $e) { $this->parseError("Illegal tag name: <$lname>. Replaced with <invalid>."); $ele = $this->doc->createElement('invalid'); } if (Elements::isA($lname, Elements::BLOCK_ONLY_INLINE)) { $this->onlyInline = $lname; } if ($pushes > 0 && !Elements::isA($name, Elements::VOID_TAG)) { $this->pushes[spl_object_hash($ele)] = array($pushes, $ele); } foreach ($attributes as $aName => $aVal) { if ('xmlns' === $aName) { continue; } if ($this->insertMode === static::IM_IN_SVG) { $aName = Elements::normalizeSvgAttribute($aName); } elseif ($this->insertMode === static::IM_IN_MATHML) { $aName = Elements::normalizeMathMlAttribute($aName); } $aVal = (string) $aVal; try { $prefix = ($pos = strpos($aName, ':')) ? substr($aName, 0, $pos) : false; if ('xmlns' === $prefix) { $ele->setAttributeNS(self::NAMESPACE_XMLNS, $aName, $aVal); } elseif (false !== $prefix && isset($this->nsStack[0][$prefix])) { $ele->setAttributeNS($this->nsStack[0][$prefix], $aName, $aVal); } else { $ele->setAttribute($aName, $aVal); } } catch (\DOMException $e) { $this->parseError("Illegal attribute name for tag $name. Ignoring: $aName"); continue; } if ('id' === $aName) { $ele->setIdAttribute('id', true); } } if ($this->frag !== $this->current && $this->rules->hasRules($name)) { $this->current = $this->rules->evaluate($ele, $this->current); } else { $this->current->appendChild($ele); if (!Elements::isA($name, Elements::VOID_TAG)) { $this->current = $ele; } if (Elements::isHtml5Element($name)) { $selfClosing = false; } } if ($this->insertMode <= static::IM_BEFORE_HEAD && 'head' !== $name && 'html' !== $name) { $this->insertMode = static::IM_IN_BODY; } if ($pushes > 0 && Elements::isA($name, Elements::VOID_TAG)) { for ($i = 0; $i < $pushes; ++$i) { array_shift($this->nsStack); } } if ($selfClosing) { $this->endTag($name); } return Elements::element($name); } public function endTag($name) { $lname = $this->normalizeTagName($name); if ('br' === $name) { $this->parseError('Closing tag encountered for void element br.'); $this->startTag('br'); } elseif (Elements::isA($name, Elements::VOID_TAG)) { return; } if ($this->insertMode <= static::IM_BEFORE_HTML) { if (in_array($name, array( 'html', 'br', 'head', 'title', ))) { $this->startTag('html'); $this->endTag($name); $this->insertMode = static::IM_BEFORE_HEAD; return; } $this->parseError('Illegal closing tag at global scope.'); return; } if ($this->insertMode === static::IM_IN_SVG) { $lname = Elements::normalizeSvgElement($lname); } $cid = spl_object_hash($this->current); if ('html' === $lname) { return; } if (isset($this->pushes[$cid])) { for ($i = 0; $i < $this->pushes[$cid][0]; ++$i) { array_shift($this->nsStack); } unset($this->pushes[$cid]); } if (!$this->autoclose($lname)) { $this->parseError('Could not find closing tag for ' . $lname); } switch ($lname) { case 'head': $this->insertMode = static::IM_AFTER_HEAD; break; case 'body': $this->insertMode = static::IM_AFTER_BODY; break; case 'svg': case 'mathml': $this->insertMode = static::IM_IN_BODY; break; } } public function comment($cdata) { $node = $this->doc->createComment($cdata); $this->current->appendChild($node); } public function text($data) { if ($this->insertMode < static::IM_IN_HEAD) { $dataTmp = trim($data, " \t\n\r\f"); if (!empty($dataTmp)) { $this->parseError('Unexpected text. Ignoring: ' . $dataTmp); } return; } $node = $this->doc->createTextNode($data); $this->current->appendChild($node); } public function eof() { } public function parseError($msg, $line = 0, $col = 0) { $this->errors[] = sprintf('Line %d, Col %d: %s', $line, $col, $msg); } public function getErrors() { return $this->errors; } public function cdata($data) { $node = $this->doc->createCDATASection($data); $this->current->appendChild($node); } public function processingInstruction($name, $data = null) { if ($this->insertMode === static::IM_INITIAL && 'xml' === strtolower($name)) { return; } if ($this->processor instanceof InstructionProcessor) { $res = $this->processor->process($this->current, $name, $data); if (!empty($res)) { $this->current = $res; } return; } $node = $this->doc->createProcessingInstruction($name, $data); $this->current->appendChild($node); } protected function normalizeTagName($tagName) { return $tagName; } protected function quirksTreeResolver($name) { throw new \Exception('Not implemented.'); } protected function autoclose($tagName) { $working = $this->current; do { if (XML_ELEMENT_NODE !== $working->nodeType) { return false; } if ($working->tagName === $tagName) { $this->current = $working->parentNode; return true; } } while ($working = $working->parentNode); return false; } protected function isAncestor($tagName) { $candidate = $this->current; while (XML_ELEMENT_NODE === $candidate->nodeType) { if ($candidate->tagName === $tagName) { return true; } $candidate = $candidate->parentNode; } return false; } protected function isParent($tagName) { return $this->current->tagName === $tagName; } } namespace AimySpeedOptimization\Masterminds\HTML5\Parser; use AimySpeedOptimization\Masterminds\HTML5\Exception; class Scanner { const CHARS_HEX = 'abcdefABCDEF01234567890'; const CHARS_ALNUM = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890'; const CHARS_ALPHA = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; private $data; private $char; private $EOF; public $errors = array(); public function __construct($data, $encoding = 'UTF-8') { if ($data instanceof InputStream) { @trigger_error('InputStream objects are deprecated since version 2.4 and will be removed in 3.0. Use strings instead.', E_USER_DEPRECATED); $data = (string) $data; } $data = UTF8Utils::convertToUTF8($data, $encoding); $this->errors = UTF8Utils::checkForIllegalCodepoints($data); $data = $this->replaceLinefeeds($data); $this->data = $data; $this->char = 0; $this->EOF = strlen($data); } public function sequenceMatches($sequence, $caseSensitive = true) { $portion = substr($this->data, $this->char, strlen($sequence)); return $caseSensitive ? $portion === $sequence : 0 === strcasecmp($portion, $sequence); } public function position() { return $this->char; } public function peek() { if (($this->char + 1) < $this->EOF) { return $this->data[$this->char + 1]; } return false; } public function next() { ++$this->char; if ($this->char < $this->EOF) { return $this->data[$this->char]; } return false; } public function current() { if ($this->char < $this->EOF) { return $this->data[$this->char]; } return false; } public function consume($count = 1) { $this->char += $count; } public function unconsume($howMany = 1) { if (($this->char - $howMany) >= 0) { $this->char -= $howMany; } } public function getHex() { return $this->doCharsWhile(static::CHARS_HEX); } public function getAsciiAlpha() { return $this->doCharsWhile(static::CHARS_ALPHA); } public function getAsciiAlphaNum() { return $this->doCharsWhile(static::CHARS_ALNUM); } public function getNumeric() { return $this->doCharsWhile('0123456789'); } public function whitespace() { if ($this->char >= $this->EOF) { return false; } $len = strspn($this->data, "\n\t\f ", $this->char); $this->char += $len; return $len; } public function currentLine() { if (empty($this->EOF) || 0 === $this->char) { return 1; } return substr_count($this->data, "\n", 0, min($this->char, $this->EOF)) + 1; } public function charsUntil($mask) { return $this->doCharsUntil($mask); } public function charsWhile($mask) { return $this->doCharsWhile($mask); } public function columnOffset() { if (0 === $this->char) { return 0; } $backwardFrom = $this->char - 1 - strlen($this->data); $lastLine = strrpos($this->data, "\n", $backwardFrom); if (false !== $lastLine) { $findLengthOf = substr($this->data, $lastLine + 1, $this->char - 1 - $lastLine); } else { $findLengthOf = substr($this->data, 0, $this->char); } return UTF8Utils::countChars($findLengthOf); } public function remainingChars() { if ($this->char < $this->EOF) { $data = substr($this->data, $this->char); $this->char = $this->EOF; return $data; } return ''; } private function replaceLinefeeds($data) { $crlfTable = array( "\0" => "\xEF\xBF\xBD", "\r\n" => "\n", "\r" => "\n", ); return strtr($data, $crlfTable); } private function doCharsUntil($bytes, $max = null) { if ($this->char >= $this->EOF) { return false; } if (0 === $max || $max) { $len = strcspn($this->data, $bytes, $this->char, $max); } else { $len = strcspn($this->data, $bytes, $this->char); } $string = (string) substr($this->data, $this->char, $len); $this->char += $len; return $string; } private function doCharsWhile($bytes, $max = null) { if ($this->char >= $this->EOF) { return false; } if (0 === $max || $max) { $len = strspn($this->data, $bytes, $this->char, $max); } else { $len = strspn($this->data, $bytes, $this->char); } $string = (string) substr($this->data, $this->char, $len); $this->char += $len; return $string; } } namespace AimySpeedOptimization\Masterminds\HTML5\Serializer; class HTML5Entities { public static $map = array( '	' => '&Tab;', "\n" => '&NewLine;', '!' => '&excl;', '"' => '&quot;', '#' => '&num;', '$' => '&dollar;', '%' => '&percnt;', '&' => '&amp;', '\'' => '&apos;', '(' => '&lpar;', ')' => '&rpar;', '*' => '&ast;', '+' => '&plus;', ',' => '&comma;', '.' => '&period;', '/' => '&sol;', ':' => '&colon;', ';' => '&semi;', '<' => '&lt;', '<⃒' => '&nvlt', '=' => '&equals;', '=⃥' => '&bne', '>' => '&gt;', '>⃒' => '&nvgt', '?' => '&quest;', '@' => '&commat;', '[' => '&lbrack;', '\\' => '&bsol;', ']' => '&rsqb;', '^' => '&Hat;', '_' => '&lowbar;', '`' => '&grave;', 'fj' => '&fjlig', '{' => '&lbrace;', '|' => '&vert;', '}' => '&rcub;', ' ' => '&nbsp;', '¡' => '&iexcl;', '¢' => '&cent;', '£' => '&pound;', '¤' => '&curren;', '¥' => '&yen;', '¦' => '&brvbar;', '§' => '&sect;', '¨' => '&DoubleDot;', '©' => '&copy;', 'ª' => '&ordf;', '«' => '&laquo;', '¬' => '&not;', '­' => '&shy;', '®' => '&reg;', '¯' => '&macr;', '°' => '&deg;', '±' => '&plusmn;', '²' => '&sup2;', '³' => '&sup3;', '´' => '&DiacriticalAcute;', 'µ' => '&micro;', '¶' => '&para;', '·' => '&CenterDot;', '¸' => '&Cedilla;', '¹' => '&sup1;', 'º' => '&ordm;', '»' => '&raquo;', '¼' => '&frac14;', '½' => '&half;', '¾' => '&frac34;', '¿' => '&iquest;', 'À' => '&Agrave;', 'Á' => '&Aacute;', 'Â' => '&Acirc;', 'Ã' => '&Atilde;', 'Ä' => '&Auml;', 'Å' => '&Aring;', 'Æ' => '&AElig;', 'Ç' => '&Ccedil;', 'È' => '&Egrave;', 'É' => '&Eacute;', 'Ê' => '&Ecirc;', 'Ë' => '&Euml;', 'Ì' => '&Igrave;', 'Í' => '&Iacute;', 'Î' => '&Icirc;', 'Ï' => '&Iuml;', 'Ð' => '&ETH;', 'Ñ' => '&Ntilde;', 'Ò' => '&Ograve;', 'Ó' => '&Oacute;', 'Ô' => '&Ocirc;', 'Õ' => '&Otilde;', 'Ö' => '&Ouml;', '×' => '&times;', 'Ø' => '&Oslash;', 'Ù' => '&Ugrave;', 'Ú' => '&Uacute;', 'Û' => '&Ucirc;', 'Ü' => '&Uuml;', 'Ý' => '&Yacute;', 'Þ' => '&THORN;', 'ß' => '&szlig;', 'à' => '&agrave;', 'á' => '&aacute;', 'â' => '&acirc;', 'ã' => '&atilde;', 'ä' => '&auml;', 'å' => '&aring;', 'æ' => '&aelig;', 'ç' => '&ccedil;', 'è' => '&egrave;', 'é' => '&eacute;', 'ê' => '&ecirc;', 'ë' => '&euml;', 'ì' => '&igrave;', 'í' => '&iacute;', 'î' => '&icirc;', 'ï' => '&iuml;', 'ð' => '&eth;', 'ñ' => '&ntilde;', 'ò' => '&ograve;', 'ó' => '&oacute;', 'ô' => '&ocirc;', 'õ' => '&otilde;', 'ö' => '&ouml;', '÷' => '&divide;', 'ø' => '&oslash;', 'ù' => '&ugrave;', 'ú' => '&uacute;', 'û' => '&ucirc;', 'ü' => '&uuml;', 'ý' => '&yacute;', 'þ' => '&thorn;', 'ÿ' => '&yuml;', 'Ā' => '&Amacr;', 'ā' => '&amacr;', 'Ă' => '&Abreve;', 'ă' => '&abreve;', 'Ą' => '&Aogon;', 'ą' => '&aogon;', 'Ć' => '&Cacute;', 'ć' => '&cacute;', 'Ĉ' => '&Ccirc;', 'ĉ' => '&ccirc;', 'Ċ' => '&Cdot;', 'ċ' => '&cdot;', 'Č' => '&Ccaron;', 'č' => '&ccaron;', 'Ď' => '&Dcaron;', 'ď' => '&dcaron;', 'Đ' => '&Dstrok;', 'đ' => '&dstrok;', 'Ē' => '&Emacr;', 'ē' => '&emacr;', 'Ė' => '&Edot;', 'ė' => '&edot;', 'Ę' => '&Eogon;', 'ę' => '&eogon;', 'Ě' => '&Ecaron;', 'ě' => '&ecaron;', 'Ĝ' => '&Gcirc;', 'ĝ' => '&gcirc;', 'Ğ' => '&Gbreve;', 'ğ' => '&gbreve;', 'Ġ' => '&Gdot;', 'ġ' => '&gdot;', 'Ģ' => '&Gcedil;', 'Ĥ' => '&Hcirc;', 'ĥ' => '&hcirc;', 'Ħ' => '&Hstrok;', 'ħ' => '&hstrok;', 'Ĩ' => '&Itilde;', 'ĩ' => '&itilde;', 'Ī' => '&Imacr;', 'ī' => '&imacr;', 'Į' => '&Iogon;', 'į' => '&iogon;', 'İ' => '&Idot;', 'ı' => '&inodot;', 'Ĳ' => '&IJlig;', 'ĳ' => '&ijlig;', 'Ĵ' => '&Jcirc;', 'ĵ' => '&jcirc;', 'Ķ' => '&Kcedil;', 'ķ' => '&kcedil;', 'ĸ' => '&kgreen;', 'Ĺ' => '&Lacute;', 'ĺ' => '&lacute;', 'Ļ' => '&Lcedil;', 'ļ' => '&lcedil;', 'Ľ' => '&Lcaron;', 'ľ' => '&lcaron;', 'Ŀ' => '&Lmidot;', 'ŀ' => '&lmidot;', 'Ł' => '&Lstrok;', 'ł' => '&lstrok;', 'Ń' => '&Nacute;', 'ń' => '&nacute;', 'Ņ' => '&Ncedil;', 'ņ' => '&ncedil;', 'Ň' => '&Ncaron;', 'ň' => '&ncaron;', 'ŉ' => '&napos;', 'Ŋ' => '&ENG;', 'ŋ' => '&eng;', 'Ō' => '&Omacr;', 'ō' => '&omacr;', 'Ő' => '&Odblac;', 'ő' => '&odblac;', 'Œ' => '&OElig;', 'œ' => '&oelig;', 'Ŕ' => '&Racute;', 'ŕ' => '&racute;', 'Ŗ' => '&Rcedil;', 'ŗ' => '&rcedil;', 'Ř' => '&Rcaron;', 'ř' => '&rcaron;', 'Ś' => '&Sacute;', 'ś' => '&sacute;', 'Ŝ' => '&Scirc;', 'ŝ' => '&scirc;', 'Ş' => '&Scedil;', 'ş' => '&scedil;', 'Š' => '&Scaron;', 'š' => '&scaron;', 'Ţ' => '&Tcedil;', 'ţ' => '&tcedil;', 'Ť' => '&Tcaron;', 'ť' => '&tcaron;', 'Ŧ' => '&Tstrok;', 'ŧ' => '&tstrok;', 'Ũ' => '&Utilde;', 'ũ' => '&utilde;', 'Ū' => '&Umacr;', 'ū' => '&umacr;', 'Ŭ' => '&Ubreve;', 'ŭ' => '&ubreve;', 'Ů' => '&Uring;', 'ů' => '&uring;', 'Ű' => '&Udblac;', 'ű' => '&udblac;', 'Ų' => '&Uogon;', 'ų' => '&uogon;', 'Ŵ' => '&Wcirc;', 'ŵ' => '&wcirc;', 'Ŷ' => '&Ycirc;', 'ŷ' => '&ycirc;', 'Ÿ' => '&Yuml;', 'Ź' => '&Zacute;', 'ź' => '&zacute;', 'Ż' => '&Zdot;', 'ż' => '&zdot;', 'Ž' => '&Zcaron;', 'ž' => '&zcaron;', 'ƒ' => '&fnof;', 'Ƶ' => '&imped;', 'ǵ' => '&gacute;', 'ȷ' => '&jmath;', 'ˆ' => '&circ;', 'ˇ' => '&Hacek;', '˘' => '&Breve;', '˙' => '&dot;', '˚' => '&ring;', '˛' => '&ogon;', '˜' => '&DiacriticalTilde;', '˝' => '&DiacriticalDoubleAcute;', '̑' => '&DownBreve;', 'Α' => '&Alpha;', 'Β' => '&Beta;', 'Γ' => '&Gamma;', 'Δ' => '&Delta;', 'Ε' => '&Epsilon;', 'Ζ' => '&Zeta;', 'Η' => '&Eta;', 'Θ' => '&Theta;', 'Ι' => '&Iota;', 'Κ' => '&Kappa;', 'Λ' => '&Lambda;', 'Μ' => '&Mu;', 'Ν' => '&Nu;', 'Ξ' => '&Xi;', 'Ο' => '&Omicron;', 'Π' => '&Pi;', 'Ρ' => '&Rho;', 'Σ' => '&Sigma;', 'Τ' => '&Tau;', 'Υ' => '&Upsilon;', 'Φ' => '&Phi;', 'Χ' => '&Chi;', 'Ψ' => '&Psi;', 'Ω' => '&Omega;', 'α' => '&alpha;', 'β' => '&beta;', 'γ' => '&gamma;', 'δ' => '&delta;', 'ε' => '&epsi;', 'ζ' => '&zeta;', 'η' => '&eta;', 'θ' => '&theta;', 'ι' => '&iota;', 'κ' => '&kappa;', 'λ' => '&lambda;', 'μ' => '&mu;', 'ν' => '&nu;', 'ξ' => '&xi;', 'ο' => '&omicron;', 'π' => '&pi;', 'ρ' => '&rho;', 'ς' => '&sigmav;', 'σ' => '&sigma;', 'τ' => '&tau;', 'υ' => '&upsi;', 'φ' => '&phi;', 'χ' => '&chi;', 'ψ' => '&psi;', 'ω' => '&omega;', 'ϑ' => '&thetasym;', 'ϒ' => '&upsih;', 'ϕ' => '&straightphi;', 'ϖ' => '&piv;', 'Ϝ' => '&Gammad;', 'ϝ' => '&gammad;', 'ϰ' => '&varkappa;', 'ϱ' => '&rhov;', 'ϵ' => '&straightepsilon;', '϶' => '&backepsilon;', 'Ё' => '&IOcy;', 'Ђ' => '&DJcy;', 'Ѓ' => '&GJcy;', 'Є' => '&Jukcy;', 'Ѕ' => '&DScy;', 'І' => '&Iukcy;', 'Ї' => '&YIcy;', 'Ј' => '&Jsercy;', 'Љ' => '&LJcy;', 'Њ' => '&NJcy;', 'Ћ' => '&TSHcy;', 'Ќ' => '&KJcy;', 'Ў' => '&Ubrcy;', 'Џ' => '&DZcy;', 'А' => '&Acy;', 'Б' => '&Bcy;', 'В' => '&Vcy;', 'Г' => '&Gcy;', 'Д' => '&Dcy;', 'Е' => '&IEcy;', 'Ж' => '&ZHcy;', 'З' => '&Zcy;', 'И' => '&Icy;', 'Й' => '&Jcy;', 'К' => '&Kcy;', 'Л' => '&Lcy;', 'М' => '&Mcy;', 'Н' => '&Ncy;', 'О' => '&Ocy;', 'П' => '&Pcy;', 'Р' => '&Rcy;', 'С' => '&Scy;', 'Т' => '&Tcy;', 'У' => '&Ucy;', 'Ф' => '&Fcy;', 'Х' => '&KHcy;', 'Ц' => '&TScy;', 'Ч' => '&CHcy;', 'Ш' => '&SHcy;', 'Щ' => '&SHCHcy;', 'Ъ' => '&HARDcy;', 'Ы' => '&Ycy;', 'Ь' => '&SOFTcy;', 'Э' => '&Ecy;', 'Ю' => '&YUcy;', 'Я' => '&YAcy;', 'а' => '&acy;', 'б' => '&bcy;', 'в' => '&vcy;', 'г' => '&gcy;', 'д' => '&dcy;', 'е' => '&iecy;', 'ж' => '&zhcy;', 'з' => '&zcy;', 'и' => '&icy;', 'й' => '&jcy;', 'к' => '&kcy;', 'л' => '&lcy;', 'м' => '&mcy;', 'н' => '&ncy;', 'о' => '&ocy;', 'п' => '&pcy;', 'р' => '&rcy;', 'с' => '&scy;', 'т' => '&tcy;', 'у' => '&ucy;', 'ф' => '&fcy;', 'х' => '&khcy;', 'ц' => '&tscy;', 'ч' => '&chcy;', 'ш' => '&shcy;', 'щ' => '&shchcy;', 'ъ' => '&hardcy;', 'ы' => '&ycy;', 'ь' => '&softcy;', 'э' => '&ecy;', 'ю' => '&yucy;', 'я' => '&yacy;', 'ё' => '&iocy;', 'ђ' => '&djcy;', 'ѓ' => '&gjcy;', 'є' => '&jukcy;', 'ѕ' => '&dscy;', 'і' => '&iukcy;', 'ї' => '&yicy;', 'ј' => '&jsercy;', 'љ' => '&ljcy;', 'њ' => '&njcy;', 'ћ' => '&tshcy;', 'ќ' => '&kjcy;', 'ў' => '&ubrcy;', 'џ' => '&dzcy;', ' ' => '&ensp;', ' ' => '&emsp;', ' ' => '&emsp13;', ' ' => '&emsp14;', ' ' => '&numsp;', ' ' => '&puncsp;', ' ' => '&ThinSpace;', ' ' => '&hairsp;', '​' => '&ZeroWidthSpace;', '‌' => '&zwnj;', '‍' => '&zwj;', '‎' => '&lrm;', '‏' => '&rlm;', '‐' => '&hyphen;', '–' => '&ndash;', '—' => '&mdash;', '―' => '&horbar;', '‖' => '&Verbar;', '‘' => '&OpenCurlyQuote;', '’' => '&rsquo;', '‚' => '&sbquo;', '“' => '&OpenCurlyDoubleQuote;', '”' => '&rdquo;', '„' => '&bdquo;', '†' => '&dagger;', '‡' => '&Dagger;', '•' => '&bull;', '‥' => '&nldr;', '…' => '&hellip;', '‰' => '&permil;', '‱' => '&pertenk;', '′' => '&prime;', '″' => '&Prime;', '‴' => '&tprime;', '‵' => '&backprime;', '‹' => '&lsaquo;', '›' => '&rsaquo;', '‾' => '&oline;', '⁁' => '&caret;', '⁃' => '&hybull;', '⁄' => '&frasl;', '⁏' => '&bsemi;', '⁗' => '&qprime;', ' ' => '&MediumSpace;', '  ' => '&ThickSpace', '⁠' => '&NoBreak;', '⁡' => '&af;', '⁢' => '&InvisibleTimes;', '⁣' => '&ic;', '€' => '&euro;', '⃛' => '&TripleDot;', '⃜' => '&DotDot;', 'ℂ' => '&complexes;', '℅' => '&incare;', 'ℊ' => '&gscr;', 'ℋ' => '&HilbertSpace;', 'ℌ' => '&Hfr;', 'ℍ' => '&Hopf;', 'ℎ' => '&planckh;', 'ℏ' => '&planck;', 'ℐ' => '&imagline;', 'ℑ' => '&Ifr;', 'ℒ' => '&lagran;', 'ℓ' => '&ell;', 'ℕ' => '&naturals;', '№' => '&numero;', '℗' => '&copysr;', '℘' => '&wp;', 'ℙ' => '&primes;', 'ℚ' => '&rationals;', 'ℛ' => '&realine;', 'ℜ' => '&Rfr;', 'ℝ' => '&Ropf;', '℞' => '&rx;', '™' => '&trade;', 'ℤ' => '&Zopf;', '℧' => '&mho;', 'ℨ' => '&Zfr;', '℩' => '&iiota;', 'ℬ' => '&Bscr;', 'ℭ' => '&Cfr;', 'ℯ' => '&escr;', 'ℰ' => '&expectation;', 'ℱ' => '&Fouriertrf;', 'ℳ' => '&Mellintrf;', 'ℴ' => '&orderof;', 'ℵ' => '&aleph;', 'ℶ' => '&beth;', 'ℷ' => '&gimel;', 'ℸ' => '&daleth;', 'ⅅ' => '&CapitalDifferentialD;', 'ⅆ' => '&DifferentialD;', 'ⅇ' => '&exponentiale;', 'ⅈ' => '&ImaginaryI;', '⅓' => '&frac13;', '⅔' => '&frac23;', '⅕' => '&frac15;', '⅖' => '&frac25;', '⅗' => '&frac35;', '⅘' => '&frac45;', '⅙' => '&frac16;', '⅚' => '&frac56;', '⅛' => '&frac18;', '⅜' => '&frac38;', '⅝' => '&frac58;', '⅞' => '&frac78;', '←' => '&larr;', '↑' => '&uarr;', '→' => '&srarr;', '↓' => '&darr;', '↔' => '&harr;', '↕' => '&UpDownArrow;', '↖' => '&nwarrow;', '↗' => '&UpperRightArrow;', '↘' => '&LowerRightArrow;', '↙' => '&swarr;', '↚' => '&nleftarrow;', '↛' => '&nrarr;', '↝' => '&rarrw;', '↝̸' => '&nrarrw', '↞' => '&Larr;', '↟' => '&Uarr;', '↠' => '&twoheadrightarrow;', '↡' => '&Darr;', '↢' => '&larrtl;', '↣' => '&rarrtl;', '↤' => '&LeftTeeArrow;', '↥' => '&UpTeeArrow;', '↦' => '&map;', '↧' => '&DownTeeArrow;', '↩' => '&larrhk;', '↪' => '&rarrhk;', '↫' => '&larrlp;', '↬' => '&looparrowright;', '↭' => '&harrw;', '↮' => '&nleftrightarrow;', '↰' => '&Lsh;', '↱' => '&rsh;', '↲' => '&ldsh;', '↳' => '&rdsh;', '↵' => '&crarr;', '↶' => '&curvearrowleft;', '↷' => '&curarr;', '↺' => '&olarr;', '↻' => '&orarr;', '↼' => '&leftharpoonup;', '↽' => '&leftharpoondown;', '↾' => '&RightUpVector;', '↿' => '&uharl;', '⇀' => '&rharu;', '⇁' => '&rhard;', '⇂' => '&RightDownVector;', '⇃' => '&dharl;', '⇄' => '&rightleftarrows;', '⇅' => '&udarr;', '⇆' => '&lrarr;', '⇇' => '&llarr;', '⇈' => '&upuparrows;', '⇉' => '&rrarr;', '⇊' => '&downdownarrows;', '⇋' => '&leftrightharpoons;', '⇌' => '&rightleftharpoons;', '⇍' => '&nLeftarrow;', '⇎' => '&nhArr;', '⇏' => '&nrArr;', '⇐' => '&DoubleLeftArrow;', '⇑' => '&DoubleUpArrow;', '⇒' => '&Implies;', '⇓' => '&Downarrow;', '⇔' => '&hArr;', '⇕' => '&Updownarrow;', '⇖' => '&nwArr;', '⇗' => '&neArr;', '⇘' => '&seArr;', '⇙' => '&swArr;', '⇚' => '&lAarr;', '⇛' => '&rAarr;', '⇝' => '&zigrarr;', '⇤' => '&LeftArrowBar;', '⇥' => '&RightArrowBar;', '⇵' => '&DownArrowUpArrow;', '⇽' => '&loarr;', '⇾' => '&roarr;', '⇿' => '&hoarr;', '∀' => '&forall;', '∁' => '&comp;', '∂' => '&part;', '∂̸' => '&npart', '∃' => '&Exists;', '∄' => '&nexist;', '∅' => '&empty;', '∇' => '&nabla;', '∈' => '&isinv;', '∉' => '&notin;', '∋' => '&ReverseElement;', '∌' => '&notniva;', '∏' => '&prod;', '∐' => '&Coproduct;', '∑' => '&sum;', '−' => '&minus;', '∓' => '&MinusPlus;', '∔' => '&plusdo;', '∖' => '&ssetmn;', '∗' => '&lowast;', '∘' => '&compfn;', '√' => '&Sqrt;', '∝' => '&prop;', '∞' => '&infin;', '∟' => '&angrt;', '∠' => '&angle;', '∠⃒' => '&nang', '∡' => '&angmsd;', '∢' => '&angsph;', '∣' => '&mid;', '∤' => '&nshortmid;', '∥' => '&shortparallel;', '∦' => '&nparallel;', '∧' => '&and;', '∨' => '&or;', '∩' => '&cap;', '∩︀' => '&caps', '∪' => '&cup;', '∪︀' => '&cups', '∫' => '&Integral;', '∬' => '&Int;', '∭' => '&tint;', '∮' => '&ContourIntegral;', '∯' => '&DoubleContourIntegral;', '∰' => '&Cconint;', '∱' => '&cwint;', '∲' => '&cwconint;', '∳' => '&awconint;', '∴' => '&there4;', '∵' => '&Because;', '∶' => '&ratio;', '∷' => '&Colon;', '∸' => '&minusd;', '∺' => '&mDDot;', '∻' => '&homtht;', '∼' => '&sim;', '∼⃒' => '&nvsim', '∽' => '&bsim;', '∽̱' => '&race', '∾' => '&ac;', '∾̳' => '&acE', '∿' => '&acd;', '≀' => '&wr;', '≁' => '&NotTilde;', '≂' => '&esim;', '≂̸' => '&nesim', '≃' => '&simeq;', '≄' => '&nsime;', '≅' => '&TildeFullEqual;', '≆' => '&simne;', '≇' => '&ncong;', '≈' => '&approx;', '≉' => '&napprox;', '≊' => '&ape;', '≋' => '&apid;', '≋̸' => '&napid', '≌' => '&bcong;', '≍' => '&CupCap;', '≍⃒' => '&nvap', '≎' => '&bump;', '≎̸' => '&nbump', '≏' => '&HumpEqual;', '≏̸' => '&nbumpe', '≐' => '&esdot;', '≐̸' => '&nedot', '≑' => '&doteqdot;', '≒' => '&fallingdotseq;', '≓' => '&risingdotseq;', '≔' => '&coloneq;', '≕' => '&eqcolon;', '≖' => '&ecir;', '≗' => '&circeq;', '≙' => '&wedgeq;', '≚' => '&veeeq;', '≜' => '&triangleq;', '≟' => '&equest;', '≠' => '&NotEqual;', '≡' => '&Congruent;', '≡⃥' => '&bnequiv', '≢' => '&NotCongruent;', '≤' => '&leq;', '≤⃒' => '&nvle', '≥' => '&ge;', '≥⃒' => '&nvge', '≦' => '&lE;', '≦̸' => '&nlE', '≧' => '&geqq;', '≧̸' => '&NotGreaterFullEqual', '≨' => '&lneqq;', '≨︀' => '&lvertneqq', '≩' => '&gneqq;', '≩︀' => '&gvertneqq', '≪' => '&ll;', '≪̸' => '&nLtv', '≪⃒' => '&nLt', '≫' => '&gg;', '≫̸' => '&NotGreaterGreater', '≫⃒' => '&nGt', '≬' => '&between;', '≭' => '&NotCupCap;', '≮' => '&NotLess;', '≯' => '&ngtr;', '≰' => '&NotLessEqual;', '≱' => '&ngeq;', '≲' => '&LessTilde;', '≳' => '&GreaterTilde;', '≴' => '&nlsim;', '≵' => '&ngsim;', '≶' => '&lessgtr;', '≷' => '&gl;', '≸' => '&ntlg;', '≹' => '&NotGreaterLess;', '≺' => '&prec;', '≻' => '&succ;', '≼' => '&PrecedesSlantEqual;', '≽' => '&succcurlyeq;', '≾' => '&precsim;', '≿' => '&SucceedsTilde;', '≿̸' => '&NotSucceedsTilde', '⊀' => '&npr;', '⊁' => '&NotSucceeds;', '⊂' => '&sub;', '⊂⃒' => '&vnsub', '⊃' => '&sup;', '⊃⃒' => '&nsupset', '⊄' => '&nsub;', '⊅' => '&nsup;', '⊆' => '&SubsetEqual;', '⊇' => '&supe;', '⊈' => '&NotSubsetEqual;', '⊉' => '&NotSupersetEqual;', '⊊' => '&subsetneq;', '⊊︀' => '&vsubne', '⊋' => '&supsetneq;', '⊋︀' => '&vsupne', '⊍' => '&cupdot;', '⊎' => '&UnionPlus;', '⊏' => '&sqsub;', '⊏̸' => '&NotSquareSubset', '⊐' => '&sqsupset;', '⊐̸' => '&NotSquareSuperset', '⊑' => '&SquareSubsetEqual;', '⊒' => '&SquareSupersetEqual;', '⊓' => '&sqcap;', '⊓︀' => '&sqcaps', '⊔' => '&sqcup;', '⊔︀' => '&sqcups', '⊕' => '&CirclePlus;', '⊖' => '&ominus;', '⊗' => '&CircleTimes;', '⊘' => '&osol;', '⊙' => '&CircleDot;', '⊚' => '&ocir;', '⊛' => '&oast;', '⊝' => '&odash;', '⊞' => '&boxplus;', '⊟' => '&boxminus;', '⊠' => '&timesb;', '⊡' => '&sdotb;', '⊢' => '&vdash;', '⊣' => '&dashv;', '⊤' => '&DownTee;', '⊥' => '&perp;', '⊧' => '&models;', '⊨' => '&DoubleRightTee;', '⊩' => '&Vdash;', '⊪' => '&Vvdash;', '⊫' => '&VDash;', '⊬' => '&nvdash;', '⊭' => '&nvDash;', '⊮' => '&nVdash;', '⊯' => '&nVDash;', '⊰' => '&prurel;', '⊲' => '&vartriangleleft;', '⊳' => '&vrtri;', '⊴' => '&LeftTriangleEqual;', '⊴⃒' => '&nvltrie', '⊵' => '&RightTriangleEqual;', '⊵⃒' => '&nvrtrie', '⊶' => '&origof;', '⊷' => '&imof;', '⊸' => '&mumap;', '⊹' => '&hercon;', '⊺' => '&intcal;', '⊻' => '&veebar;', '⊽' => '&barvee;', '⊾' => '&angrtvb;', '⊿' => '&lrtri;', '⋀' => '&xwedge;', '⋁' => '&xvee;', '⋂' => '&bigcap;', '⋃' => '&bigcup;', '⋄' => '&diamond;', '⋅' => '&sdot;', '⋆' => '&Star;', '⋇' => '&divonx;', '⋈' => '&bowtie;', '⋉' => '&ltimes;', '⋊' => '&rtimes;', '⋋' => '&lthree;', '⋌' => '&rthree;', '⋍' => '&backsimeq;', '⋎' => '&curlyvee;', '⋏' => '&curlywedge;', '⋐' => '&Sub;', '⋑' => '&Supset;', '⋒' => '&Cap;', '⋓' => '&Cup;', '⋔' => '&pitchfork;', '⋕' => '&epar;', '⋖' => '&lessdot;', '⋗' => '&gtrdot;', '⋘' => '&Ll;', '⋘̸' => '&nLl', '⋙' => '&Gg;', '⋙̸' => '&nGg', '⋚' => '&lesseqgtr;', '⋚︀' => '&lesg', '⋛' => '&gtreqless;', '⋛︀' => '&gesl', '⋞' => '&curlyeqprec;', '⋟' => '&cuesc;', '⋠' => '&NotPrecedesSlantEqual;', '⋡' => '&NotSucceedsSlantEqual;', '⋢' => '&NotSquareSubsetEqual;', '⋣' => '&NotSquareSupersetEqual;', '⋦' => '&lnsim;', '⋧' => '&gnsim;', '⋨' => '&precnsim;', '⋩' => '&scnsim;', '⋪' => '&nltri;', '⋫' => '&ntriangleright;', '⋬' => '&nltrie;', '⋭' => '&NotRightTriangleEqual;', '⋮' => '&vellip;', '⋯' => '&ctdot;', '⋰' => '&utdot;', '⋱' => '&dtdot;', '⋲' => '&disin;', '⋳' => '&isinsv;', '⋴' => '&isins;', '⋵' => '&isindot;', '⋵̸' => '&notindot', '⋶' => '&notinvc;', '⋷' => '&notinvb;', '⋹' => '&isinE;', '⋹̸' => '&notinE', '⋺' => '&nisd;', '⋻' => '&xnis;', '⋼' => '&nis;', '⋽' => '&notnivc;', '⋾' => '&notnivb;', '⌅' => '&barwed;', '⌆' => '&doublebarwedge;', '⌈' => '&lceil;', '⌉' => '&RightCeiling;', '⌊' => '&LeftFloor;', '⌋' => '&RightFloor;', '⌌' => '&drcrop;', '⌍' => '&dlcrop;', '⌎' => '&urcrop;', '⌏' => '&ulcrop;', '⌐' => '&bnot;', '⌒' => '&profline;', '⌓' => '&profsurf;', '⌕' => '&telrec;', '⌖' => '&target;', '⌜' => '&ulcorner;', '⌝' => '&urcorner;', '⌞' => '&llcorner;', '⌟' => '&drcorn;', '⌢' => '&frown;', '⌣' => '&smile;', '⌭' => '&cylcty;', '⌮' => '&profalar;', '⌶' => '&topbot;', '⌽' => '&ovbar;', '⌿' => '&solbar;', '⍼' => '&angzarr;', '⎰' => '&lmoust;', '⎱' => '&rmoust;', '⎴' => '&OverBracket;', '⎵' => '&bbrk;', '⎶' => '&bbrktbrk;', '⏜' => '&OverParenthesis;', '⏝' => '&UnderParenthesis;', '⏞' => '&OverBrace;', '⏟' => '&UnderBrace;', '⏢' => '&trpezium;', '⏧' => '&elinters;', '␣' => '&blank;', 'Ⓢ' => '&oS;', '─' => '&HorizontalLine;', '│' => '&boxv;', '┌' => '&boxdr;', '┐' => '&boxdl;', '└' => '&boxur;', '┘' => '&boxul;', '├' => '&boxvr;', '┤' => '&boxvl;', '┬' => '&boxhd;', '┴' => '&boxhu;', '┼' => '&boxvh;', '═' => '&boxH;', '║' => '&boxV;', '╒' => '&boxdR;', '╓' => '&boxDr;', '╔' => '&boxDR;', '╕' => '&boxdL;', '╖' => '&boxDl;', '╗' => '&boxDL;', '╘' => '&boxuR;', '╙' => '&boxUr;', '╚' => '&boxUR;', '╛' => '&boxuL;', '╜' => '&boxUl;', '╝' => '&boxUL;', '╞' => '&boxvR;', '╟' => '&boxVr;', '╠' => '&boxVR;', '╡' => '&boxvL;', '╢' => '&boxVl;', '╣' => '&boxVL;', '╤' => '&boxHd;', '╥' => '&boxhD;', '╦' => '&boxHD;', '╧' => '&boxHu;', '╨' => '&boxhU;', '╩' => '&boxHU;', '╪' => '&boxvH;', '╫' => '&boxVh;', '╬' => '&boxVH;', '▀' => '&uhblk;', '▄' => '&lhblk;', '█' => '&block;', '░' => '&blk14;', '▒' => '&blk12;', '▓' => '&blk34;', '□' => '&Square;', '▪' => '&squarf;', '▫' => '&EmptyVerySmallSquare;', '▭' => '&rect;', '▮' => '&marker;', '▱' => '&fltns;', '△' => '&bigtriangleup;', '▴' => '&blacktriangle;', '▵' => '&triangle;', '▸' => '&blacktriangleright;', '▹' => '&rtri;', '▽' => '&bigtriangledown;', '▾' => '&blacktriangledown;', '▿' => '&triangledown;', '◂' => '&blacktriangleleft;', '◃' => '&ltri;', '◊' => '&lozenge;', '○' => '&cir;', '◬' => '&tridot;', '◯' => '&bigcirc;', '◸' => '&ultri;', '◹' => '&urtri;', '◺' => '&lltri;', '◻' => '&EmptySmallSquare;', '◼' => '&FilledSmallSquare;', '★' => '&starf;', '☆' => '&star;', '☎' => '&phone;', '♀' => '&female;', '♂' => '&male;', '♠' => '&spadesuit;', '♣' => '&clubs;', '♥' => '&hearts;', '♦' => '&diamondsuit;', '♪' => '&sung;', '♭' => '&flat;', '♮' => '&natur;', '♯' => '&sharp;', '✓' => '&check;', '✗' => '&cross;', '✠' => '&maltese;', '✶' => '&sext;', '❘' => '&VerticalSeparator;', '❲' => '&lbbrk;', '❳' => '&rbbrk;', '⟈' => '&bsolhsub;', '⟉' => '&suphsol;', '⟦' => '&LeftDoubleBracket;', '⟧' => '&RightDoubleBracket;', '⟨' => '&langle;', '⟩' => '&RightAngleBracket;', '⟪' => '&Lang;', '⟫' => '&Rang;', '⟬' => '&loang;', '⟭' => '&roang;', '⟵' => '&longleftarrow;', '⟶' => '&LongRightArrow;', '⟷' => '&LongLeftRightArrow;', '⟸' => '&xlArr;', '⟹' => '&DoubleLongRightArrow;', '⟺' => '&xhArr;', '⟼' => '&xmap;', '⟿' => '&dzigrarr;', '⤂' => '&nvlArr;', '⤃' => '&nvrArr;', '⤄' => '&nvHarr;', '⤅' => '&Map;', '⤌' => '&lbarr;', '⤍' => '&bkarow;', '⤎' => '&lBarr;', '⤏' => '&dbkarow;', '⤐' => '&drbkarow;', '⤑' => '&DDotrahd;', '⤒' => '&UpArrowBar;', '⤓' => '&DownArrowBar;', '⤖' => '&Rarrtl;', '⤙' => '&latail;', '⤚' => '&ratail;', '⤛' => '&lAtail;', '⤜' => '&rAtail;', '⤝' => '&larrfs;', '⤞' => '&rarrfs;', '⤟' => '&larrbfs;', '⤠' => '&rarrbfs;', '⤣' => '&nwarhk;', '⤤' => '&nearhk;', '⤥' => '&searhk;', '⤦' => '&swarhk;', '⤧' => '&nwnear;', '⤨' => '&toea;', '⤩' => '&seswar;', '⤪' => '&swnwar;', '⤳' => '&rarrc;', '⤳̸' => '&nrarrc', '⤵' => '&cudarrr;', '⤶' => '&ldca;', '⤷' => '&rdca;', '⤸' => '&cudarrl;', '⤹' => '&larrpl;', '⤼' => '&curarrm;', '⤽' => '&cularrp;', '⥅' => '&rarrpl;', '⥈' => '&harrcir;', '⥉' => '&Uarrocir;', '⥊' => '&lurdshar;', '⥋' => '&ldrushar;', '⥎' => '&LeftRightVector;', '⥏' => '&RightUpDownVector;', '⥐' => '&DownLeftRightVector;', '⥑' => '&LeftUpDownVector;', '⥒' => '&LeftVectorBar;', '⥓' => '&RightVectorBar;', '⥔' => '&RightUpVectorBar;', '⥕' => '&RightDownVectorBar;', '⥖' => '&DownLeftVectorBar;', '⥗' => '&DownRightVectorBar;', '⥘' => '&LeftUpVectorBar;', '⥙' => '&LeftDownVectorBar;', '⥚' => '&LeftTeeVector;', '⥛' => '&RightTeeVector;', '⥜' => '&RightUpTeeVector;', '⥝' => '&RightDownTeeVector;', '⥞' => '&DownLeftTeeVector;', '⥟' => '&DownRightTeeVector;', '⥠' => '&LeftUpTeeVector;', '⥡' => '&LeftDownTeeVector;', '⥢' => '&lHar;', '⥣' => '&uHar;', '⥤' => '&rHar;', '⥥' => '&dHar;', '⥦' => '&luruhar;', '⥧' => '&ldrdhar;', '⥨' => '&ruluhar;', '⥩' => '&rdldhar;', '⥪' => '&lharul;', '⥫' => '&llhard;', '⥬' => '&rharul;', '⥭' => '&lrhard;', '⥮' => '&udhar;', '⥯' => '&ReverseUpEquilibrium;', '⥰' => '&RoundImplies;', '⥱' => '&erarr;', '⥲' => '&simrarr;', '⥳' => '&larrsim;', '⥴' => '&rarrsim;', '⥵' => '&rarrap;', '⥶' => '&ltlarr;', '⥸' => '&gtrarr;', '⥹' => '&subrarr;', '⥻' => '&suplarr;', '⥼' => '&lfisht;', '⥽' => '&rfisht;', '⥾' => '&ufisht;', '⥿' => '&dfisht;', '⦅' => '&lopar;', '⦆' => '&ropar;', '⦋' => '&lbrke;', '⦌' => '&rbrke;', '⦍' => '&lbrkslu;', '⦎' => '&rbrksld;', '⦏' => '&lbrksld;', '⦐' => '&rbrkslu;', '⦑' => '&langd;', '⦒' => '&rangd;', '⦓' => '&lparlt;', '⦔' => '&rpargt;', '⦕' => '&gtlPar;', '⦖' => '&ltrPar;', '⦚' => '&vzigzag;', '⦜' => '&vangrt;', '⦝' => '&angrtvbd;', '⦤' => '&ange;', '⦥' => '&range;', '⦦' => '&dwangle;', '⦧' => '&uwangle;', '⦨' => '&angmsdaa;', '⦩' => '&angmsdab;', '⦪' => '&angmsdac;', '⦫' => '&angmsdad;', '⦬' => '&angmsdae;', '⦭' => '&angmsdaf;', '⦮' => '&angmsdag;', '⦯' => '&angmsdah;', '⦰' => '&bemptyv;', '⦱' => '&demptyv;', '⦲' => '&cemptyv;', '⦳' => '&raemptyv;', '⦴' => '&laemptyv;', '⦵' => '&ohbar;', '⦶' => '&omid;', '⦷' => '&opar;', '⦹' => '&operp;', '⦻' => '&olcross;', '⦼' => '&odsold;', '⦾' => '&olcir;', '⦿' => '&ofcir;', '⧀' => '&olt;', '⧁' => '&ogt;', '⧂' => '&cirscir;', '⧃' => '&cirE;', '⧄' => '&solb;', '⧅' => '&bsolb;', '⧉' => '&boxbox;', '⧍' => '&trisb;', '⧎' => '&rtriltri;', '⧏' => '&LeftTriangleBar;', '⧏̸' => '&NotLeftTriangleBar', '⧐' => '&RightTriangleBar;', '⧐̸' => '&NotRightTriangleBar', '⧜' => '&iinfin;', '⧝' => '&infintie;', '⧞' => '&nvinfin;', '⧣' => '&eparsl;', '⧤' => '&smeparsl;', '⧥' => '&eqvparsl;', '⧫' => '&lozf;', '⧴' => '&RuleDelayed;', '⧶' => '&dsol;', '⨀' => '&xodot;', '⨁' => '&bigoplus;', '⨂' => '&bigotimes;', '⨄' => '&biguplus;', '⨆' => '&bigsqcup;', '⨌' => '&iiiint;', '⨍' => '&fpartint;', '⨐' => '&cirfnint;', '⨑' => '&awint;', '⨒' => '&rppolint;', '⨓' => '&scpolint;', '⨔' => '&npolint;', '⨕' => '&pointint;', '⨖' => '&quatint;', '⨗' => '&intlarhk;', '⨢' => '&pluscir;', '⨣' => '&plusacir;', '⨤' => '&simplus;', '⨥' => '&plusdu;', '⨦' => '&plussim;', '⨧' => '&plustwo;', '⨩' => '&mcomma;', '⨪' => '&minusdu;', '⨭' => '&loplus;', '⨮' => '&roplus;', '⨯' => '&Cross;', '⨰' => '&timesd;', '⨱' => '&timesbar;', '⨳' => '&smashp;', '⨴' => '&lotimes;', '⨵' => '&rotimes;', '⨶' => '&otimesas;', '⨷' => '&Otimes;', '⨸' => '&odiv;', '⨹' => '&triplus;', '⨺' => '&triminus;', '⨻' => '&tritime;', '⨼' => '&iprod;', '⨿' => '&amalg;', '⩀' => '&capdot;', '⩂' => '&ncup;', '⩃' => '&ncap;', '⩄' => '&capand;', '⩅' => '&cupor;', '⩆' => '&cupcap;', '⩇' => '&capcup;', '⩈' => '&cupbrcap;', '⩉' => '&capbrcup;', '⩊' => '&cupcup;', '⩋' => '&capcap;', '⩌' => '&ccups;', '⩍' => '&ccaps;', '⩐' => '&ccupssm;', '⩓' => '&And;', '⩔' => '&Or;', '⩕' => '&andand;', '⩖' => '&oror;', '⩗' => '&orslope;', '⩘' => '&andslope;', '⩚' => '&andv;', '⩛' => '&orv;', '⩜' => '&andd;', '⩝' => '&ord;', '⩟' => '&wedbar;', '⩦' => '&sdote;', '⩪' => '&simdot;', '⩭' => '&congdot;', '⩭̸' => '&ncongdot', '⩮' => '&easter;', '⩯' => '&apacir;', '⩰' => '&apE;', '⩰̸' => '&napE', '⩱' => '&eplus;', '⩲' => '&pluse;', '⩳' => '&Esim;', '⩴' => '&Colone;', '⩵' => '&Equal;', '⩷' => '&ddotseq;', '⩸' => '&equivDD;', '⩹' => '&ltcir;', '⩺' => '&gtcir;', '⩻' => '&ltquest;', '⩼' => '&gtquest;', '⩽' => '&les;', '⩽̸' => '&nles', '⩾' => '&ges;', '⩾̸' => '&nges', '⩿' => '&lesdot;', '⪀' => '&gesdot;', '⪁' => '&lesdoto;', '⪂' => '&gesdoto;', '⪃' => '&lesdotor;', '⪄' => '&gesdotol;', '⪅' => '&lap;', '⪆' => '&gap;', '⪇' => '&lne;', '⪈' => '&gne;', '⪉' => '&lnap;', '⪊' => '&gnap;', '⪋' => '&lesseqqgtr;', '⪌' => '&gEl;', '⪍' => '&lsime;', '⪎' => '&gsime;', '⪏' => '&lsimg;', '⪐' => '&gsiml;', '⪑' => '&lgE;', '⪒' => '&glE;', '⪓' => '&lesges;', '⪔' => '&gesles;', '⪕' => '&els;', '⪖' => '&egs;', '⪗' => '&elsdot;', '⪘' => '&egsdot;', '⪙' => '&el;', '⪚' => '&eg;', '⪝' => '&siml;', '⪞' => '&simg;', '⪟' => '&simlE;', '⪠' => '&simgE;', '⪡' => '&LessLess;', '⪡̸' => '&NotNestedLessLess', '⪢' => '&GreaterGreater;', '⪢̸' => '&NotNestedGreaterGreater', '⪤' => '&glj;', '⪥' => '&gla;', '⪦' => '&ltcc;', '⪧' => '&gtcc;', '⪨' => '&lescc;', '⪩' => '&gescc;', '⪪' => '&smt;', '⪫' => '&lat;', '⪬' => '&smte;', '⪬︀' => '&smtes', '⪭' => '&late;', '⪭︀' => '&lates', '⪮' => '&bumpE;', '⪯' => '&preceq;', '⪯̸' => '&NotPrecedesEqual', '⪰' => '&SucceedsEqual;', '⪰̸' => '&NotSucceedsEqual', '⪳' => '&prE;', '⪴' => '&scE;', '⪵' => '&precneqq;', '⪶' => '&scnE;', '⪷' => '&precapprox;', '⪸' => '&succapprox;', '⪹' => '&precnapprox;', '⪺' => '&succnapprox;', '⪻' => '&Pr;', '⪼' => '&Sc;', '⪽' => '&subdot;', '⪾' => '&supdot;', '⪿' => '&subplus;', '⫀' => '&supplus;', '⫁' => '&submult;', '⫂' => '&supmult;', '⫃' => '&subedot;', '⫄' => '&supedot;', '⫅' => '&subE;', '⫅̸' => '&nsubE', '⫆' => '&supseteqq;', '⫆̸' => '&nsupseteqq', '⫇' => '&subsim;', '⫈' => '&supsim;', '⫋' => '&subsetneqq;', '⫋︀' => '&vsubnE', '⫌' => '&supnE;', '⫌︀' => '&varsupsetneqq', '⫏' => '&csub;', '⫐' => '&csup;', '⫑' => '&csube;', '⫒' => '&csupe;', '⫓' => '&subsup;', '⫔' => '&supsub;', '⫕' => '&subsub;', '⫖' => '&supsup;', '⫗' => '&suphsub;', '⫘' => '&supdsub;', '⫙' => '&forkv;', '⫚' => '&topfork;', '⫛' => '&mlcp;', '⫤' => '&Dashv;', '⫦' => '&Vdashl;', '⫧' => '&Barv;', '⫨' => '&vBar;', '⫩' => '&vBarv;', '⫫' => '&Vbar;', '⫬' => '&Not;', '⫭' => '&bNot;', '⫮' => '&rnmid;', '⫯' => '&cirmid;', '⫰' => '&midcir;', '⫱' => '&topcir;', '⫲' => '&nhpar;', '⫳' => '&parsim;', '⫽︀' => '&varsupsetneqq', 'ﬀ' => '&fflig;', 'ﬁ' => '&filig;', 'ﬂ' => '&fllig;', 'ﬃ' => '&ffilig;', 'ﬄ' => '&ffllig;', '𝒜' => '&Ascr;', '𝒞' => '&Cscr;', '𝒟' => '&Dscr;', '𝒢' => '&Gscr;', '𝒥' => '&Jscr;', '𝒦' => '&Kscr;', '𝒩' => '&Nscr;', '𝒪' => '&Oscr;', '𝒫' => '&Pscr;', '𝒬' => '&Qscr;', '𝒮' => '&Sscr;', '𝒯' => '&Tscr;', '𝒰' => '&Uscr;', '𝒱' => '&Vscr;', '𝒲' => '&Wscr;', '𝒳' => '&Xscr;', '𝒴' => '&Yscr;', '𝒵' => '&Zscr;', '𝒶' => '&ascr;', '𝒷' => '&bscr;', '𝒸' => '&cscr;', '𝒹' => '&dscr;', '𝒻' => '&fscr;', '𝒽' => '&hscr;', '𝒾' => '&iscr;', '𝒿' => '&jscr;', '𝓀' => '&kscr;', '𝓁' => '&lscr;', '𝓂' => '&mscr;', '𝓃' => '&nscr;', '𝓅' => '&pscr;', '𝓆' => '&qscr;', '𝓇' => '&rscr;', '𝓈' => '&sscr;', '𝓉' => '&tscr;', '𝓊' => '&uscr;', '𝓋' => '&vscr;', '𝓌' => '&wscr;', '𝓍' => '&xscr;', '𝓎' => '&yscr;', '𝓏' => '&zscr;', '𝔄' => '&Afr;', '𝔅' => '&Bfr;', '𝔇' => '&Dfr;', '𝔈' => '&Efr;', '𝔉' => '&Ffr;', '𝔊' => '&Gfr;', '𝔍' => '&Jfr;', '𝔎' => '&Kfr;', '𝔏' => '&Lfr;', '𝔐' => '&Mfr;', '𝔑' => '&Nfr;', '𝔒' => '&Ofr;', '𝔓' => '&Pfr;', '𝔔' => '&Qfr;', '𝔖' => '&Sfr;', '𝔗' => '&Tfr;', '𝔘' => '&Ufr;', '𝔙' => '&Vfr;', '𝔚' => '&Wfr;', '𝔛' => '&Xfr;', '𝔜' => '&Yfr;', '𝔞' => '&afr;', '𝔟' => '&bfr;', '𝔠' => '&cfr;', '𝔡' => '&dfr;', '𝔢' => '&efr;', '𝔣' => '&ffr;', '𝔤' => '&gfr;', '𝔥' => '&hfr;', '𝔦' => '&ifr;', '𝔧' => '&jfr;', '𝔨' => '&kfr;', '𝔩' => '&lfr;', '𝔪' => '&mfr;', '𝔫' => '&nfr;', '𝔬' => '&ofr;', '𝔭' => '&pfr;', '𝔮' => '&qfr;', '𝔯' => '&rfr;', '𝔰' => '&sfr;', '𝔱' => '&tfr;', '𝔲' => '&ufr;', '𝔳' => '&vfr;', '𝔴' => '&wfr;', '𝔵' => '&xfr;', '𝔶' => '&yfr;', '𝔷' => '&zfr;', '𝔸' => '&Aopf;', '𝔹' => '&Bopf;', '𝔻' => '&Dopf;', '𝔼' => '&Eopf;', '𝔽' => '&Fopf;', '𝔾' => '&Gopf;', '𝕀' => '&Iopf;', '𝕁' => '&Jopf;', '𝕂' => '&Kopf;', '𝕃' => '&Lopf;', '𝕄' => '&Mopf;', '𝕆' => '&Oopf;', '𝕊' => '&Sopf;', '𝕋' => '&Topf;', '𝕌' => '&Uopf;', '𝕍' => '&Vopf;', '𝕎' => '&Wopf;', '𝕏' => '&Xopf;', '𝕐' => '&Yopf;', '𝕒' => '&aopf;', '𝕓' => '&bopf;', '𝕔' => '&copf;', '𝕕' => '&dopf;', '𝕖' => '&eopf;', '𝕗' => '&fopf;', '𝕘' => '&gopf;', '𝕙' => '&hopf;', '𝕚' => '&iopf;', '𝕛' => '&jopf;', '𝕜' => '&kopf;', '𝕝' => '&lopf;', '𝕞' => '&mopf;', '𝕟' => '&nopf;', '𝕠' => '&oopf;', '𝕡' => '&popf;', '𝕢' => '&qopf;', '𝕣' => '&ropf;', '𝕤' => '&sopf;', '𝕥' => '&topf;', '𝕦' => '&uopf;', '𝕧' => '&vopf;', '𝕨' => '&wopf;', '𝕩' => '&xopf;', '𝕪' => '&yopf;', '𝕫' => '&zopf;', ); } namespace AimySpeedOptimization\Masterminds\HTML5\Serializer; class Traverser { protected static $local_ns = array( 'http://www.w3.org/1999/xhtml' => 'html', 'http://www.w3.org/1998/Math/MathML' => 'math', 'http://www.w3.org/2000/svg' => 'svg', ); protected $dom; protected $options; protected $encode = false; protected $rules; protected $out; public function __construct($dom, $out, RulesInterface $rules, $options = array()) { $this->dom = $dom; $this->out = $out; $this->rules = $rules; $this->options = $options; $this->rules->setTraverser($this); } public function walk() { if ($this->dom instanceof \DOMDocument) { $this->rules->document($this->dom); } elseif ($this->dom instanceof \DOMDocumentFragment) { if ($this->dom->hasChildNodes()) { $this->children($this->dom->childNodes); } } elseif ($this->dom instanceof \DOMNodeList) { $this->children($this->dom); } else { $this->node($this->dom); } return $this->out; } public function node($node) { switch ($node->nodeType) { case XML_ELEMENT_NODE: $this->rules->element($node); break; case XML_TEXT_NODE: $this->rules->text($node); break; case XML_CDATA_SECTION_NODE: $this->rules->cdata($node); break; case XML_PI_NODE: $this->rules->processorInstruction($node); break; case XML_COMMENT_NODE: $this->rules->comment($node); break; default: break; } } public function children($nl) { foreach ($nl as $node) { $this->node($node); } } public function isLocalElement($ele) { $uri = $ele->namespaceURI; if (empty($uri)) { return false; } return isset(static::$local_ns[$uri]); } } namespace AimySpeedOptimization\Masterminds\HTML5\Serializer; interface RulesInterface { public function __construct($output, $options = array()); public function setTraverser(Traverser $traverser); public function document($dom); public function element($ele); public function text($ele); public function cdata($ele); public function comment($ele); public function processorInstruction($ele); } namespace AimySpeedOptimization\Masterminds\HTML5\Serializer; use AimySpeedOptimization\Masterminds\HTML5\Elements; class OutputRules implements RulesInterface { const NAMESPACE_HTML = 'http://www.w3.org/1999/xhtml'; const NAMESPACE_MATHML = 'http://www.w3.org/1998/Math/MathML'; const NAMESPACE_SVG = 'http://www.w3.org/2000/svg'; const NAMESPACE_XLINK = 'http://www.w3.org/1999/xlink'; const NAMESPACE_XML = 'http://www.w3.org/XML/1998/namespace'; const NAMESPACE_XMLNS = 'http://www.w3.org/2000/xmlns/'; protected $implicitNamespaces = array( self::NAMESPACE_HTML, self::NAMESPACE_SVG, self::NAMESPACE_MATHML, self::NAMESPACE_XML, self::NAMESPACE_XMLNS, ); const IM_IN_HTML = 1; const IM_IN_SVG = 2; const IM_IN_MATHML = 3; private $hasHTML5 = false; protected $traverser; protected $encode = false; protected $out; protected $outputMode; private $xpath; protected $nonBooleanAttributes = array( array( 'nodeNamespace' => 'http://www.w3.org/1999/xhtml', 'attrName' => array('href', 'hreflang', 'http-equiv', 'icon', 'id', 'keytype', 'kind', 'label', 'lang', 'language', 'list', 'maxlength', 'media', 'method', 'name', 'placeholder', 'rel', 'rows', 'rowspan', 'sandbox', 'spellcheck', 'scope', 'seamless', 'shape', 'size', 'sizes', 'span', 'src', 'srcdoc', 'srclang', 'srcset', 'start', 'step', 'style', 'summary', 'tabindex', 'target', 'title', 'type', 'value', 'width', 'border', 'charset', 'cite', 'class', 'code', 'codebase', 'color', 'cols', 'colspan', 'content', 'coords', 'data', 'datetime', 'default', 'dir', 'dirname', 'enctype', 'for', 'form', 'formaction', 'headers', 'height', 'accept', 'accept-charset', 'accesskey', 'action', 'align', 'alt', 'bgcolor', ), ), array( 'nodeNamespace' => 'http://www.w3.org/1999/xhtml', 'xpath' => 'starts-with(local-name(), \'data-\')', ), ); const DOCTYPE = '<!DOCTYPE html>'; public function __construct($output, $options = array()) { if (isset($options['encode_entities'])) { $this->encode = $options['encode_entities']; } $this->outputMode = static::IM_IN_HTML; $this->out = $output; $this->hasHTML5 = defined('ENT_HTML5'); } public function addRule(array $rule) { $this->nonBooleanAttributes[] = $rule; } public function setTraverser(Traverser $traverser) { $this->traverser = $traverser; return $this; } public function unsetTraverser() { $this->traverser = null; return $this; } public function document($dom) { $this->doctype(); if ($dom->documentElement) { foreach ($dom->childNodes as $node) { $this->traverser->node($node); } $this->nl(); } } protected function doctype() { $this->wr(static::DOCTYPE); $this->nl(); } public function element($ele) { $name = $ele->tagName; if ($this->traverser->isLocalElement($ele)) { $name = $ele->localName; } if ('svg' == $name) { $this->outputMode = static::IM_IN_SVG; $name = Elements::normalizeSvgElement($name); } elseif ('math' == $name) { $this->outputMode = static::IM_IN_MATHML; } $this->openTag($ele); if (Elements::isA($name, Elements::TEXT_RAW)) { foreach ($ele->childNodes as $child) { if ($child instanceof \DOMCharacterData) { $this->wr($child->data); } elseif ($child instanceof \DOMElement) { $this->element($child); } } } else { if ($ele->hasChildNodes()) { $this->traverser->children($ele->childNodes); } if ('svg' == $name || 'math' == $name) { $this->outputMode = static::IM_IN_HTML; } } if (!Elements::isA($name, Elements::VOID_TAG)) { $this->closeTag($ele); } } public function text($ele) { if (isset($ele->parentNode) && isset($ele->parentNode->tagName) && Elements::isA($ele->parentNode->localName, Elements::TEXT_RAW)) { $this->wr($ele->data); return; } $this->wr($this->enc($ele->data)); } public function cdata($ele) { $this->wr($ele->ownerDocument->saveXML($ele)); } public function comment($ele) { $this->wr($ele->ownerDocument->saveXML($ele)); } public function processorInstruction($ele) { $this->wr('<?') ->wr($ele->target) ->wr(' ') ->wr($ele->data) ->wr('?>'); } protected function namespaceAttrs($ele) { if (!$this->xpath || $this->xpath->document !== $ele->ownerDocument) { $this->xpath = new \DOMXPath($ele->ownerDocument); } foreach ($this->xpath->query('namespace::*[not(.=../../namespace::*)]', $ele) as $nsNode) { if (!in_array($nsNode->nodeValue, $this->implicitNamespaces)) { $this->wr(' ')->wr($nsNode->nodeName)->wr('="')->wr($nsNode->nodeValue)->wr('"'); } } } protected function openTag($ele) { $this->wr('<')->wr($this->traverser->isLocalElement($ele) ? $ele->localName : $ele->tagName); $this->attrs($ele); $this->namespaceAttrs($ele); if ($this->outputMode == static::IM_IN_HTML) { $this->wr('>'); } else { if ($ele->hasChildNodes()) { $this->wr('>'); } else { $this->wr(' />'); } } } protected function attrs($ele) { if (!$ele->hasAttributes()) { return $this; } $map = $ele->attributes; $len = $map->length; for ($i = 0; $i < $len; ++$i) { $node = $map->item($i); $val = $this->enc($node->value, true); $name = $node->nodeName; if ($this->outputMode == static::IM_IN_SVG) { $name = Elements::normalizeSvgAttribute($name); } elseif ($this->outputMode == static::IM_IN_MATHML) { $name = Elements::normalizeMathMlAttribute($name); } $this->wr(' ')->wr($name); if ((isset($val) && '' !== $val) || $this->nonBooleanAttribute($node)) { $this->wr('="')->wr($val)->wr('"'); } } } protected function nonBooleanAttribute(\DOMAttr $attr) { $ele = $attr->ownerElement; foreach ($this->nonBooleanAttributes as $rule) { if (isset($rule['nodeNamespace']) && $rule['nodeNamespace'] !== $ele->namespaceURI) { continue; } if (isset($rule['attNamespace']) && $rule['attNamespace'] !== $attr->namespaceURI) { continue; } if (isset($rule['nodeName']) && !is_array($rule['nodeName']) && $rule['nodeName'] !== $ele->localName) { continue; } if (isset($rule['nodeName']) && is_array($rule['nodeName']) && !in_array($ele->localName, $rule['nodeName'], true)) { continue; } if (isset($rule['attrName']) && !is_array($rule['attrName']) && $rule['attrName'] !== $attr->localName) { continue; } if (isset($rule['attrName']) && is_array($rule['attrName']) && !in_array($attr->localName, $rule['attrName'], true)) { continue; } if (isset($rule['xpath'])) { $xp = $this->getXPath($attr); if (isset($rule['prefixes'])) { foreach ($rule['prefixes'] as $nsPrefix => $ns) { $xp->registerNamespace($nsPrefix, $ns); } } if (!$xp->evaluate($rule['xpath'], $attr)) { continue; } } return true; } return false; } private function getXPath(\DOMNode $node) { if (!$this->xpath) { $this->xpath = new \DOMXPath($node->ownerDocument); } return $this->xpath; } protected function closeTag($ele) { if ($this->outputMode == static::IM_IN_HTML || $ele->hasChildNodes()) { $this->wr('</')->wr($this->traverser->isLocalElement($ele) ? $ele->localName : $ele->tagName)->wr('>'); } } protected function wr($text) { fwrite($this->out, $text); return $this; } protected function nl() { fwrite($this->out, PHP_EOL); return $this; } protected function enc($text, $attribute = false) { if (!$this->encode) { return $this->escape($text, $attribute); } if ($this->hasHTML5) { return htmlentities($text, ENT_HTML5 | ENT_SUBSTITUTE | ENT_QUOTES, 'UTF-8', false); } else { return strtr($text, HTML5Entities::$map); } } protected function escape($text, $attribute = false) { if ($attribute) { $replace = array( '"' => '&quot;', '&' => '&amp;', "\xc2\xa0" => '&nbsp;', ); } else { $replace = array( '<' => '&lt;', '>' => '&gt;', '&' => '&amp;', "\xc2\xa0" => '&nbsp;', ); } return strtr($text, $replace); } } 
