diff options
author | Leonard Richardson <leonardr@segfault.org> | 2021-05-31 15:49:41 -0400 |
---|---|---|
committer | Leonard Richardson <leonardr@segfault.org> | 2021-05-31 15:49:41 -0400 |
commit | a00624d7fc2e29b41b286f46844cb75f4d96ff63 (patch) | |
tree | 339396570eeaef7e51454dd5de9c432df29cce36 | |
parent | 8d73b97105bf6534057ee93af6795a2a0aceb993 (diff) |
The html.parser tree builder can now handles named entities
found in the HTML5 spec in much the same way that the html5lib
tree builder does. Note that the lxml tree builder still handles
named entities differently. [bug=1924908]
-rw-r--r-- | CHANGELOG | 5 | ||||
-rw-r--r-- | bs4/builder/_htmlparser.py | 2 | ||||
-rw-r--r-- | bs4/dammit.py | 2387 | ||||
-rw-r--r-- | bs4/testing.py | 7 | ||||
-rw-r--r-- | bs4/tests/test_html5lib.py | 36 | ||||
-rw-r--r-- | bs4/tests/test_htmlparser.py | 32 | ||||
-rw-r--r-- | bs4/tests/test_lxml.py | 2 | ||||
-rw-r--r-- | bs4/tests/test_soup.py | 45 |
8 files changed, 2484 insertions, 32 deletions
@@ -47,6 +47,11 @@ guarantee that this will hold for the next release. the <template> tag, which may contain both TemplateString objects and Comment objects. [bug=1913406] +* The html.parser tree builder can now handles named entities + found in the HTML5 spec in much the same way that the html5lib + tree builder does. Note that the lxml tree builder still handles + named entities differently. [bug=1924908] + * Added a second way to pass specify encodings to UnicodeDammit and EncodingDetector, based on the order of precedence defined in the HTML5 spec, starting at: diff --git a/bs4/builder/_htmlparser.py b/bs4/builder/_htmlparser.py index 2f2bf1e..355be11 100644 --- a/bs4/builder/_htmlparser.py +++ b/bs4/builder/_htmlparser.py @@ -231,7 +231,7 @@ class BeautifulSoupHTMLParser(HTMLParser): def handle_entityref(self, name): """Handle a named entity reference by converting it to the - corresponding Unicode character and treating it as textual + corresponding Unicode character(s) and treating it as textual data. :param name: Name of the entity reference. diff --git a/bs4/dammit.py b/bs4/dammit.py index 7e0a7f8..a0d1c21 100644 --- a/bs4/dammit.py +++ b/bs4/dammit.py @@ -9,8 +9,9 @@ XML or HTML to reflect a new encoding; that's the tree builder's job. # Use of this source code is governed by the MIT license. __license__ = "MIT" -import codecs from htmlentitydefs import codepoint2name +from collections import defaultdict +import codecs import re import logging import string @@ -65,34 +66,2368 @@ encoding_res[unicode] = { 'xml' : re.compile(xml_encoding, re.I) } +try: + from html.entities import html5 +except ImportError: + # This is a copy of html.entities.html5 from Python 3.9. There's + # no equivalent table in Python 2, so we'll just provide a copy + # here. + html5 = { + 'Aacute': u'\xc1', + 'aacute': u'\xe1', + 'Aacute;': u'\xc1', + 'aacute;': u'\xe1', + 'Abreve;': u'\u0102', + 'abreve;': u'\u0103', + 'ac;': u'\u223e', + 'acd;': u'\u223f', + 'acE;': u'\u223e\u0333', + 'Acirc': u'\xc2', + 'acirc': u'\xe2', + 'Acirc;': u'\xc2', + 'acirc;': u'\xe2', + 'acute': u'\xb4', + 'acute;': u'\xb4', + 'Acy;': u'\u0410', + 'acy;': u'\u0430', + 'AElig': u'\xc6', + 'aelig': u'\xe6', + 'AElig;': u'\xc6', + 'aelig;': u'\xe6', + 'af;': u'\u2061', + 'Afr;': u'\U0001d504', + 'afr;': u'\U0001d51e', + 'Agrave': u'\xc0', + 'agrave': u'\xe0', + 'Agrave;': u'\xc0', + 'agrave;': u'\xe0', + 'alefsym;': u'\u2135', + 'aleph;': u'\u2135', + 'Alpha;': u'\u0391', + 'alpha;': u'\u03b1', + 'Amacr;': u'\u0100', + 'amacr;': u'\u0101', + 'amalg;': u'\u2a3f', + 'AMP': u'&', + 'amp': u'&', + 'AMP;': u'&', + 'amp;': u'&', + 'And;': u'\u2a53', + 'and;': u'\u2227', + 'andand;': u'\u2a55', + 'andd;': u'\u2a5c', + 'andslope;': u'\u2a58', + 'andv;': u'\u2a5a', + 'ang;': u'\u2220', + 'ange;': u'\u29a4', + 'angle;': u'\u2220', + 'angmsd;': u'\u2221', + 'angmsdaa;': u'\u29a8', + 'angmsdab;': u'\u29a9', + 'angmsdac;': u'\u29aa', + 'angmsdad;': u'\u29ab', + 'angmsdae;': u'\u29ac', + 'angmsdaf;': u'\u29ad', + 'angmsdag;': u'\u29ae', + 'angmsdah;': u'\u29af', + 'angrt;': u'\u221f', + 'angrtvb;': u'\u22be', + 'angrtvbd;': u'\u299d', + 'angsph;': u'\u2222', + 'angst;': u'\xc5', + 'angzarr;': u'\u237c', + 'Aogon;': u'\u0104', + 'aogon;': u'\u0105', + 'Aopf;': u'\U0001d538', + 'aopf;': u'\U0001d552', + 'ap;': u'\u2248', + 'apacir;': u'\u2a6f', + 'apE;': u'\u2a70', + 'ape;': u'\u224a', + 'apid;': u'\u224b', + 'apos;': "'", + 'ApplyFunction;': u'\u2061', + 'approx;': u'\u2248', + 'approxeq;': u'\u224a', + 'Aring': u'\xc5', + 'aring': u'\xe5', + 'Aring;': u'\xc5', + 'aring;': u'\xe5', + 'Ascr;': u'\U0001d49c', + 'ascr;': u'\U0001d4b6', + 'Assign;': u'\u2254', + 'ast;': u'*', + 'asymp;': u'\u2248', + 'asympeq;': u'\u224d', + 'Atilde': u'\xc3', + 'atilde': u'\xe3', + 'Atilde;': u'\xc3', + 'atilde;': u'\xe3', + 'Auml': u'\xc4', + 'auml': u'\xe4', + 'Auml;': u'\xc4', + 'auml;': u'\xe4', + 'awconint;': u'\u2233', + 'awint;': u'\u2a11', + 'backcong;': u'\u224c', + 'backepsilon;': u'\u03f6', + 'backprime;': u'\u2035', + 'backsim;': u'\u223d', + 'backsimeq;': u'\u22cd', + 'Backslash;': u'\u2216', + 'Barv;': u'\u2ae7', + 'barvee;': u'\u22bd', + 'Barwed;': u'\u2306', + 'barwed;': u'\u2305', + 'barwedge;': u'\u2305', + 'bbrk;': u'\u23b5', + 'bbrktbrk;': u'\u23b6', + 'bcong;': u'\u224c', + 'Bcy;': u'\u0411', + 'bcy;': u'\u0431', + 'bdquo;': u'\u201e', + 'becaus;': u'\u2235', + 'Because;': u'\u2235', + 'because;': u'\u2235', + 'bemptyv;': u'\u29b0', + 'bepsi;': u'\u03f6', + 'bernou;': u'\u212c', + 'Bernoullis;': u'\u212c', + 'Beta;': u'\u0392', + 'beta;': u'\u03b2', + 'beth;': u'\u2136', + 'between;': u'\u226c', + 'Bfr;': u'\U0001d505', + 'bfr;': u'\U0001d51f', + 'bigcap;': u'\u22c2', + 'bigcirc;': u'\u25ef', + 'bigcup;': u'\u22c3', + 'bigodot;': u'\u2a00', + 'bigoplus;': u'\u2a01', + 'bigotimes;': u'\u2a02', + 'bigsqcup;': u'\u2a06', + 'bigstar;': u'\u2605', + 'bigtriangledown;': u'\u25bd', + 'bigtriangleup;': u'\u25b3', + 'biguplus;': u'\u2a04', + 'bigvee;': u'\u22c1', + 'bigwedge;': u'\u22c0', + 'bkarow;': u'\u290d', + 'blacklozenge;': u'\u29eb', + 'blacksquare;': u'\u25aa', + 'blacktriangle;': u'\u25b4', + 'blacktriangledown;': u'\u25be', + 'blacktriangleleft;': u'\u25c2', + 'blacktriangleright;': u'\u25b8', + 'blank;': u'\u2423', + 'blk12;': u'\u2592', + 'blk14;': u'\u2591', + 'blk34;': u'\u2593', + 'block;': u'\u2588', + 'bne;': u'=\u20e5', + 'bnequiv;': u'\u2261\u20e5', + 'bNot;': u'\u2aed', + 'bnot;': u'\u2310', + 'Bopf;': u'\U0001d539', + 'bopf;': u'\U0001d553', + 'bot;': u'\u22a5', + 'bottom;': u'\u22a5', + 'bowtie;': u'\u22c8', + 'boxbox;': u'\u29c9', + 'boxDL;': u'\u2557', + 'boxDl;': u'\u2556', + 'boxdL;': u'\u2555', + 'boxdl;': u'\u2510', + 'boxDR;': u'\u2554', + 'boxDr;': u'\u2553', + 'boxdR;': u'\u2552', + 'boxdr;': u'\u250c', + 'boxH;': u'\u2550', + 'boxh;': u'\u2500', + 'boxHD;': u'\u2566', + 'boxHd;': u'\u2564', + 'boxhD;': u'\u2565', + 'boxhd;': u'\u252c', + 'boxHU;': u'\u2569', + 'boxHu;': u'\u2567', + 'boxhU;': u'\u2568', + 'boxhu;': u'\u2534', + 'boxminus;': u'\u229f', + 'boxplus;': u'\u229e', + 'boxtimes;': u'\u22a0', + 'boxUL;': u'\u255d', + 'boxUl;': u'\u255c', + 'boxuL;': u'\u255b', + 'boxul;': u'\u2518', + 'boxUR;': u'\u255a', + 'boxUr;': u'\u2559', + 'boxuR;': u'\u2558', + 'boxur;': u'\u2514', + 'boxV;': u'\u2551', + 'boxv;': u'\u2502', + 'boxVH;': u'\u256c', + 'boxVh;': u'\u256b', + 'boxvH;': u'\u256a', + 'boxvh;': u'\u253c', + 'boxVL;': u'\u2563', + 'boxVl;': u'\u2562', + 'boxvL;': u'\u2561', + 'boxvl;': u'\u2524', + 'boxVR;': u'\u2560', + 'boxVr;': u'\u255f', + 'boxvR;': u'\u255e', + 'boxvr;': u'\u251c', + 'bprime;': u'\u2035', + 'Breve;': u'\u02d8', + 'breve;': u'\u02d8', + 'brvbar': u'\xa6', + 'brvbar;': u'\xa6', + 'Bscr;': u'\u212c', + 'bscr;': u'\U0001d4b7', + 'bsemi;': u'\u204f', + 'bsim;': u'\u223d', + 'bsime;': u'\u22cd', + 'bsol;': u'\\', + 'bsolb;': u'\u29c5', + 'bsolhsub;': u'\u27c8', + 'bull;': u'\u2022', + 'bullet;': u'\u2022', + 'bump;': u'\u224e', + 'bumpE;': u'\u2aae', + 'bumpe;': u'\u224f', + 'Bumpeq;': u'\u224e', + 'bumpeq;': u'\u224f', + 'Cacute;': u'\u0106', + 'cacute;': u'\u0107', + 'Cap;': u'\u22d2', + 'cap;': u'\u2229', + 'capand;': u'\u2a44', + 'capbrcup;': u'\u2a49', + 'capcap;': u'\u2a4b', + 'capcup;': u'\u2a47', + 'capdot;': u'\u2a40', + 'CapitalDifferentialD;': u'\u2145', + 'caps;': u'\u2229\ufe00', + 'caret;': u'\u2041', + 'caron;': u'\u02c7', + 'Cayleys;': u'\u212d', + 'ccaps;': u'\u2a4d', + 'Ccaron;': u'\u010c', + 'ccaron;': u'\u010d', + 'Ccedil': u'\xc7', + 'ccedil': u'\xe7', + 'Ccedil;': u'\xc7', + 'ccedil;': u'\xe7', + 'Ccirc;': u'\u0108', + 'ccirc;': u'\u0109', + 'Cconint;': u'\u2230', + 'ccups;': u'\u2a4c', + 'ccupssm;': u'\u2a50', + 'Cdot;': u'\u010a', + 'cdot;': u'\u010b', + 'cedil': u'\xb8', + 'cedil;': u'\xb8', + 'Cedilla;': u'\xb8', + 'cemptyv;': u'\u29b2', + 'cent': u'\xa2', + 'cent;': u'\xa2', + 'CenterDot;': u'\xb7', + 'centerdot;': u'\xb7', + 'Cfr;': u'\u212d', + 'cfr;': u'\U0001d520', + 'CHcy;': u'\u0427', + 'chcy;': u'\u0447', + 'check;': u'\u2713', + 'checkmark;': u'\u2713', + 'Chi;': u'\u03a7', + 'chi;': u'\u03c7', + 'cir;': u'\u25cb', + 'circ;': u'\u02c6', + 'circeq;': u'\u2257', + 'circlearrowleft;': u'\u21ba', + 'circlearrowright;': u'\u21bb', + 'circledast;': u'\u229b', + 'circledcirc;': u'\u229a', + 'circleddash;': u'\u229d', + 'CircleDot;': u'\u2299', + 'circledR;': u'\xae', + 'circledS;': u'\u24c8', + 'CircleMinus;': u'\u2296', + 'CirclePlus;': u'\u2295', + 'CircleTimes;': u'\u2297', + 'cirE;': u'\u29c3', + 'cire;': u'\u2257', + 'cirfnint;': u'\u2a10', + 'cirmid;': u'\u2aef', + 'cirscir;': u'\u29c2', + 'ClockwiseContourIntegral;': u'\u2232', + 'CloseCurlyDoubleQuote;': u'\u201d', + 'CloseCurlyQuote;': u'\u2019', + 'clubs;': u'\u2663', + 'clubsuit;': u'\u2663', + 'Colon;': u'\u2237', + 'colon;': u':', + 'Colone;': u'\u2a74', + 'colone;': u'\u2254', + 'coloneq;': u'\u2254', + 'comma;': u',', + 'commat;': u'@', + 'comp;': u'\u2201', + 'compfn;': u'\u2218', + 'complement;': u'\u2201', + 'complexes;': u'\u2102', + 'cong;': u'\u2245', + 'congdot;': u'\u2a6d', + 'Congruent;': u'\u2261', + 'Conint;': u'\u222f', + 'conint;': u'\u222e', + 'ContourIntegral;': u'\u222e', + 'Copf;': u'\u2102', + 'copf;': u'\U0001d554', + 'coprod;': u'\u2210', + 'Coproduct;': u'\u2210', + 'COPY': u'\xa9', + 'copy': u'\xa9', + 'COPY;': u'\xa9', + 'copy;': u'\xa9', + 'copysr;': u'\u2117', + 'CounterClockwiseContourIntegral;': u'\u2233', + 'crarr;': u'\u21b5', + 'Cross;': u'\u2a2f', + 'cross;': u'\u2717', + 'Cscr;': u'\U0001d49e', + 'cscr;': u'\U0001d4b8', + 'csub;': u'\u2acf', + 'csube;': u'\u2ad1', + 'csup;': u'\u2ad0', + 'csupe;': u'\u2ad2', + 'ctdot;': u'\u22ef', + 'cudarrl;': u'\u2938', + 'cudarrr;': u'\u2935', + 'cuepr;': u'\u22de', + 'cuesc;': u'\u22df', + 'cularr;': u'\u21b6', + 'cularrp;': u'\u293d', + 'Cup;': u'\u22d3', + 'cup;': u'\u222a', + 'cupbrcap;': u'\u2a48', + 'CupCap;': u'\u224d', + 'cupcap;': u'\u2a46', + 'cupcup;': u'\u2a4a', + 'cupdot;': u'\u228d', + 'cupor;': u'\u2a45', + 'cups;': u'\u222a\ufe00', + 'curarr;': u'\u21b7', + 'curarrm;': u'\u293c', + 'curlyeqprec;': u'\u22de', + 'curlyeqsucc;': u'\u22df', + 'curlyvee;': u'\u22ce', + 'curlywedge;': u'\u22cf', + 'curren': u'\xa4', + 'curren;': u'\xa4', + 'curvearrowleft;': u'\u21b6', + 'curvearrowright;': u'\u21b7', + 'cuvee;': u'\u22ce', + 'cuwed;': u'\u22cf', + 'cwconint;': u'\u2232', + 'cwint;': u'\u2231', + 'cylcty;': u'\u232d', + 'Dagger;': u'\u2021', + 'dagger;': u'\u2020', + 'daleth;': u'\u2138', + 'Darr;': u'\u21a1', + 'dArr;': u'\u21d3', + 'darr;': u'\u2193', + 'dash;': u'\u2010', + 'Dashv;': u'\u2ae4', + 'dashv;': u'\u22a3', + 'dbkarow;': u'\u290f', + 'dblac;': u'\u02dd', + 'Dcaron;': u'\u010e', + 'dcaron;': u'\u010f', + 'Dcy;': u'\u0414', + 'dcy;': u'\u0434', + 'DD;': u'\u2145', + 'dd;': u'\u2146', + 'ddagger;': u'\u2021', + 'ddarr;': u'\u21ca', + 'DDotrahd;': u'\u2911', + 'ddotseq;': u'\u2a77', + 'deg': u'\xb0', + 'deg;': u'\xb0', + 'Del;': u'\u2207', + 'Delta;': u'\u0394', + 'delta;': u'\u03b4', + 'demptyv;': u'\u29b1', + 'dfisht;': u'\u297f', + 'Dfr;': u'\U0001d507', + 'dfr;': u'\U0001d521', + 'dHar;': u'\u2965', + 'dharl;': u'\u21c3', + 'dharr;': u'\u21c2', + 'DiacriticalAcute;': u'\xb4', + 'DiacriticalDot;': u'\u02d9', + 'DiacriticalDoubleAcute;': u'\u02dd', + 'DiacriticalGrave;': u'`', + 'DiacriticalTilde;': u'\u02dc', + 'diam;': u'\u22c4', + 'Diamond;': u'\u22c4', + 'diamond;': u'\u22c4', + 'diamondsuit;': u'\u2666', + 'diams;': u'\u2666', + 'die;': u'\xa8', + 'DifferentialD;': u'\u2146', + 'digamma;': u'\u03dd', + 'disin;': u'\u22f2', + 'div;': u'\xf7', + 'divide': u'\xf7', + 'divide;': u'\xf7', + 'divideontimes;': u'\u22c7', + 'divonx;': u'\u22c7', + 'DJcy;': u'\u0402', + 'djcy;': u'\u0452', + 'dlcorn;': u'\u231e', + 'dlcrop;': u'\u230d', + 'dollar;': u'$', + 'Dopf;': u'\U0001d53b', + 'dopf;': u'\U0001d555', + 'Dot;': u'\xa8', + 'dot;': u'\u02d9', + 'DotDot;': u'\u20dc', + 'doteq;': u'\u2250', + 'doteqdot;': u'\u2251', + 'DotEqual;': u'\u2250', + 'dotminus;': u'\u2238', + 'dotplus;': u'\u2214', + 'dotsquare;': u'\u22a1', + 'doublebarwedge;': u'\u2306', + 'DoubleContourIntegral;': u'\u222f', + 'DoubleDot;': u'\xa8', + 'DoubleDownArrow;': u'\u21d3', + 'DoubleLeftArrow;': u'\u21d0', + 'DoubleLeftRightArrow;': u'\u21d4', + 'DoubleLeftTee;': u'\u2ae4', + 'DoubleLongLeftArrow;': u'\u27f8', + 'DoubleLongLeftRightArrow;': u'\u27fa', + 'DoubleLongRightArrow;': u'\u27f9', + 'DoubleRightArrow;': u'\u21d2', + 'DoubleRightTee;': u'\u22a8', + 'DoubleUpArrow;': u'\u21d1', + 'DoubleUpDownArrow;': u'\u21d5', + 'DoubleVerticalBar;': u'\u2225', + 'DownArrow;': u'\u2193', + 'Downarrow;': u'\u21d3', + 'downarrow;': u'\u2193', + 'DownArrowBar;': u'\u2913', + 'DownArrowUpArrow;': u'\u21f5', + 'DownBreve;': u'\u0311', + 'downdownarrows;': u'\u21ca', + 'downharpoonleft;': u'\u21c3', + 'downharpoonright;': u'\u21c2', + 'DownLeftRightVector;': u'\u2950', + 'DownLeftTeeVector;': u'\u295e', + 'DownLeftVector;': u'\u21bd', + 'DownLeftVectorBar;': u'\u2956', + 'DownRightTeeVector;': u'\u295f', + 'DownRightVector;': u'\u21c1', + 'DownRightVectorBar;': u'\u2957', + 'DownTee;': u'\u22a4', + 'DownTeeArrow;': u'\u21a7', + 'drbkarow;': u'\u2910', + 'drcorn;': u'\u231f', + 'drcrop;': u'\u230c', + 'Dscr;': u'\U0001d49f', + 'dscr;': u'\U0001d4b9', + 'DScy;': u'\u0405', + 'dscy;': u'\u0455', + 'dsol;': u'\u29f6', + 'Dstrok;': u'\u0110', + 'dstrok;': u'\u0111', + 'dtdot;': u'\u22f1', + 'dtri;': u'\u25bf', + 'dtrif;': u'\u25be', + 'duarr;': u'\u21f5', + 'duhar;': u'\u296f', + 'dwangle;': u'\u29a6', + 'DZcy;': u'\u040f', + 'dzcy;': u'\u045f', + 'dzigrarr;': u'\u27ff', + 'Eacute': u'\xc9', + 'eacute': u'\xe9', + 'Eacute;': u'\xc9', + 'eacute;': u'\xe9', + 'easter;': u'\u2a6e', + 'Ecaron;': u'\u011a', + 'ecaron;': u'\u011b', + 'ecir;': u'\u2256', + 'Ecirc': u'\xca', + 'ecirc': u'\xea', + 'Ecirc;': u'\xca', + 'ecirc;': u'\xea', + 'ecolon;': u'\u2255', + 'Ecy;': u'\u042d', + 'ecy;': u'\u044d', + 'eDDot;': u'\u2a77', + 'Edot;': u'\u0116', + 'eDot;': u'\u2251', + 'edot;': u'\u0117', + 'ee;': u'\u2147', + 'efDot;': u'\u2252', + 'Efr;': u'\U0001d508', + 'efr;': u'\U0001d522', + 'eg;': u'\u2a9a', + 'Egrave': u'\xc8', + 'egrave': u'\xe8', + 'Egrave;': u'\xc8', + 'egrave;': u'\xe8', + 'egs;': u'\u2a96', + 'egsdot;': u'\u2a98', + 'el;': u'\u2a99', + 'Element;': u'\u2208', + 'elinters;': u'\u23e7', + 'ell;': u'\u2113', + 'els;': u'\u2a95', + 'elsdot;': u'\u2a97', + 'Emacr;': u'\u0112', + 'emacr;': u'\u0113', + 'empty;': u'\u2205', + 'emptyset;': u'\u2205', + 'EmptySmallSquare;': u'\u25fb', + 'emptyv;': u'\u2205', + 'EmptyVerySmallSquare;': u'\u25ab', + 'emsp13;': u'\u2004', + 'emsp14;': u'\u2005', + 'emsp;': u'\u2003', + 'ENG;': u'\u014a', + 'eng;': u'\u014b', + 'ensp;': u'\u2002', + 'Eogon;': u'\u0118', + 'eogon;': u'\u0119', + 'Eopf;': u'\U0001d53c', + 'eopf;': u'\U0001d556', + 'epar;': u'\u22d5', + 'eparsl;': u'\u29e3', + 'eplus;': u'\u2a71', + 'epsi;': u'\u03b5', + 'Epsilon;': u'\u0395', + 'epsilon;': u'\u03b5', + 'epsiv;': u'\u03f5', + 'eqcirc;': u'\u2256', + 'eqcolon;': u'\u2255', + 'eqsim;': u'\u2242', + 'eqslantgtr;': u'\u2a96', + 'eqslantless;': u'\u2a95', + 'Equal;': u'\u2a75', + 'equals;': u'=', + 'EqualTilde;': u'\u2242', + 'equest;': u'\u225f', + 'Equilibrium;': u'\u21cc', + 'equiv;': u'\u2261', + 'equivDD;': u'\u2a78', + 'eqvparsl;': u'\u29e5', + 'erarr;': u'\u2971', + 'erDot;': u'\u2253', + 'Escr;': u'\u2130', + 'escr;': u'\u212f', + 'esdot;': u'\u2250', + 'Esim;': u'\u2a73', + 'esim;': u'\u2242', + 'Eta;': u'\u0397', + 'eta;': u'\u03b7', + 'ETH': u'\xd0', + 'eth': u'\xf0', + 'ETH;': u'\xd0', + 'eth;': u'\xf0', + 'Euml': u'\xcb', + 'euml': u'\xeb', + 'Euml;': u'\xcb', + 'euml;': u'\xeb', + 'euro;': u'\u20ac', + 'excl;': u'!', + 'exist;': u'\u2203', + 'Exists;': u'\u2203', + 'expectation;': u'\u2130', + 'ExponentialE;': u'\u2147', + 'exponentiale;': u'\u2147', + 'fallingdotseq;': u'\u2252', + 'Fcy;': u'\u0424', + 'fcy;': u'\u0444', + 'female;': u'\u2640', + 'ffilig;': u'\ufb03', + 'fflig;': u'\ufb00', + 'ffllig;': u'\ufb04', + 'Ffr;': u'\U0001d509', + 'ffr;': u'\U0001d523', + 'filig;': u'\ufb01', + 'FilledSmallSquare;': u'\u25fc', + 'FilledVerySmallSquare;': u'\u25aa', + 'fjlig;': u'fj', + 'flat;': u'\u266d', + 'fllig;': u'\ufb02', + 'fltns;': u'\u25b1', + 'fnof;': u'\u0192', + 'Fopf;': u'\U0001d53d', + 'fopf;': u'\U0001d557', + 'ForAll;': u'\u2200', + 'forall;': u'\u2200', + 'fork;': u'\u22d4', + 'forkv;': u'\u2ad9', + 'Fouriertrf;': u'\u2131', + 'fpartint;': u'\u2a0d', + 'frac12': u'\xbd', + 'frac12;': u'\xbd', + 'frac13;': u'\u2153', + 'frac14': u'\xbc', + 'frac14;': u'\xbc', + 'frac15;': u'\u2155', + 'frac16;': u'\u2159', + 'frac18;': u'\u215b', + 'frac23;': u'\u2154', + 'frac25;': u'\u2156', + 'frac34': u'\xbe', + 'frac34;': u'\xbe', + 'frac35;': u'\u2157', + 'frac38;': u'\u215c', + 'frac45;': u'\u2158', + 'frac56;': u'\u215a', + 'frac58;': u'\u215d', + 'frac78;': u'\u215e', + 'frasl;': u'\u2044', + 'frown;': u'\u2322', + 'Fscr;': u'\u2131', + 'fscr;': u'\U0001d4bb', + 'gacute;': u'\u01f5', + 'Gamma;': u'\u0393', + 'gamma;': u'\u03b3', + 'Gammad;': u'\u03dc', + 'gammad;': u'\u03dd', + 'gap;': u'\u2a86', + 'Gbreve;': u'\u011e', + 'gbreve;': u'\u011f', + 'Gcedil;': u'\u0122', + 'Gcirc;': u'\u011c', + 'gcirc;': u'\u011d', + 'Gcy;': u'\u0413', + 'gcy;': u'\u0433', + 'Gdot;': u'\u0120', + 'gdot;': u'\u0121', + 'gE;': u'\u2267', + 'ge;': u'\u2265', + 'gEl;': u'\u2a8c', + 'gel;': u'\u22db', + 'geq;': u'\u2265', + 'geqq;': u'\u2267', + 'geqslant;': u'\u2a7e', + 'ges;': u'\u2a7e', + 'gescc;': u'\u2aa9', + 'gesdot;': u'\u2a80', + 'gesdoto;': u'\u2a82', + 'gesdotol;': u'\u2a84', + 'gesl;': u'\u22db\ufe00', + 'gesles;': u'\u2a94', + 'Gfr;': u'\U0001d50a', + 'gfr;': u'\U0001d524', + 'Gg;': u'\u22d9', + 'gg;': u'\u226b', + 'ggg;': u'\u22d9', + 'gimel;': u'\u2137', + 'GJcy;': u'\u0403', + 'gjcy;': u'\u0453', + 'gl;': u'\u2277', + 'gla;': u'\u2aa5', + 'glE;': u'\u2a92', + 'glj;': u'\u2aa4', + 'gnap;': u'\u2a8a', + 'gnapprox;': u'\u2a8a', + 'gnE;': u'\u2269', + 'gne;': u'\u2a88', + 'gneq;': u'\u2a88', + 'gneqq;': u'\u2269', + 'gnsim;': u'\u22e7', + 'Gopf;': u'\U0001d53e', + 'gopf;': u'\U0001d558', + 'grave;': u'`', + 'GreaterEqual;': u'\u2265', + 'GreaterEqualLess;': u'\u22db', + 'GreaterFullEqual;': u'\u2267', + 'GreaterGreater;': u'\u2aa2', + 'GreaterLess;': u'\u2277', + 'GreaterSlantEqual;': u'\u2a7e', + 'GreaterTilde;': u'\u2273', + 'Gscr;': u'\U0001d4a2', + 'gscr;': u'\u210a', + 'gsim;': u'\u2273', + 'gsime;': u'\u2a8e', + 'gsiml;': u'\u2a90', + 'GT': u'>', + 'gt': u'>', + 'GT;': u'>', + 'Gt;': u'\u226b', + 'gt;': u'>', + 'gtcc;': u'\u2aa7', + 'gtcir;': u'\u2a7a', + 'gtdot;': u'\u22d7', + 'gtlPar;': u'\u2995', + 'gtquest;': u'\u2a7c', + 'gtrapprox;': u'\u2a86', + 'gtrarr;': u'\u2978', + 'gtrdot;': u'\u22d7', + 'gtreqless;': u'\u22db', + 'gtreqqless;': u'\u2a8c', + 'gtrless;': u'\u2277', + 'gtrsim;': u'\u2273', + 'gvertneqq;': u'\u2269\ufe00', + 'gvnE;': u'\u2269\ufe00', + 'Hacek;': u'\u02c7', + 'hairsp;': u'\u200a', + 'half;': u'\xbd', + 'hamilt;': u'\u210b', + 'HARDcy;': u'\u042a', + 'hardcy;': u'\u044a', + 'hArr;': u'\u21d4', + 'harr;': u'\u2194', + 'harrcir;': u'\u2948', + 'harrw;': u'\u21ad', + 'Hat;': u'^', + 'hbar;': u'\u210f', + 'Hcirc;': u'\u0124', + 'hcirc;': u'\u0125', + 'hearts;': u'\u2665', + 'heartsuit;': u'\u2665', + 'hellip;': u'\u2026', + 'hercon;': u'\u22b9', + 'Hfr;': u'\u210c', + 'hfr;': u'\U0001d525', + 'HilbertSpace;': u'\u210b', + 'hksearow;': u'\u2925', + 'hkswarow;': u'\u2926', + 'hoarr;': u'\u21ff', + 'homtht;': u'\u223b', + 'hookleftarrow;': u'\u21a9', + 'hookrightarrow;': u'\u21aa', + 'Hopf;': u'\u210d', + 'hopf;': u'\U0001d559', + 'horbar;': u'\u2015', + 'HorizontalLine;': u'\u2500', + 'Hscr;': u'\u210b', + 'hscr;': u'\U0001d4bd', + 'hslash;': u'\u210f', + 'Hstrok;': u'\u0126', + 'hstrok;': u'\u0127', + 'HumpDownHump;': u'\u224e', + 'HumpEqual;': u'\u224f', + 'hybull;': u'\u2043', + 'hyphen;': u'\u2010', + 'Iacute': u'\xcd', + 'iacute': u'\xed', + 'Iacute;': u'\xcd', + 'iacute;': u'\xed', + 'ic;': u'\u2063', + 'Icirc': u'\xce', + 'icirc': u'\xee', + 'Icirc;': u'\xce', + 'icirc;': u'\xee', + 'Icy;': u'\u0418', + 'icy;': u'\u0438', + 'Idot;': u'\u0130', + 'IEcy;': u'\u0415', + 'iecy;': u'\u0435', + 'iexcl': u'\xa1', + 'iexcl;': u'\xa1', + 'iff;': u'\u21d4', + 'Ifr;': u'\u2111', + 'ifr;': u'\U0001d526', + 'Igrave': u'\xcc', + 'igrave': u'\xec', + 'Igrave;': u'\xcc', + 'igrave;': u'\xec', + 'ii;': u'\u2148', + 'iiiint;': u'\u2a0c', + 'iiint;': u'\u222d', + 'iinfin;': u'\u29dc', + 'iiota;': u'\u2129', + 'IJlig;': u'\u0132', + 'ijlig;': u'\u0133', + 'Im;': u'\u2111', + 'Imacr;': u'\u012a', + 'imacr;': u'\u012b', + 'image;': u'\u2111', + 'ImaginaryI;': u'\u2148', + 'imagline;': u'\u2110', + 'imagpart;': u'\u2111', + 'imath;': u'\u0131', + 'imof;': u'\u22b7', + 'imped;': u'\u01b5', + 'Implies;': u'\u21d2', + 'in;': u'\u2208', + 'incare;': u'\u2105', + 'infin;': u'\u221e', + 'infintie;': u'\u29dd', + 'inodot;': u'\u0131', + 'Int;': u'\u222c', + 'int;': u'\u222b', + 'intcal;': u'\u22ba', + 'integers;': u'\u2124', + 'Integral;': u'\u222b', + 'intercal;': u'\u22ba', + 'Intersection;': u'\u22c2', + 'intlarhk;': u'\u2a17', + 'intprod;': u'\u2a3c', + 'InvisibleComma;': u'\u2063', + 'InvisibleTimes;': u'\u2062', + 'IOcy;': u'\u0401', + 'iocy;': u'\u0451', + 'Iogon;': u'\u012e', + 'iogon;': u'\u012f', + 'Iopf;': u'\U0001d540', + 'iopf;': u'\U0001d55a', + 'Iota;': u'\u0399', + 'iota;': u'\u03b9', + 'iprod;': u'\u2a3c', + 'iquest': u'\xbf', + 'iquest;': u'\xbf', + 'Iscr;': u'\u2110', + 'iscr;': u'\U0001d4be', + 'isin;': u'\u2208', + 'isindot;': u'\u22f5', + 'isinE;': u'\u22f9', + 'isins;': u'\u22f4', + 'isinsv;': u'\u22f3', + 'isinv;': u'\u2208', + 'it;': u'\u2062', + 'Itilde;': u'\u0128', + 'itilde;': u'\u0129', + 'Iukcy;': u'\u0406', + 'iukcy;': u'\u0456', + 'Iuml': u'\xcf', + 'iuml': u'\xef', + 'Iuml;': u'\xcf', + 'iuml;': u'\xef', + 'Jcirc;': u'\u0134', + 'jcirc;': u'\u0135', + 'Jcy;': u'\u0419', + 'jcy;': u'\u0439', + 'Jfr;': u'\U0001d50d', + 'jfr;': u'\U0001d527', + 'jmath;': u'\u0237', + 'Jopf;': u'\U0001d541', + 'jopf;': u'\U0001d55b', + 'Jscr;': u'\U0001d4a5', + 'jscr;': u'\U0001d4bf', + 'Jsercy;': u'\u0408', + 'jsercy;': u'\u0458', + 'Jukcy;': u'\u0404', + 'jukcy;': u'\u0454', + 'Kappa;': u'\u039a', + 'kappa;': u'\u03ba', + 'kappav;': u'\u03f0', + 'Kcedil;': u'\u0136', + 'kcedil;': u'\u0137', + 'Kcy;': u'\u041a', + 'kcy;': u'\u043a', + 'Kfr;': u'\U0001d50e', + 'kfr;': u'\U0001d528', + 'kgreen;': u'\u0138', + 'KHcy;': u'\u0425', + 'khcy;': u'\u0445', + 'KJcy;': u'\u040c', + 'kjcy;': u'\u045c', + 'Kopf;': u'\U0001d542', + 'kopf;': u'\U0001d55c', + 'Kscr;': u'\U0001d4a6', + 'kscr;': u'\U0001d4c0', + 'lAarr;': u'\u21da', + 'Lacute;': u'\u0139', + 'lacute;': u'\u013a', + 'laemptyv;': u'\u29b4', + 'lagran;': u'\u2112', + 'Lambda;': u'\u039b', + 'lambda;': u'\u03bb', + 'Lang;': u'\u27ea', + 'lang;': u'\u27e8', + 'langd;': u'\u2991', + 'langle;': u'\u27e8', + 'lap;': u'\u2a85', + 'Laplacetrf;': u'\u2112', + 'laquo': u'\xab', + 'laquo;': u'\xab', + 'Larr;': u'\u219e', + 'lArr;': u'\u21d0', + 'larr;': u'\u2190', + 'larrb;': u'\u21e4', + 'larrbfs;': u'\u291f', + 'larrfs;': u'\u291d', + 'larrhk;': u'\u21a9', + 'larrlp;': u'\u21ab', + 'larrpl;': u'\u2939', + 'larrsim;': u'\u2973', + 'larrtl;': u'\u21a2', + 'lat;': u'\u2aab', + 'lAtail;': u'\u291b', + 'latail;': u'\u2919', + 'late;': u'\u2aad', + 'lates;': u'\u2aad\ufe00', + 'lBarr;': u'\u290e', + 'lbarr;': u'\u290c', + 'lbbrk;': u'\u2772', + 'lbrace;': u'{', + 'lbrack;': u'[', + 'lbrke;': u'\u298b', + 'lbrksld;': u'\u298f', + 'lbrkslu;': u'\u298d', + 'Lcaron;': u'\u013d', + 'lcaron;': u'\u013e', + 'Lcedil;': u'\u013b', + 'lcedil;': u'\u013c', + 'lceil;': u'\u2308', + 'lcub;': u'{', + 'Lcy;': u'\u041b', + 'lcy;': u'\u043b', + 'ldca;': u'\u2936', + 'ldquo;': u'\u201c', + 'ldquor;': u'\u201e', + 'ldrdhar;': u'\u2967', + 'ldrushar;': u'\u294b', + 'ldsh;': u'\u21b2', + 'lE;': u'\u2266', + 'le;': u'\u2264', + 'LeftAngleBracket;': u'\u27e8', + 'LeftArrow;': u'\u2190', + 'Leftarrow;': u'\u21d0', + 'leftarrow;': u'\u2190', + 'LeftArrowBar;': u'\u21e4', + 'LeftArrowRightArrow;': u'\u21c6', + 'leftarrowtail;': u'\u21a2', + 'LeftCeiling;': u'\u2308', + 'LeftDoubleBracket;': u'\u27e6', + 'LeftDownTeeVector;': u'\u2961', + 'LeftDownVector;': u'\u21c3', + 'LeftDownVectorBar;': u'\u2959', + 'LeftFloor;': u'\u230a', + 'leftharpoondown;': u'\u21bd', + 'leftharpoonup;': u'\u21bc', + 'leftleftarrows;': u'\u21c7', + 'LeftRightArrow;': u'\u2194', + 'Leftrightarrow;': u'\u21d4', + 'leftrightarrow;': u'\u2194', + 'leftrightarrows;': u'\u21c6', + 'leftrightharpoons;': u'\u21cb', + 'leftrightsquigarrow;': u'\u21ad', + 'LeftRightVector;': u'\u294e', + 'LeftTee;': u'\u22a3', + 'LeftTeeArrow;': u'\u21a4', + 'LeftTeeVector;': u'\u295a', + 'leftthreetimes;': u'\u22cb', + 'LeftTriangle;': u'\u22b2', + 'LeftTriangleBar;': u'\u29cf', + 'LeftTriangleEqual;': u'\u22b4', + 'LeftUpDownVector;': u'\u2951', + 'LeftUpTeeVector;': u'\u2960', + 'LeftUpVector;': u'\u21bf', + 'LeftUpVectorBar;': u'\u2958', + 'LeftVector;': u'\u21bc', + 'LeftVectorBar;': u'\u2952', + 'lEg;': u'\u2a8b', + 'leg;': u'\u22da', + 'leq;': u'\u2264', + 'leqq;': u'\u2266', + 'leqslant;': u'\u2a7d', + 'les;': u'\u2a7d', + 'lescc;': u'\u2aa8', + 'lesdot;': u'\u2a7f', + 'lesdoto;': u'\u2a81', + 'lesdotor;': u'\u2a83', + 'lesg;': u'\u22da\ufe00', + 'lesges;': u'\u2a93', + 'lessapprox;': u'\u2a85', + 'lessdot;': u'\u22d6', + 'lesseqgtr;': u'\u22da', + 'lesseqqgtr;': u'\u2a8b', + 'LessEqualGreater;': u'\u22da', + 'LessFullEqual;': u'\u2266', + 'LessGreater;': u'\u2276', + 'lessgtr;': u'\u2276', + 'LessLess;': u'\u2aa1', + 'lesssim;': u'\u2272', + 'LessSlantEqual;': u'\u2a7d', + 'LessTilde;': u'\u2272', + 'lfisht;': u'\u297c', + 'lfloor;': u'\u230a', + 'Lfr;': u'\U0001d50f', + 'lfr;': u'\U0001d529', + 'lg;': u'\u2276', + 'lgE;': u'\u2a91', + 'lHar;': u'\u2962', + 'lhard;': u'\u21bd', + 'lharu;': u'\u21bc', + 'lharul;': u'\u296a', + 'lhblk;': u'\u2584', + 'LJcy;': u'\u0409', + 'ljcy;': u'\u0459', + 'Ll;': u'\u22d8', + 'll;': u'\u226a', + 'llarr;': u'\u21c7', + 'llcorner;': u'\u231e', + 'Lleftarrow;': u'\u21da', + 'llhard;': u'\u296b', + 'lltri;': u'\u25fa', + 'Lmidot;': u'\u013f', + 'lmidot;': u'\u0140', + 'lmoust;': u'\u23b0', + 'lmoustache;': u'\u23b0', + 'lnap;': u'\u2a89', + 'lnapprox;': u'\u2a89', + 'lnE;': u'\u2268', + 'lne;': u'\u2a87', + 'lneq;': u'\u2a87', + 'lneqq;': u'\u2268', + 'lnsim;': u'\u22e6', + 'loang;': u'\u27ec', + 'loarr;': u'\u21fd', + 'lobrk;': u'\u27e6', + 'LongLeftArrow;': u'\u27f5', + 'Longleftarrow;': u'\u27f8', + 'longleftarrow;': u'\u27f5', + 'LongLeftRightArrow;': u'\u27f7', + 'Longleftrightarrow;': u'\u27fa', + 'longleftrightarrow;': u'\u27f7', + 'longmapsto;': u'\u27fc', + 'LongRightArrow;': u'\u27f6', + 'Longrightarrow;': u'\u27f9', + 'longrightarrow;': u'\u27f6', + 'looparrowleft;': u'\u21ab', + 'looparrowright;': u'\u21ac', + 'lopar;': u'\u2985', + 'Lopf;': u'\U0001d543', + 'lopf;': u'\U0001d55d', + 'loplus;': u'\u2a2d', + 'lotimes;': u'\u2a34', + 'lowast;': u'\u2217', + 'lowbar;': u'_', + 'LowerLeftArrow;': u'\u2199', + 'LowerRightArrow;': u'\u2198', + 'loz;': u'\u25ca', + 'lozenge;': u'\u25ca', + 'lozf;': u'\u29eb', + 'lpar;': u'(', + 'lparlt;': u'\u2993', + 'lrarr;': u'\u21c6', + 'lrcorner;': u'\u231f', + 'lrhar;': u'\u21cb', + 'lrhard;': u'\u296d', + 'lrm;': u'\u200e', + 'lrtri;': u'\u22bf', + 'lsaquo;': u'\u2039', + 'Lscr;': u'\u2112', + 'lscr;': u'\U0001d4c1', + 'Lsh;': u'\u21b0', + 'lsh;': u'\u21b0', + 'lsim;': u'\u2272', + 'lsime;': u'\u2a8d', + 'lsimg;': u'\u2a8f', + 'lsqb;': u'[', + 'lsquo;': u'\u2018', + 'lsquor;': u'\u201a', + 'Lstrok;': u'\u0141', + 'lstrok;': u'\u0142', + 'LT': u'<', + 'lt': u'<', + 'LT;': u'<', + 'Lt;': u'\u226a', + 'lt;': u'<', + 'ltcc;': u'\u2aa6', + 'ltcir;': u'\u2a79', + 'ltdot;': u'\u22d6', + 'lthree;': u'\u22cb', + 'ltimes;': u'\u22c9', + 'ltlarr;': u'\u2976', + 'ltquest;': u'\u2a7b', + 'ltri;': u'\u25c3', + 'ltrie;': u'\u22b4', + 'ltrif;': u'\u25c2', + 'ltrPar;': u'\u2996', + 'lurdshar;': u'\u294a', + 'luruhar;': u'\u2966', + 'lvertneqq;': u'\u2268\ufe00', + 'lvnE;': u'\u2268\ufe00', + 'macr': u'\xaf', + 'macr;': u'\xaf', + 'male;': u'\u2642', + 'malt;': u'\u2720', + 'maltese;': u'\u2720', + 'Map;': u'\u2905', + 'map;': u'\u21a6', + 'mapsto;': u'\u21a6', + 'mapstodown;': u'\u21a7', + 'mapstoleft;': u'\u21a4', + 'mapstoup;': u'\u21a5', + 'marker;': u'\u25ae', + 'mcomma;': u'\u2a29', + 'Mcy;': u'\u041c', + 'mcy;': u'\u043c', + 'mdash;': u'\u2014', + 'mDDot;': u'\u223a', + 'measuredangle;': u'\u2221', + 'MediumSpace;': u'\u205f', + 'Mellintrf;': u'\u2133', + 'Mfr;': u'\U0001d510', + 'mfr;': u'\U0001d52a', + 'mho;': u'\u2127', + 'micro': u'\xb5', + 'micro;': u'\xb5', + 'mid;': u'\u2223', + 'midast;': u'*', + 'midcir;': u'\u2af0', + 'middot': u'\xb7', + 'middot;': u'\xb7', + 'minus;': u'\u2212', + 'minusb;': u'\u229f', + 'minusd;': u'\u2238', + 'minusdu;': u'\u2a2a', + 'MinusPlus;': u'\u2213', + 'mlcp;': u'\u2adb', + 'mldr;': u'\u2026', + 'mnplus;': u'\u2213', + 'models;': u'\u22a7', + 'Mopf;': u'\U0001d544', + 'mopf;': u'\U0001d55e', + 'mp;': u'\u2213', + 'Mscr;': u'\u2133', + 'mscr;': u'\U0001d4c2', + 'mstpos;': u'\u223e', + 'Mu;': u'\u039c', + 'mu;': u'\u03bc', + 'multimap;': u'\u22b8', + 'mumap;': u'\u22b8', + 'nabla;': u'\u2207', + 'Nacute;': u'\u0143', + 'nacute;': u'\u0144', + 'nang;': u'\u2220\u20d2', + 'nap;': u'\u2249', + 'napE;': u'\u2a70\u0338', + 'napid;': u'\u224b\u0338', + 'napos;': u'\u0149', + 'napprox;': u'\u2249', + 'natur;': u'\u266e', + 'natural;': u'\u266e', + 'naturals;': u'\u2115', + 'nbsp': u'\xa0', + 'nbsp;': u'\xa0', + 'nbump;': u'\u224e\u0338', + 'nbumpe;': u'\u224f\u0338', + 'ncap;': u'\u2a43', + 'Ncaron;': u'\u0147', + 'ncaron;': u'\u0148', + 'Ncedil;': u'\u0145', + 'ncedil;': u'\u0146', + 'ncong;': u'\u2247', + 'ncongdot;': u'\u2a6d\u0338', + 'ncup;': u'\u2a42', + 'Ncy;': u'\u041d', + 'ncy;': u'\u043d', + 'ndash;': u'\u2013', + 'ne;': u'\u2260', + 'nearhk;': u'\u2924', + 'neArr;': u'\u21d7', + 'nearr;': u'\u2197', + 'nearrow;': u'\u2197', + 'nedot;': u'\u2250\u0338', + 'NegativeMediumSpace;': u'\u200b', + 'NegativeThickSpace;': u'\u200b', + 'NegativeThinSpace;': u'\u200b', + 'NegativeVeryThinSpace;': u'\u200b', + 'nequiv;': u'\u2262', + 'nesear;': u'\u2928', + 'nesim;': u'\u2242\u0338', + 'NestedGreaterGreater;': u'\u226b', + 'NestedLessLess;': u'\u226a', + 'NewLine;': u'\n', + 'nexist;': u'\u2204', + 'nexists;': u'\u2204', + 'Nfr;': u'\U0001d511', + 'nfr;': u'\U0001d52b', + 'ngE;': u'\u2267\u0338', + 'nge;': u'\u2271', + 'ngeq;': u'\u2271', + 'ngeqq;': u'\u2267\u0338', + 'ngeqslant;': u'\u2a7e\u0338', + 'nges;': u'\u2a7e\u0338', + 'nGg;': u'\u22d9\u0338', + 'ngsim;': u'\u2275', + 'nGt;': u'\u226b\u20d2', + 'ngt;': u'\u226f', + 'ngtr;': u'\u226f', + 'nGtv;': u'\u226b\u0338', + 'nhArr;': u'\u21ce', + 'nharr;': u'\u21ae', + 'nhpar;': u'\u2af2', + 'ni;': u'\u220b', + 'nis;': u'\u22fc', + 'nisd;': u'\u22fa', + 'niv;': u'\u220b', + 'NJcy;': u'\u040a', + 'njcy;': u'\u045a', + 'nlArr;': u'\u21cd', + 'nlarr;': u'\u219a', + 'nldr;': u'\u2025', + 'nlE;': u'\u2266\u0338', + 'nle;': u'\u2270', + 'nLeftarrow;': u'\u21cd', + 'nleftarrow;': u'\u219a', + 'nLeftrightarrow;': u'\u21ce', + 'nleftrightarrow;': u'\u21ae', + 'nleq;': u'\u2270', + 'nleqq;': u'\u2266\u0338', + 'nleqslant;': u'\u2a7d\u0338', + 'nles;': u'\u2a7d\u0338', + 'nless;': u'\u226e', + 'nLl;': u'\u22d8\u0338', + 'nlsim;': u'\u2274', + 'nLt;': u'\u226a\u20d2', + 'nlt;': u'\u226e', + 'nltri;': u'\u22ea', + 'nltrie;': u'\u22ec', + 'nLtv;': u'\u226a\u0338', + 'nmid;': u'\u2224', + 'NoBreak;': u'\u2060', + 'NonBreakingSpace;': u'\xa0', + 'Nopf;': u'\u2115', + 'nopf;': u'\U0001d55f', + 'not': u'\xac', + 'Not;': u'\u2aec', + 'not;': u'\xac', + 'NotCongruent;': u'\u2262', + 'NotCupCap;': u'\u226d', + 'NotDoubleVerticalBar;': u'\u2226', + 'NotElement;': u'\u2209', + 'NotEqual;': u'\u2260', + 'NotEqualTilde;': u'\u2242\u0338', + 'NotExists;': u'\u2204', + 'NotGreater;': u'\u226f', + 'NotGreaterEqual;': u'\u2271', + 'NotGreaterFullEqual;': u'\u2267\u0338', + 'NotGreaterGreater;': u'\u226b\u0338', + 'NotGreaterLess;': u'\u2279', + 'NotGreaterSlantEqual;': u'\u2a7e\u0338', + 'NotGreaterTilde;': u'\u2275', + 'NotHumpDownHump;': u'\u224e\u0338', + 'NotHumpEqual;': u'\u224f\u0338', + 'notin;': u'\u2209', + 'notindot;': u'\u22f5\u0338', + 'notinE;': u'\u22f9\u0338', + 'notinva;': u'\u2209', + 'notinvb;': u'\u22f7', + 'notinvc;': u'\u22f6', + 'NotLeftTriangle;': u'\u22ea', + 'NotLeftTriangleBar;': u'\u29cf\u0338', + 'NotLeftTriangleEqual;': u'\u22ec', + 'NotLess;': u'\u226e', + 'NotLessEqual;': u'\u2270', + 'NotLessGreater;': u'\u2278', + 'NotLessLess;': u'\u226a\u0338', + 'NotLessSlantEqual;': u'\u2a7d\u0338', + 'NotLessTilde;': u'\u2274', + 'NotNestedGreaterGreater;': u'\u2aa2\u0338', + 'NotNestedLessLess;': u'\u2aa1\u0338', + 'notni;': u'\u220c', + 'notniva;': u'\u220c', + 'notnivb;': u'\u22fe', + 'notnivc;': u'\u22fd', + 'NotPrecedes;': u'\u2280', + 'NotPrecedesEqual;': u'\u2aaf\u0338', + 'NotPrecedesSlantEqual;': u'\u22e0', + 'NotReverseElement;': u'\u220c', + 'NotRightTriangle;': u'\u22eb', + 'NotRightTriangleBar;': u'\u29d0\u0338', + 'NotRightTriangleEqual;': u'\u22ed', + 'NotSquareSubset;': u'\u228f\u0338', + 'NotSquareSubsetEqual;': u'\u22e2', + 'NotSquareSuperset;': u'\u2290\u0338', + 'NotSquareSupersetEqual;': u'\u22e3', + 'NotSubset;': u'\u2282\u20d2', + 'NotSubsetEqual;': u'\u2288', + 'NotSucceeds;': u'\u2281', + 'NotSucceedsEqual;': u'\u2ab0\u0338', + 'NotSucceedsSlantEqual;': u'\u22e1', + 'NotSucceedsTilde;': u'\u227f\u0338', + 'NotSuperset;': u'\u2283\u20d2', + 'NotSupersetEqual;': u'\u2289', + 'NotTilde;': u'\u2241', + 'NotTildeEqual;': u'\u2244', + 'NotTildeFullEqual;': u'\u2247', + 'NotTildeTilde;': u'\u2249', + 'NotVerticalBar;': u'\u2224', + 'npar;': u'\u2226', + 'nparallel;': u'\u2226', + 'nparsl;': u'\u2afd\u20e5', + 'npart;': u'\u2202\u0338', + 'npolint;': u'\u2a14', + 'npr;': u'\u2280', + 'nprcue;': u'\u22e0', + 'npre;': u'\u2aaf\u0338', + 'nprec;': u'\u2280', + 'npreceq;': u'\u2aaf\u0338', + 'nrArr;': u'\u21cf', + 'nrarr;': u'\u219b', + 'nrarrc;': u'\u2933\u0338', + 'nrarrw;': u'\u219d\u0338', + 'nRightarrow;': u'\u21cf', + 'nrightarrow;': u'\u219b', + 'nrtri;': u'\u22eb', + 'nrtrie;': u'\u22ed', + 'nsc;': u'\u2281', + 'nsccue;': u'\u22e1', + 'nsce;': u'\u2ab0\u0338', + 'Nscr;': u'\U0001d4a9', + 'nscr;': u'\U0001d4c3', + 'nshortmid;': u'\u2224', + 'nshortparallel;': u'\u2226', + 'nsim;': u'\u2241', + 'nsime;': u'\u2244', + 'nsimeq;': u'\u2244', + 'nsmid;': u'\u2224', + 'nspar;': u'\u2226', + 'nsqsube;': u'\u22e2', + 'nsqsupe;': u'\u22e3', + 'nsub;': u'\u2284', + 'nsubE;': u'\u2ac5\u0338', + 'nsube;': u'\u2288', + 'nsubset;': u'\u2282\u20d2', + 'nsubseteq;': u'\u2288', + 'nsubseteqq;': u'\u2ac5\u0338', + 'nsucc;': u'\u2281', + 'nsucceq;': u'\u2ab0\u0338', + 'nsup;': u'\u2285', + 'nsupE;': u'\u2ac6\u0338', + 'nsupe;': u'\u2289', + 'nsupset;': u'\u2283\u20d2', + 'nsupseteq;': u'\u2289', + 'nsupseteqq;': u'\u2ac6\u0338', + 'ntgl;': u'\u2279', + 'Ntilde': u'\xd1', + 'ntilde': u'\xf1', + 'Ntilde;': u'\xd1', + 'ntilde;': u'\xf1', + 'ntlg;': u'\u2278', + 'ntriangleleft;': u'\u22ea', + 'ntrianglelefteq;': u'\u22ec', + 'ntriangleright;': u'\u22eb', + 'ntrianglerighteq;': u'\u22ed', + 'Nu;': u'\u039d', + 'nu;': u'\u03bd', + 'num;': u'#', + 'numero;': u'\u2116', + 'numsp;': u'\u2007', + 'nvap;': u'\u224d\u20d2', + 'nVDash;': u'\u22af', + 'nVdash;': u'\u22ae', + 'nvDash;': u'\u22ad', + 'nvdash;': u'\u22ac', + 'nvge;': u'\u2265\u20d2', + 'nvgt;': u'>\u20d2', + 'nvHarr;': u'\u2904', + 'nvinfin;': u'\u29de', + 'nvlArr;': u'\u2902', + 'nvle;': u'\u2264\u20d2', + 'nvlt;': u'<\u20d2', + 'nvltrie;': u'\u22b4\u20d2', + 'nvrArr;': u'\u2903', + 'nvrtrie;': u'\u22b5\u20d2', + 'nvsim;': u'\u223c\u20d2', + 'nwarhk;': u'\u2923', + 'nwArr;': u'\u21d6', + 'nwarr;': u'\u2196', + 'nwarrow;': u'\u2196', + 'nwnear;': u'\u2927', + 'Oacute': u'\xd3', + 'oacute': u'\xf3', + 'Oacute;': u'\xd3', + 'oacute;': u'\xf3', + 'oast;': u'\u229b', + 'ocir;': u'\u229a', + 'Ocirc': u'\xd4', + 'ocirc': u'\xf4', + 'Ocirc;': u'\xd4', + 'ocirc;': u'\xf4', + 'Ocy;': u'\u041e', + 'ocy;': u'\u043e', + 'odash;': u'\u229d', + 'Odblac;': u'\u0150', + 'odblac;': u'\u0151', + 'odiv;': u'\u2a38', + 'odot;': u'\u2299', + 'odsold;': u'\u29bc', + 'OElig;': u'\u0152', + 'oelig;': u'\u0153', + 'ofcir;': u'\u29bf', + 'Ofr;': u'\U0001d512', + 'ofr;': u'\U0001d52c', + 'ogon;': u'\u02db', + 'Ograve': u'\xd2', + 'ograve': u'\xf2', + 'Ograve;': u'\xd2', + 'ograve;': u'\xf2', + 'ogt;': u'\u29c1', + 'ohbar;': u'\u29b5', + 'ohm;': u'\u03a9', + 'oint;': u'\u222e', + 'olarr;': u'\u21ba', + 'olcir;': u'\u29be', + 'olcross;': u'\u29bb', + 'oline;': u'\u203e', + 'olt;': u'\u29c0', + 'Omacr;': u'\u014c', + 'omacr;': u'\u014d', + 'Omega;': u'\u03a9', + 'omega;': u'\u03c9', + 'Omicron;': u'\u039f', + 'omicron;': u'\u03bf', + 'omid;': u'\u29b6', + 'ominus;': u'\u2296', + 'Oopf;': u'\U0001d546', + 'oopf;': u'\U0001d560', + 'opar;': u'\u29b7', + 'OpenCurlyDoubleQuote;': u'\u201c', + 'OpenCurlyQuote;': u'\u2018', + 'operp;': u'\u29b9', + 'oplus;': u'\u2295', + 'Or;': u'\u2a54', + 'or;': u'\u2228', + 'orarr;': u'\u21bb', + 'ord;': u'\u2a5d', + 'order;': u'\u2134', + 'orderof;': u'\u2134', + 'ordf': u'\xaa', + 'ordf;': u'\xaa', + 'ordm': u'\xba', + 'ordm;': u'\xba', + 'origof;': u'\u22b6', + 'oror;': u'\u2a56', + 'orslope;': u'\u2a57', + 'orv;': u'\u2a5b', + 'oS;': u'\u24c8', + 'Oscr;': u'\U0001d4aa', + 'oscr;': u'\u2134', + 'Oslash': u'\xd8', + 'oslash': u'\xf8', + 'Oslash;': u'\xd8', + 'oslash;': u'\xf8', + 'osol;': u'\u2298', + 'Otilde': u'\xd5', + 'otilde': u'\xf5', + 'Otilde;': u'\xd5', + 'otilde;': u'\xf5', + 'Otimes;': u'\u2a37', + 'otimes;': u'\u2297', + 'otimesas;': u'\u2a36', + 'Ouml': u'\xd6', + 'ouml': u'\xf6', + 'Ouml;': u'\xd6', + 'ouml;': u'\xf6', + 'ovbar;': u'\u233d', + 'OverBar;': u'\u203e', + 'OverBrace;': u'\u23de', + 'OverBracket;': u'\u23b4', + 'OverParenthesis;': u'\u23dc', + 'par;': u'\u2225', + 'para': u'\xb6', + 'para;': u'\xb6', + 'parallel;': u'\u2225', + 'parsim;': u'\u2af3', + 'parsl;': u'\u2afd', + 'part;': u'\u2202', + 'PartialD;': u'\u2202', + 'Pcy;': u'\u041f', + 'pcy;': u'\u043f', + 'percnt;': u'%', + 'period;': u'.', + 'permil;': u'\u2030', + 'perp;': u'\u22a5', + 'pertenk;': u'\u2031', + 'Pfr;': u'\U0001d513', + 'pfr;': u'\U0001d52d', + 'Phi;': u'\u03a6', + 'phi;': u'\u03c6', + 'phiv;': u'\u03d5', + 'phmmat;': u'\u2133', + 'phone;': u'\u260e', + 'Pi;': u'\u03a0', + 'pi;': u'\u03c0', + 'pitchfork;': u'\u22d4', + 'piv;': u'\u03d6', + 'planck;': u'\u210f', + 'planckh;': u'\u210e', + 'plankv;': u'\u210f', + 'plus;': u'+', + 'plusacir;': u'\u2a23', + 'plusb;': u'\u229e', + 'pluscir;': u'\u2a22', + 'plusdo;': u'\u2214', + 'plusdu;': u'\u2a25', + 'pluse;': u'\u2a72', + 'PlusMinus;': u'\xb1', + 'plusmn': u'\xb1', + 'plusmn;': u'\xb1', + 'plussim;': u'\u2a26', + 'plustwo;': u'\u2a27', + 'pm;': u'\xb1', + 'Poincareplane;': u'\u210c', + 'pointint;': u'\u2a15', + 'Popf;': u'\u2119', + 'popf;': u'\U0001d561', + 'pound': u'\xa3', + 'pound;': u'\xa3', + 'Pr;': u'\u2abb', + 'pr;': u'\u227a', + 'prap;': u'\u2ab7', + 'prcue;': u'\u227c', + 'prE;': u'\u2ab3', + 'pre;': u'\u2aaf', + 'prec;': u'\u227a', + 'precapprox;': u'\u2ab7', + 'preccurlyeq;': u'\u227c', + 'Precedes;': u'\u227a', + 'PrecedesEqual;': u'\u2aaf', + 'PrecedesSlantEqual;': u'\u227c', + 'PrecedesTilde;': u'\u227e', + 'preceq;': u'\u2aaf', + 'precnapprox;': u'\u2ab9', + 'precneqq;': u'\u2ab5', + 'precnsim;': u'\u22e8', + 'precsim;': u'\u227e', + 'Prime;': u'\u2033', + 'prime;': u'\u2032', + 'primes;': u'\u2119', + 'prnap;': u'\u2ab9', + 'prnE;': u'\u2ab5', + 'prnsim;': u'\u22e8', + 'prod;': u'\u220f', + 'Product;': u'\u220f', + 'profalar;': u'\u232e', + 'profline;': u'\u2312', + 'profsurf;': u'\u2313', + 'prop;': u'\u221d', + 'Proportion;': u'\u2237', + 'Proportional;': u'\u221d', + 'propto;': u'\u221d', + 'prsim;': u'\u227e', + 'prurel;': u'\u22b0', + 'Pscr;': u'\U0001d4ab', + 'pscr;': u'\U0001d4c5', + 'Psi;': u'\u03a8', + 'psi;': u'\u03c8', + 'puncsp;': u'\u2008', + 'Qfr;': u'\U0001d514', + 'qfr;': u'\U0001d52e', + 'qint;': u'\u2a0c', + 'Qopf;': u'\u211a', + 'qopf;': u'\U0001d562', + 'qprime;': u'\u2057', + 'Qscr;': u'\U0001d4ac', + 'qscr;': u'\U0001d4c6', + 'quaternions;': u'\u210d', + 'quatint;': u'\u2a16', + 'quest;': u'?', + 'questeq;': u'\u225f', + 'QUOT': u'"', + 'quot': u'"', + 'QUOT;': u'"', + 'quot;': u'"', + 'rAarr;': u'\u21db', + 'race;': u'\u223d\u0331', + 'Racute;': u'\u0154', + 'racute;': u'\u0155', + 'radic;': u'\u221a', + 'raemptyv;': u'\u29b3', + 'Rang;': u'\u27eb', + 'rang;': u'\u27e9', + 'rangd;': u'\u2992', + 'range;': u'\u29a5', + 'rangle;': u'\u27e9', + 'raquo': u'\xbb', + 'raquo;': u'\xbb', + 'Rarr;': u'\u21a0', + 'rArr;': u'\u21d2', + 'rarr;': u'\u2192', + 'rarrap;': u'\u2975', + 'rarrb;': u'\u21e5', + 'rarrbfs;': u'\u2920', + 'rarrc;': u'\u2933', + 'rarrfs;': u'\u291e', + 'rarrhk;': u'\u21aa', + 'rarrlp;': u'\u21ac', + 'rarrpl;': u'\u2945', + 'rarrsim;': u'\u2974', + 'Rarrtl;': u'\u2916', + 'rarrtl;': u'\u21a3', + 'rarrw;': u'\u219d', + 'rAtail;': u'\u291c', + 'ratail;': u'\u291a', + 'ratio;': u'\u2236', + 'rationals;': u'\u211a', + 'RBarr;': u'\u2910', + 'rBarr;': u'\u290f', + 'rbarr;': u'\u290d', + 'rbbrk;': u'\u2773', + 'rbrace;': u'}', + 'rbrack;': u']', + 'rbrke;': u'\u298c', + 'rbrksld;': u'\u298e', + 'rbrkslu;': u'\u2990', + 'Rcaron;': u'\u0158', + 'rcaron;': u'\u0159', + 'Rcedil;': u'\u0156', + 'rcedil;': u'\u0157', + 'rceil;': u'\u2309', + 'rcub;': u'}', + 'Rcy;': u'\u0420', + 'rcy;': u'\u0440', + 'rdca;': u'\u2937', + 'rdldhar;': u'\u2969', + 'rdquo;': u'\u201d', + 'rdquor;': u'\u201d', + 'rdsh;': u'\u21b3', + 'Re;': u'\u211c', + 'real;': u'\u211c', + 'realine;': u'\u211b', + 'realpart;': u'\u211c', + 'reals;': u'\u211d', + 'rect;': u'\u25ad', + 'REG': u'\xae', + 'reg': u'\xae', + 'REG;': u'\xae', + 'reg;': u'\xae', + 'ReverseElement;': u'\u220b', + 'ReverseEquilibrium;': u'\u21cb', + 'ReverseUpEquilibrium;': u'\u296f', + 'rfisht;': u'\u297d', + 'rfloor;': u'\u230b', + 'Rfr;': u'\u211c', + 'rfr;': u'\U0001d52f', + 'rHar;': u'\u2964', + 'rhard;': u'\u21c1', + 'rharu;': u'\u21c0', + 'rharul;': u'\u296c', + 'Rho;': u'\u03a1', + 'rho;': u'\u03c1', + 'rhov;': u'\u03f1', + 'RightAngleBracket;': u'\u27e9', + 'RightArrow;': u'\u2192', + 'Rightarrow;': u'\u21d2', + 'rightarrow;': u'\u2192', + 'RightArrowBar;': u'\u21e5', + 'RightArrowLeftArrow;': u'\u21c4', + 'rightarrowtail;': u'\u21a3', + 'RightCeiling;': u'\u2309', + 'RightDoubleBracket;': u'\u27e7', + 'RightDownTeeVector;': u'\u295d', + 'RightDownVector;': u'\u21c2', + 'RightDownVectorBar;': u'\u2955', + 'RightFloor;': u'\u230b', + 'rightharpoondown;': u'\u21c1', + 'rightharpoonup;': u'\u21c0', + 'rightleftarrows;': u'\u21c4', + 'rightleftharpoons;': u'\u21cc', + 'rightrightarrows;': u'\u21c9', + 'rightsquigarrow;': u'\u219d', + 'RightTee;': u'\u22a2', + 'RightTeeArrow;': u'\u21a6', + 'RightTeeVector;': u'\u295b', + 'rightthreetimes;': u'\u22cc', + 'RightTriangle;': u'\u22b3', + 'RightTriangleBar;': u'\u29d0', + 'RightTriangleEqual;': u'\u22b5', + 'RightUpDownVector;': u'\u294f', + 'RightUpTeeVector;': u'\u295c', + 'RightUpVector;': u'\u21be', + 'RightUpVectorBar;': u'\u2954', + 'RightVector;': u'\u21c0', + 'RightVectorBar;': u'\u2953', + 'ring;': u'\u02da', + 'risingdotseq;': u'\u2253', + 'rlarr;': u'\u21c4', + 'rlhar;': u'\u21cc', + 'rlm;': u'\u200f', + 'rmoust;': u'\u23b1', + 'rmoustache;': u'\u23b1', + 'rnmid;': u'\u2aee', + 'roang;': u'\u27ed', + 'roarr;': u'\u21fe', + 'robrk;': u'\u27e7', + 'ropar;': u'\u2986', + 'Ropf;': u'\u211d', + 'ropf;': u'\U0001d563', + 'roplus;': u'\u2a2e', + 'rotimes;': u'\u2a35', + 'RoundImplies;': u'\u2970', + 'rpar;': u')', + 'rpargt;': u'\u2994', + 'rppolint;': u'\u2a12', + 'rrarr;': u'\u21c9', + 'Rrightarrow;': u'\u21db', + 'rsaquo;': u'\u203a', + 'Rscr;': u'\u211b', + 'rscr;': u'\U0001d4c7', + 'Rsh;': u'\u21b1', + 'rsh;': u'\u21b1', + 'rsqb;': u']', + 'rsquo;': u'\u2019', + 'rsquor;': u'\u2019', + 'rthree;': u'\u22cc', + 'rtimes;': u'\u22ca', + 'rtri;': u'\u25b9', + 'rtrie;': u'\u22b5', + 'rtrif;': u'\u25b8', + 'rtriltri;': u'\u29ce', + 'RuleDelayed;': u'\u29f4', + 'ruluhar;': u'\u2968', + 'rx;': u'\u211e', + 'Sacute;': u'\u015a', + 'sacute;': u'\u015b', + 'sbquo;': u'\u201a', + 'Sc;': u'\u2abc', + 'sc;': u'\u227b', + 'scap;': u'\u2ab8', + 'Scaron;': u'\u0160', + 'scaron;': u'\u0161', + 'sccue;': u'\u227d', + 'scE;': u'\u2ab4', + 'sce;': u'\u2ab0', + 'Scedil;': u'\u015e', + 'scedil;': u'\u015f', + 'Scirc;': u'\u015c', + 'scirc;': u'\u015d', + 'scnap;': u'\u2aba', + 'scnE;': u'\u2ab6', + 'scnsim;': u'\u22e9', + 'scpolint;': u'\u2a13', + 'scsim;': u'\u227f', + 'Scy;': u'\u0421', + 'scy;': u'\u0441', + 'sdot;': u'\u22c5', + 'sdotb;': u'\u22a1', + 'sdote;': u'\u2a66', + 'searhk;': u'\u2925', + 'seArr;': u'\u21d8', + 'searr;': u'\u2198', + 'searrow;': u'\u2198', + 'sect': u'\xa7', + 'sect;': u'\xa7', + 'semi;': u';', + 'seswar;': u'\u2929', + 'setminus;': u'\u2216', + 'setmn;': u'\u2216', + 'sext;': u'\u2736', + 'Sfr;': u'\U0001d516', + 'sfr;': u'\U0001d530', + 'sfrown;': u'\u2322', + 'sharp;': u'\u266f', + 'SHCHcy;': u'\u0429', + 'shchcy;': u'\u0449', + 'SHcy;': u'\u0428', + 'shcy;': u'\u0448', + 'ShortDownArrow;': u'\u2193', + 'ShortLeftArrow;': u'\u2190', + 'shortmid;': u'\u2223', + 'shortparallel;': u'\u2225', + 'ShortRightArrow;': u'\u2192', + 'ShortUpArrow;': u'\u2191', + 'shy': u'\xad', + 'shy;': u'\xad', + 'Sigma;': u'\u03a3', + 'sigma;': u'\u03c3', + 'sigmaf;': u'\u03c2', + 'sigmav;': u'\u03c2', + 'sim;': u'\u223c', + 'simdot;': u'\u2a6a', + 'sime;': u'\u2243', + 'simeq;': u'\u2243', + 'simg;': u'\u2a9e', + 'simgE;': u'\u2aa0', + 'siml;': u'\u2a9d', + 'simlE;': u'\u2a9f', + 'simne;': u'\u2246', + 'simplus;': u'\u2a24', + 'simrarr;': u'\u2972', + 'slarr;': u'\u2190', + 'SmallCircle;': u'\u2218', + 'smallsetminus;': u'\u2216', + 'smashp;': u'\u2a33', + 'smeparsl;': u'\u29e4', + 'smid;': u'\u2223', + 'smile;': u'\u2323', + 'smt;': u'\u2aaa', + 'smte;': u'\u2aac', + 'smtes;': u'\u2aac\ufe00', + 'SOFTcy;': u'\u042c', + 'softcy;': u'\u044c', + 'sol;': u'/', + 'solb;': u'\u29c4', + 'solbar;': u'\u233f', + 'Sopf;': u'\U0001d54a', + 'sopf;': u'\U0001d564', + 'spades;': u'\u2660', + 'spadesuit;': u'\u2660', + 'spar;': u'\u2225', + 'sqcap;': u'\u2293', + 'sqcaps;': u'\u2293\ufe00', + 'sqcup;': u'\u2294', + 'sqcups;': u'\u2294\ufe00', + 'Sqrt;': u'\u221a', + 'sqsub;': u'\u228f', + 'sqsube;': u'\u2291', + 'sqsubset;': u'\u228f', + 'sqsubseteq;': u'\u2291', + 'sqsup;': u'\u2290', + 'sqsupe;': u'\u2292', + 'sqsupset;': u'\u2290', + 'sqsupseteq;': u'\u2292', + 'squ;': u'\u25a1', + 'Square;': u'\u25a1', + 'square;': u'\u25a1', + 'SquareIntersection;': u'\u2293', + 'SquareSubset;': u'\u228f', + 'SquareSubsetEqual;': u'\u2291', + 'SquareSuperset;': u'\u2290', + 'SquareSupersetEqual;': u'\u2292', + 'SquareUnion;': u'\u2294', + 'squarf;': u'\u25aa', + 'squf;': u'\u25aa', + 'srarr;': u'\u2192', + 'Sscr;': u'\U0001d4ae', + 'sscr;': u'\U0001d4c8', + 'ssetmn;': u'\u2216', + 'ssmile;': u'\u2323', + 'sstarf;': u'\u22c6', + 'Star;': u'\u22c6', + 'star;': u'\u2606', + 'starf;': u'\u2605', + 'straightepsilon;': u'\u03f5', + 'straightphi;': u'\u03d5', + 'strns;': u'\xaf', + 'Sub;': u'\u22d0', + 'sub;': u'\u2282', + 'subdot;': u'\u2abd', + 'subE;': u'\u2ac5', + 'sube;': u'\u2286', + 'subedot;': u'\u2ac3', + 'submult;': u'\u2ac1', + 'subnE;': u'\u2acb', + 'subne;': u'\u228a', + 'subplus;': u'\u2abf', + 'subrarr;': u'\u2979', + 'Subset;': u'\u22d0', + 'subset;': u'\u2282', + 'subseteq;': u'\u2286', + 'subseteqq;': u'\u2ac5', + 'SubsetEqual;': u'\u2286', + 'subsetneq;': u'\u228a', + 'subsetneqq;': u'\u2acb', + 'subsim;': u'\u2ac7', + 'subsub;': u'\u2ad5', + 'subsup;': u'\u2ad3', + 'succ;': u'\u227b', + 'succapprox;': u'\u2ab8', + 'succcurlyeq;': u'\u227d', + 'Succeeds;': u'\u227b', + 'SucceedsEqual;': u'\u2ab0', + 'SucceedsSlantEqual;': u'\u227d', + 'SucceedsTilde;': u'\u227f', + 'succeq;': u'\u2ab0', + 'succnapprox;': u'\u2aba', + 'succneqq;': u'\u2ab6', + 'succnsim;': u'\u22e9', + 'succsim;': u'\u227f', + 'SuchThat;': u'\u220b', + 'Sum;': u'\u2211', + 'sum;': u'\u2211', + 'sung;': u'\u266a', + 'sup1': u'\xb9', + 'sup1;': u'\xb9', + 'sup2': u'\xb2', + 'sup2;': u'\xb2', + 'sup3': u'\xb3', + 'sup3;': u'\xb3', + 'Sup;': u'\u22d1', + 'sup;': u'\u2283', + 'supdot;': u'\u2abe', + 'supdsub;': u'\u2ad8', + 'supE;': u'\u2ac6', + 'supe;': u'\u2287', + 'supedot;': u'\u2ac4', + 'Superset;': u'\u2283', + 'SupersetEqual;': u'\u2287', + 'suphsol;': u'\u27c9', + 'suphsub;': u'\u2ad7', + 'suplarr;': u'\u297b', + 'supmult;': u'\u2ac2', + 'supnE;': u'\u2acc', + 'supne;': u'\u228b', + 'supplus;': u'\u2ac0', + 'Supset;': u'\u22d1', + 'supset;': u'\u2283', + 'supseteq;': u'\u2287', + 'supseteqq;': u'\u2ac6', + 'supsetneq;': u'\u228b', + 'supsetneqq;': u'\u2acc', + 'supsim;': u'\u2ac8', + 'supsub;': u'\u2ad4', + 'supsup;': u'\u2ad6', + 'swarhk;': u'\u2926', + 'swArr;': u'\u21d9', + 'swarr;': u'\u2199', + 'swarrow;': u'\u2199', + 'swnwar;': u'\u292a', + 'szlig': u'\xdf', + 'szlig;': u'\xdf', + 'Tab;': u'\t', + 'target;': u'\u2316', + 'Tau;': u'\u03a4', + 'tau;': u'\u03c4', + 'tbrk;': u'\u23b4', + 'Tcaron;': u'\u0164', + 'tcaron;': u'\u0165', + 'Tcedil;': u'\u0162', + 'tcedil;': u'\u0163', + 'Tcy;': u'\u0422', + 'tcy;': u'\u0442', + 'tdot;': u'\u20db', + 'telrec;': u'\u2315', + 'Tfr;': u'\U0001d517', + 'tfr;': u'\U0001d531', + 'there4;': u'\u2234', + 'Therefore;': u'\u2234', + 'therefore;': u'\u2234', + 'Theta;': u'\u0398', + 'theta;': u'\u03b8', + 'thetasym;': u'\u03d1', + 'thetav;': u'\u03d1', + 'thickapprox;': u'\u2248', + 'thicksim;': u'\u223c', + 'ThickSpace;': u'\u205f\u200a', + 'thinsp;': u'\u2009', + 'ThinSpace;': u'\u2009', + 'thkap;': u'\u2248', + 'thksim;': u'\u223c', + 'THORN': u'\xde', + 'thorn': u'\xfe', + 'THORN;': u'\xde', + 'thorn;': u'\xfe', + 'Tilde;': u'\u223c', + 'tilde;': u'\u02dc', + 'TildeEqual;': u'\u2243', + 'TildeFullEqual;': u'\u2245', + 'TildeTilde;': u'\u2248', + 'times': u'\xd7', + 'times;': u'\xd7', + 'timesb;': u'\u22a0', + 'timesbar;': u'\u2a31', + 'timesd;': u'\u2a30', + 'tint;': u'\u222d', + 'toea;': u'\u2928', + 'top;': u'\u22a4', + 'topbot;': u'\u2336', + 'topcir;': u'\u2af1', + 'Topf;': u'\U0001d54b', + 'topf;': u'\U0001d565', + 'topfork;': u'\u2ada', + 'tosa;': u'\u2929', + 'tprime;': u'\u2034', + 'TRADE;': u'\u2122', + 'trade;': u'\u2122', + 'triangle;': u'\u25b5', + 'triangledown;': u'\u25bf', + 'triangleleft;': u'\u25c3', + 'trianglelefteq;': u'\u22b4', + 'triangleq;': u'\u225c', + 'triangleright;': u'\u25b9', + 'trianglerighteq;': u'\u22b5', + 'tridot;': u'\u25ec', + 'trie;': u'\u225c', + 'triminus;': u'\u2a3a', + 'TripleDot;': u'\u20db', + 'triplus;': u'\u2a39', + 'trisb;': u'\u29cd', + 'tritime;': u'\u2a3b', + 'trpezium;': u'\u23e2', + 'Tscr;': u'\U0001d4af', + 'tscr;': u'\U0001d4c9', + 'TScy;': u'\u0426', + 'tscy;': u'\u0446', + 'TSHcy;': u'\u040b', + 'tshcy;': u'\u045b', + 'Tstrok;': u'\u0166', + 'tstrok;': u'\u0167', + 'twixt;': u'\u226c', + 'twoheadleftarrow;': u'\u219e', + 'twoheadrightarrow;': u'\u21a0', + 'Uacute': u'\xda', + 'uacute': u'\xfa', + 'Uacute;': u'\xda', + 'uacute;': u'\xfa', + 'Uarr;': u'\u219f', + 'uArr;': u'\u21d1', + 'uarr;': u'\u2191', + 'Uarrocir;': u'\u2949', + 'Ubrcy;': u'\u040e', + 'ubrcy;': u'\u045e', + 'Ubreve;': u'\u016c', + 'ubreve;': u'\u016d', + 'Ucirc': u'\xdb', + 'ucirc': u'\xfb', + 'Ucirc;': u'\xdb', + 'ucirc;': u'\xfb', + 'Ucy;': u'\u0423', + 'ucy;': u'\u0443', + 'udarr;': u'\u21c5', + 'Udblac;': u'\u0170', + 'udblac;': u'\u0171', + 'udhar;': u'\u296e', + 'ufisht;': u'\u297e', + 'Ufr;': u'\U0001d518', + 'ufr;': u'\U0001d532', + 'Ugrave': u'\xd9', + 'ugrave': u'\xf9', + 'Ugrave;': u'\xd9', + 'ugrave;': u'\xf9', + 'uHar;': u'\u2963', + 'uharl;': u'\u21bf', + 'uharr;': u'\u21be', + 'uhblk;': u'\u2580', + 'ulcorn;': u'\u231c', + 'ulcorner;': u'\u231c', + 'ulcrop;': u'\u230f', + 'ultri;': u'\u25f8', + 'Umacr;': u'\u016a', + 'umacr;': u'\u016b', + 'uml': u'\xa8', + 'uml;': u'\xa8', + 'UnderBar;': u'_', + 'UnderBrace;': u'\u23df', + 'UnderBracket;': u'\u23b5', + 'UnderParenthesis;': u'\u23dd', + 'Union;': u'\u22c3', + 'UnionPlus;': u'\u228e', + 'Uogon;': u'\u0172', + 'uogon;': u'\u0173', + 'Uopf;': u'\U0001d54c', + 'uopf;': u'\U0001d566', + 'UpArrow;': u'\u2191', + 'Uparrow;': u'\u21d1', + 'uparrow;': u'\u2191', + 'UpArrowBar;': u'\u2912', + 'UpArrowDownArrow;': u'\u21c5', + 'UpDownArrow;': u'\u2195', + 'Updownarrow;': u'\u21d5', + 'updownarrow;': u'\u2195', + 'UpEquilibrium;': u'\u296e', + 'upharpoonleft;': u'\u21bf', + 'upharpoonright;': u'\u21be', + 'uplus;': u'\u228e', + 'UpperLeftArrow;': u'\u2196', + 'UpperRightArrow;': u'\u2197', + 'Upsi;': u'\u03d2', + 'upsi;': u'\u03c5', + 'upsih;': u'\u03d2', + 'Upsilon;': u'\u03a5', + 'upsilon;': u'\u03c5', + 'UpTee;': u'\u22a5', + 'UpTeeArrow;': u'\u21a5', + 'upuparrows;': u'\u21c8', + 'urcorn;': u'\u231d', + 'urcorner;': u'\u231d', + 'urcrop;': u'\u230e', + 'Uring;': u'\u016e', + 'uring;': u'\u016f', + 'urtri;': u'\u25f9', + 'Uscr;': u'\U0001d4b0', + 'uscr;': u'\U0001d4ca', + 'utdot;': u'\u22f0', + 'Utilde;': u'\u0168', + 'utilde;': u'\u0169', + 'utri;': u'\u25b5', + 'utrif;': u'\u25b4', + 'uuarr;': u'\u21c8', + 'Uuml': u'\xdc', + 'uuml': u'\xfc', + 'Uuml;': u'\xdc', + 'uuml;': u'\xfc', + 'uwangle;': u'\u29a7', + 'vangrt;': u'\u299c', + 'varepsilon;': u'\u03f5', + 'varkappa;': u'\u03f0', + 'varnothing;': u'\u2205', + 'varphi;': u'\u03d5', + 'varpi;': u'\u03d6', + 'varpropto;': u'\u221d', + 'vArr;': u'\u21d5', + 'varr;': u'\u2195', + 'varrho;': u'\u03f1', + 'varsigma;': u'\u03c2', + 'varsubsetneq;': u'\u228a\ufe00', + 'varsubsetneqq;': u'\u2acb\ufe00', + 'varsupsetneq;': u'\u228b\ufe00', + 'varsupsetneqq;': u'\u2acc\ufe00', + 'vartheta;': u'\u03d1', + 'vartriangleleft;': u'\u22b2', + 'vartriangleright;': u'\u22b3', + 'Vbar;': u'\u2aeb', + 'vBar;': u'\u2ae8', + 'vBarv;': u'\u2ae9', + 'Vcy;': u'\u0412', + 'vcy;': u'\u0432', + 'VDash;': u'\u22ab', + 'Vdash;': u'\u22a9', + 'vDash;': u'\u22a8', + 'vdash;': u'\u22a2', + 'Vdashl;': u'\u2ae6', + 'Vee;': u'\u22c1', + 'vee;': u'\u2228', + 'veebar;': u'\u22bb', + 'veeeq;': u'\u225a', + 'vellip;': u'\u22ee', + 'Verbar;': u'\u2016', + 'verbar;': u'|', + 'Vert;': u'\u2016', + 'vert;': u'|', + 'VerticalBar;': u'\u2223', + 'VerticalLine;': u'|', + 'VerticalSeparator;': u'\u2758', + 'VerticalTilde;': u'\u2240', + 'VeryThinSpace;': u'\u200a', + 'Vfr;': u'\U0001d519', + 'vfr;': u'\U0001d533', + 'vltri;': u'\u22b2', + 'vnsub;': u'\u2282\u20d2', + 'vnsup;': u'\u2283\u20d2', + 'Vopf;': u'\U0001d54d', + 'vopf;': u'\U0001d567', + 'vprop;': u'\u221d', + 'vrtri;': u'\u22b3', + 'Vscr;': u'\U0001d4b1', + 'vscr;': u'\U0001d4cb', + 'vsubnE;': u'\u2acb\ufe00', + 'vsubne;': u'\u228a\ufe00', + 'vsupnE;': u'\u2acc\ufe00', + 'vsupne;': u'\u228b\ufe00', + 'Vvdash;': u'\u22aa', + 'vzigzag;': u'\u299a', + 'Wcirc;': u'\u0174', + 'wcirc;': u'\u0175', + 'wedbar;': u'\u2a5f', + 'Wedge;': u'\u22c0', + 'wedge;': u'\u2227', + 'wedgeq;': u'\u2259', + 'weierp;': u'\u2118', + 'Wfr;': u'\U0001d51a', + 'wfr;': u'\U0001d534', + 'Wopf;': u'\U0001d54e', + 'wopf;': u'\U0001d568', + 'wp;': u'\u2118', + 'wr;': u'\u2240', + 'wreath;': u'\u2240', + 'Wscr;': u'\U0001d4b2', + 'wscr;': u'\U0001d4cc', + 'xcap;': u'\u22c2', + 'xcirc;': u'\u25ef', + 'xcup;': u'\u22c3', + 'xdtri;': u'\u25bd', + 'Xfr;': u'\U0001d51b', + 'xfr;': u'\U0001d535', + 'xhArr;': u'\u27fa', + 'xharr;': u'\u27f7', + 'Xi;': u'\u039e', + 'xi;': u'\u03be', + 'xlArr;': u'\u27f8', + 'xlarr;': u'\u27f5', + 'xmap;': u'\u27fc', + 'xnis;': u'\u22fb', + 'xodot;': u'\u2a00', + 'Xopf;': u'\U0001d54f', + 'xopf;': u'\U0001d569', + 'xoplus;': u'\u2a01', + 'xotime;': u'\u2a02', + 'xrArr;': u'\u27f9', + 'xrarr;': u'\u27f6', + 'Xscr;': u'\U0001d4b3', + 'xscr;': u'\U0001d4cd', + 'xsqcup;': u'\u2a06', + 'xuplus;': u'\u2a04', + 'xutri;': u'\u25b3', + 'xvee;': u'\u22c1', + 'xwedge;': u'\u22c0', + 'Yacute': u'\xdd', + 'yacute': u'\xfd', + 'Yacute;': u'\xdd', + 'yacute;': u'\xfd', + 'YAcy;': u'\u042f', + 'yacy;': u'\u044f', + 'Ycirc;': u'\u0176', + 'ycirc;': u'\u0177', + 'Ycy;': u'\u042b', + 'ycy;': u'\u044b', + 'yen': u'\xa5', + 'yen;': u'\xa5', + 'Yfr;': u'\U0001d51c', + 'yfr;': u'\U0001d536', + 'YIcy;': u'\u0407', + 'yicy;': u'\u0457', + 'Yopf;': u'\U0001d550', + 'yopf;': u'\U0001d56a', + 'Yscr;': u'\U0001d4b4', + 'yscr;': u'\U0001d4ce', + 'YUcy;': u'\u042e', + 'yucy;': u'\u044e', + 'yuml': u'\xff', + 'Yuml;': u'\u0178', + 'yuml;': u'\xff', + 'Zacute;': u'\u0179', + 'zacute;': u'\u017a', + 'Zcaron;': u'\u017d', + 'zcaron;': u'\u017e', + 'Zcy;': u'\u0417', + 'zcy;': u'\u0437', + 'Zdot;': u'\u017b', + 'zdot;': u'\u017c', + 'zeetrf;': u'\u2128', + 'ZeroWidthSpace;': u'\u200b', + 'Zeta;': u'\u0396', + 'zeta;': u'\u03b6', + 'Zfr;': u'\u2128', + 'zfr;': u'\U0001d537', + 'ZHcy;': u'\u0416', + 'zhcy;': u'\u0436', + 'zigrarr;': u'\u21dd', + 'Zopf;': u'\u2124', + 'zopf;': u'\U0001d56b', + 'Zscr;': u'\U0001d4b5', + 'zscr;': u'\U0001d4cf', + 'zwj;': u'\u200d', + 'zwnj;': u'\u200c', +} + + class EntitySubstitution(object): """The ability to substitute XML or HTML entities for certain characters.""" def _populate_class_variables(): - lookup = {} - reverse_lookup = {} - characters_for_re = [] - - # &apos is an XHTML entity and an HTML 5, but not an HTML 4 - # entity. We don't want to use it, but we want to recognize it on the way in. - # - # TODO: Ideally we would be able to recognize all HTML 5 named - # entities, but that's a little tricky. - extra = [(39, 'apos')] - for codepoint, name in list(codepoint2name.items()) + extra: + """Initialize variables used by this class to manage the plethora of + HTML5 named entities. + + This function returns a 3-tuple containing two dictionaries + and a regular expression: + + unicode_to_name - A mapping of Unicode strings like "⦨" to + entity names like "angmsdaa". When a single Unicode string has + multiple entity names, we try to choose the most commonly-used + name. + + name_to_unicode: A mapping of entity names like "angmsdaa" to + Unicode strings like "⦨". + + named_entity_re: A regular expression matching (almost) any + Unicode string that corresponds to an HTML5 named entity. + """ + unicode_to_name = {} + name_to_unicode = {} + + short_entities = set() + long_entities_by_first_character = defaultdict(set) + + for name_with_semicolon, character in sorted(html5.items()): + # "It is intentional, for legacy compatibility, that many + # code points have multiple character reference names. For + # example, some appear both with and without the trailing + # semicolon, or with different capitalizations." + # - https://html.spec.whatwg.org/multipage/named-characters.html#named-character-references + # + # The parsers are in charge of handling (or not) character + # references with no trailing semicolon, so we remove the + # semicolon whenever it appears. + if name_with_semicolon.endswith(';'): + name = name_with_semicolon[:-1] + else: + name = name_with_semicolon + + # When parsing HTML, we want to recognize any known named + # entity and convert it to a sequence of Unicode + # characters. + if name not in name_to_unicode: + name_to_unicode[name] = character + + # When _generating_ HTML, we want to recognize special + # character sequences that _could_ be converted to named + # entities. + unicode_to_name[character] = name + + # We also need to build a regular expression that lets us + # _find_ those characters in output strings so we can + # replace them. + # + # This is tricky, for two reasons. + + if (len(character) == 1 and ord(character) < 128 + and character not in '<>&'): + # First, it would be annoying to turn single ASCII + # characters like | into named entities like + # |. The exceptions are <>&, which we _must_ + # turn into named entities to produce valid HTML. + continue + + if len(character) > 1 and all(ord(x) < 128 for x in character): + # We also do not want to turn _combinations_ of ASCII + # characters like 'fj' into named entities like 'fj', + # though that's more debateable. + continue + + # Second, some named entities have a Unicode value that's + # a subset of the Unicode value for some _other_ named + # entity. As an example, \u2267' is ≧, + # but '\u2267\u0338' is ≧̸. Our regular + # expression needs to match the first two characters of + # "\u2267\u0338foo", but only the first character of + # "\u2267foo". + # + # In this step, we build two sets of characters that + # _eventually_ need to go into the regular expression. But + # we won't know exactly what the regular expression needs + # to look like until we've gone through the entire list of + # named entities. + if len(character) == 1: + short_entities.add(character) + else: + long_entities_by_first_character[character[0]].add(character) + + # Now that we've been through the entire list of entities, we + # can create a regular expression that matches any of them. + particles = set() + for short in short_entities: + long_versions = long_entities_by_first_character[short] + if not long_versions: + particles.add(short) + else: + ignore = "".join([x[1] for x in long_versions]) + # This finds, e.g. \u2267 but only if it is _not_ + # followed by \u0338. + particles.add("%s(?![%s])" % (short, ignore)) + + for long_entities in long_entities_by_first_character.values(): + for long_entity in long_entities: + particles.add(long_entity) + + re_definition = "(%s)" % "|".join(particles) + + # If an entity shows up in both html5 and codepoint2name, it's + # likely that HTML5 gives it several different names, such as + # 'rsquo' and 'rsquor'. When converting Unicode characters to + # named entities, the codepoint2name name should take + # precedence where possible, since that's the more easily + # recognizable one. + for codepoint, name in codepoint2name.items(): character = unichr(codepoint) - if codepoint not in (34, 39): - # There's no point in turning the quotation mark into - # " or the single quote into ', unless it - # happens within an attribute value, which is handled - # elsewhere. - characters_for_re.append(character) - lookup[character] = name - # But we do want to recognize those entities on the way in and - # convert them to Unicode characters. - reverse_lookup[name] = character - re_definition = "[%s]" % "".join(characters_for_re) - return lookup, reverse_lookup, re.compile(re_definition) + unicode_to_name[character] = name + + return unicode_to_name, name_to_unicode, re.compile(re_definition) (CHARACTER_TO_HTML_ENTITY, HTML_ENTITY_TO_CHARACTER, CHARACTER_TO_HTML_ENTITY_RE) = _populate_class_variables() @@ -113,14 +2448,14 @@ class EntitySubstitution(object): @classmethod def _substitute_html_entity(cls, matchobj): """Used with a regular expression to substitute the - appropriate HTML entity for a special character.""" + appropriate HTML entity for a special character string.""" entity = cls.CHARACTER_TO_HTML_ENTITY.get(matchobj.group(0)) return "&%s;" % entity @classmethod def _substitute_xml_entity(cls, matchobj): """Used with a regular expression to substitute the - appropriate XML entity for a special character.""" + appropriate XML entity for a special character string.""" entity = cls.CHARACTER_TO_XML_ENTITY[matchobj.group(0)] return "&%s;" % entity diff --git a/bs4/testing.py b/bs4/testing.py index 87cd13f..5b0eb7c 100644 --- a/bs4/testing.py +++ b/bs4/testing.py @@ -234,13 +234,13 @@ class TreeBuilderSmokeTest(object): def test_fuzzed_input(self): # This test centralizes in one place the various fuzz tests - # for Beautiful Soup created by the oss-fuzz. + # for Beautiful Soup created by the oss-fuzz project. # These strings superficially resemble markup, but they # generally can't be parsed into anything. The best we can # hope for is that parsing these strings won't crash the # parser. - + # # n.b. This markup is commented out because these fuzz tests # _do_ crash the parser. However the crashes are due to bugs # in html.parser, not Beautiful Soup -- otherwise I'd fix the @@ -261,7 +261,6 @@ class TreeBuilderSmokeTest(object): for markup in bad_markup: with warnings.catch_warnings(record=False): soup = self.soup(markup) - pass class HTMLTreeBuilderSmokeTest(TreeBuilderSmokeTest): @@ -625,7 +624,7 @@ Hello, world! self.assertSoupEquals("�", expect) self.assertSoupEquals("�", expect) self.assertSoupEquals("�", expect) - + def test_multipart_strings(self): "Mostly to prevent a recurrence of a bug in the html5lib treebuilder." soup = self.soup("<html><h2>\nfoo</h2><p></p></html>") diff --git a/bs4/tests/test_html5lib.py b/bs4/tests/test_html5lib.py index 7b0a6d4..2adebc8 100644 --- a/bs4/tests/test_html5lib.py +++ b/bs4/tests/test_html5lib.py @@ -188,3 +188,39 @@ class HTML5LibBuilderSmokeTest(SoupTest, HTML5TreeBuilderSmokeTest): # because there's no way of knowing, when a string is created, # where in the tree it will eventually end up. pass + + def test_html5_attributes(self): + # The html5lib TreeBuilder can convert any entity named in + # the HTML5 spec to a sequence of Unicode characters, and + # convert those Unicode characters to a (potentially + # different) named entity on the way out. + # + # This is a copy of the same test from + # HTMLParserTreeBuilderSmokeTest. It's not in the superclass + # because the lxml HTML TreeBuilder _doesn't_ work this way. + for input_element, output_unicode, output_element in ( + ("⇄", u'\u21c4', b'⇄'), + ('⊧', u'\u22a7', b'⊧'), + ('𝔑', u'\U0001d511', b'𝔑'), + ('≧̸', u'\u2267\u0338', b'≧̸'), + ('¬', u'\xac', b'¬'), + ('⫬', u'\u2aec', b'⫬'), + ('"', u'"', b'"'), + ('∴', u'\u2234', b'∴'), + ('∴', u'\u2234', b'∴'), + ('∴', u'\u2234', b'∴'), + ("fj", u'fj', b'fj'), + ("⊔", u'\u2294', b'⊔'), + ("⊔︀", u'\u2294\ufe00', b'⊔︀'), + ("'", u"'", b"'"), + ("|", u"|", b"|"), + ): + markup = u'<div>%s</div>' % input_element + div = self.soup(markup).div + without_element = div.encode() + expect = b"<div>%s</div>" % output_unicode.encode("utf8") + self.assertEquals(without_element, expect) + + with_element = div.encode(formatter="html") + expect = b"<div>%s</div>" % output_element + self.assertEquals(with_element, expect) diff --git a/bs4/tests/test_htmlparser.py b/bs4/tests/test_htmlparser.py index db85d2d..e84eced 100644 --- a/bs4/tests/test_htmlparser.py +++ b/bs4/tests/test_htmlparser.py @@ -88,6 +88,38 @@ class HTMLParserTreeBuilderSmokeTest(SoupTest, HTMLTreeBuilderSmokeTest): attrs[key].append(value) assert_attribute(accumulate, ["url1", "url2", "url3"]) + def test_html5_attributes(self): + # The html.parser TreeBuilder can convert any entity named in + # the HTML5 spec to a sequence of Unicode characters, and + # convert those Unicode characters to a (potentially + # different) named entity on the way out. + for input_element, output_unicode, output_element in ( + ("⇄", u'\u21c4', b'⇄'), + ('⊧', u'\u22a7', b'⊧'), + ('𝔑', u'\U0001d511', b'𝔑'), + ('≧̸', u'\u2267\u0338', b'≧̸'), + ('¬', u'\xac', b'¬'), + ('⫬', u'\u2aec', b'⫬'), + ('"', u'"', b'"'), + ('∴', u'\u2234', b'∴'), + ('∴', u'\u2234', b'∴'), + ('∴', u'\u2234', b'∴'), + ("fj", u'fj', b'fj'), + ("⊔", u'\u2294', b'⊔'), + ("⊔︀", u'\u2294\ufe00', b'⊔︀'), + ("'", u"'", b"'"), + ("|", u"|", b"|"), + ): + markup = u'<div>%s</div>' % input_element + div = self.soup(markup).div + without_element = div.encode() + expect = b"<div>%s</div>" % output_unicode.encode("utf8") + self.assertEquals(without_element, expect) + + with_element = div.encode(formatter="html") + expect = b"<div>%s</div>" % output_element + self.assertEquals(with_element, expect) + class TestHTMLParserSubclass(SoupTest): def test_error(self): diff --git a/bs4/tests/test_lxml.py b/bs4/tests/test_lxml.py index f96e4ae..d8dada4 100644 --- a/bs4/tests/test_lxml.py +++ b/bs4/tests/test_lxml.py @@ -45,7 +45,7 @@ class LXMLTreeBuilderSmokeTest(SoupTest, HTMLTreeBuilderSmokeTest): "<p>foo�bar</p>", "<p>foobar</p>") self.assertSoupEquals( "<p>foo�bar</p>", "<p>foobar</p>") - + def test_entities_in_foreign_document_encoding(self): # We can't implement this case correctly because by the time we # hear about markup like "“", it's been (incorrectly) converted into diff --git a/bs4/tests/test_soup.py b/bs4/tests/test_soup.py index ddb6446..9074bdb 100644 --- a/bs4/tests/test_soup.py +++ b/bs4/tests/test_soup.py @@ -368,6 +368,51 @@ class TestEntitySubstitution(unittest.TestCase): self.assertEqual(self.sub.substitute_html(dammit.markup), "‘’foo“”") + def test_html5_entity(self): + # Some HTML5 entities correspond to single- or multi-character + # Unicode sequences. + + for entity, u in ( + # A few spot checks of our ability to recognize + # special character sequences and convert them + # to named entities. + ('⊧', u'\u22a7'), + ('𝔑', u'\U0001d511'), + ('≧̸', u'\u2267\u0338'), + ('¬', u'\xac'), + ('⫬', u'\u2aec'), + + # We _could_ convert | to &verbarr;, but we don't, because + # | is an ASCII character. + ('|' '|'), + + # Similarly for the fj ligature, which we could convert to + # fj, but we don't. + ("fj", "fj"), + + # We do convert _these_ ASCII characters to HTML entities, + # because that's required to generate valid HTML. + ('>', '>'), + ('<', '<'), + ('&', '&'), + ): + template = u'3 %s 4' + raw = template % u + with_entities = template % entity + self.assertEqual(self.sub.substitute_html(raw), with_entities) + + def test_html5_entity_with_variation_selector(self): + # Some HTML5 entities correspond either to a single-character + # Unicode sequence _or_ to the same character plus U+FE00, + # VARIATION SELECTOR 1. We can handle this. + data = u"fjords \u2294 penguins" + markup = u"fjords ⊔ penguins" + self.assertEqual(self.sub.substitute_html(data), markup) + + data = u"fjords \u2294\ufe00 penguins" + markup = u"fjords ⊔︀ penguins" + self.assertEqual(self.sub.substitute_html(data), markup) + def test_xml_converstion_includes_no_quotes_if_make_quoted_attribute_is_false(self): s = 'Welcome to "my bar"' self.assertEqual(self.sub.substitute_xml(s, False), s) |