1#
2#
3#            Nim's Runtime Library
4#        (c) Copyright 2013 Andreas Rumpf
5#
6#    See the file "copying.txt", included in this
7#    distribution, for details about the copyright.
8#
9
10## **NOTE**: The behaviour might change in future versions as it is not
11## clear what "*wild* HTML the real world uses" really implies.
12##
13## It can be used to parse a wild HTML document and output it as valid XHTML
14## document (well, if you are lucky):
15##
16## .. code-block:: Nim
17##
18##   echo loadHtml("mydirty.html")
19##
20## Every tag in the resulting tree is in lower case.
21##
22## **Note:** The resulting `XmlNode` already uses the `clientData` field,
23## so it cannot be used by clients of this library.
24##
25## Example: Transforming hyperlinks
26## ================================
27##
28## This code demonstrates how you can iterate over all the tags in an HTML file
29## and write back the modified version. In this case we look for hyperlinks
30## ending with the extension `.rst` and convert them to `.html`.
31##
32## .. code-block:: Nim
33##     :test:
34##
35##   import std/htmlparser
36##   import std/xmltree  # To use '$' for XmlNode
37##   import std/strtabs  # To access XmlAttributes
38##   import std/os       # To use splitFile
39##   import std/strutils # To use cmpIgnoreCase
40##
41##   proc transformHyperlinks() =
42##     let html = loadHtml("input.html")
43##
44##     for a in html.findAll("a"):
45##       if a.attrs.hasKey "href":
46##         let (dir, filename, ext) = splitFile(a.attrs["href"])
47##         if cmpIgnoreCase(ext, ".rst") == 0:
48##           a.attrs["href"] = dir / filename & ".html"
49##
50##     writeFile("output.html", $html)
51
52import strutils, streams, parsexml, xmltree, unicode, strtabs
53
54type
55  HtmlTag* = enum  ## list of all supported HTML tags; order will always be
56                   ## alphabetically
57    tagUnknown,    ## unknown HTML element
58    tagA,          ## the HTML `a` element
59    tagAbbr,       ## the deprecated HTML `abbr` element
60    tagAcronym,    ## the HTML `acronym` element
61    tagAddress,    ## the HTML `address` element
62    tagApplet,     ## the deprecated HTML `applet` element
63    tagArea,       ## the HTML `area` element
64    tagArticle,    ## the HTML `article` element
65    tagAside,      ## the HTML `aside` element
66    tagAudio,      ## the HTML `audio` element
67    tagB,          ## the HTML `b` element
68    tagBase,       ## the HTML `base` element
69    tagBdi,        ## the HTML `bdi` element
70    tagBdo,        ## the deprecated HTML `dbo` element
71    tagBasefont,   ## the deprecated HTML `basefont` element
72    tagBig,        ## the HTML `big` element
73    tagBlockquote, ## the HTML `blockquote` element
74    tagBody,       ## the HTML `body` element
75    tagBr,         ## the HTML `br` element
76    tagButton,     ## the HTML `button` element
77    tagCanvas,     ## the HTML `canvas` element
78    tagCaption,    ## the HTML `caption` element
79    tagCenter,     ## the deprecated HTML `center` element
80    tagCite,       ## the HTML `cite` element
81    tagCode,       ## the HTML `code` element
82    tagCol,        ## the HTML `col` element
83    tagColgroup,   ## the HTML `colgroup` element
84    tagCommand,    ## the HTML `command` element
85    tagDatalist,   ## the HTML `datalist` element
86    tagDd,         ## the HTML `dd` element
87    tagDel,        ## the HTML `del` element
88    tagDetails,    ## the HTML `details` element
89    tagDfn,        ## the HTML `dfn` element
90    tagDialog,     ## the HTML `dialog` element
91    tagDiv,        ## the HTML `div` element
92    tagDir,        ## the deprecated HTLM `dir` element
93    tagDl,         ## the HTML `dl` element
94    tagDt,         ## the HTML `dt` element
95    tagEm,         ## the HTML `em` element
96    tagEmbed,      ## the HTML `embed` element
97    tagFieldset,   ## the HTML `fieldset` element
98    tagFigcaption, ## the HTML `figcaption` element
99    tagFigure,     ## the HTML `figure` element
100    tagFont,       ## the deprecated HTML `font` element
101    tagFooter,     ## the HTML `footer` element
102    tagForm,       ## the HTML `form` element
103    tagFrame,      ## the HTML `frame` element
104    tagFrameset,   ## the deprecated HTML `frameset` element
105    tagH1,         ## the HTML `h1` element
106    tagH2,         ## the HTML `h2` element
107    tagH3,         ## the HTML `h3` element
108    tagH4,         ## the HTML `h4` element
109    tagH5,         ## the HTML `h5` element
110    tagH6,         ## the HTML `h6` element
111    tagHead,       ## the HTML `head` element
112    tagHeader,     ## the HTML `header` element
113    tagHgroup,     ## the HTML `hgroup` element
114    tagHtml,       ## the HTML `html` element
115    tagHr,         ## the HTML `hr` element
116    tagI,          ## the HTML `i` element
117    tagIframe,     ## the deprecated HTML `iframe` element
118    tagImg,        ## the HTML `img` element
119    tagInput,      ## the HTML `input` element
120    tagIns,        ## the HTML `ins` element
121    tagIsindex,    ## the deprecated HTML `isindex` element
122    tagKbd,        ## the HTML `kbd` element
123    tagKeygen,     ## the HTML `keygen` element
124    tagLabel,      ## the HTML `label` element
125    tagLegend,     ## the HTML `legend` element
126    tagLi,         ## the HTML `li` element
127    tagLink,       ## the HTML `link` element
128    tagMap,        ## the HTML `map` element
129    tagMark,       ## the HTML `mark` element
130    tagMenu,       ## the deprecated HTML `menu` element
131    tagMeta,       ## the HTML `meta` element
132    tagMeter,      ## the HTML `meter` element
133    tagNav,        ## the HTML `nav` element
134    tagNobr,       ## the deprecated HTML `nobr` element
135    tagNoframes,   ## the deprecated HTML `noframes` element
136    tagNoscript,   ## the HTML `noscript` element
137    tagObject,     ## the HTML `object` element
138    tagOl,         ## the HTML `ol` element
139    tagOptgroup,   ## the HTML `optgroup` element
140    tagOption,     ## the HTML `option` element
141    tagOutput,     ## the HTML `output` element
142    tagP,          ## the HTML `p` element
143    tagParam,      ## the HTML `param` element
144    tagPre,        ## the HTML `pre` element
145    tagProgress,   ## the HTML `progress` element
146    tagQ,          ## the HTML `q` element
147    tagRp,         ## the HTML `rp` element
148    tagRt,         ## the HTML `rt` element
149    tagRuby,       ## the HTML `ruby` element
150    tagS,          ## the deprecated HTML `s` element
151    tagSamp,       ## the HTML `samp` element
152    tagScript,     ## the HTML `script` element
153    tagSection,    ## the HTML `section` element
154    tagSelect,     ## the HTML `select` element
155    tagSmall,      ## the HTML `small` element
156    tagSource,     ## the HTML `source` element
157    tagSpan,       ## the HTML `span` element
158    tagStrike,     ## the deprecated HTML `strike` element
159    tagStrong,     ## the HTML `strong` element
160    tagStyle,      ## the HTML `style` element
161    tagSub,        ## the HTML `sub` element
162    tagSummary,    ## the HTML `summary` element
163    tagSup,        ## the HTML `sup` element
164    tagTable,      ## the HTML `table` element
165    tagTbody,      ## the HTML `tbody` element
166    tagTd,         ## the HTML `td` element
167    tagTextarea,   ## the HTML `textarea` element
168    tagTfoot,      ## the HTML `tfoot` element
169    tagTh,         ## the HTML `th` element
170    tagThead,      ## the HTML `thead` element
171    tagTime,       ## the HTML `time` element
172    tagTitle,      ## the HTML `title` element
173    tagTr,         ## the HTML `tr` element
174    tagTrack,      ## the HTML `track` element
175    tagTt,         ## the HTML `tt` element
176    tagU,          ## the deprecated HTML `u` element
177    tagUl,         ## the HTML `ul` element
178    tagVar,        ## the HTML `var` element
179    tagVideo,      ## the HTML `video` element
180    tagWbr         ## the HTML `wbr` element
181
182const
183  tagToStr* = [
184    "a", "abbr", "acronym", "address", "applet", "area", "article",
185    "aside", "audio",
186    "b", "base", "basefont", "bdi", "bdo", "big", "blockquote", "body",
187    "br", "button", "canvas", "caption", "center", "cite", "code",
188    "col", "colgroup", "command",
189    "datalist", "dd", "del", "details", "dfn", "dialog", "div",
190    "dir", "dl", "dt", "em", "embed", "fieldset",
191    "figcaption", "figure", "font", "footer",
192    "form", "frame", "frameset", "h1", "h2", "h3",
193    "h4", "h5", "h6", "head", "header", "hgroup", "html", "hr",
194    "i", "iframe", "img", "input", "ins", "isindex",
195    "kbd", "keygen", "label", "legend", "li", "link", "map", "mark",
196    "menu", "meta", "meter", "nav", "nobr", "noframes", "noscript",
197    "object", "ol",
198    "optgroup", "option", "output", "p", "param", "pre", "progress", "q",
199    "rp", "rt", "ruby", "s", "samp", "script", "section", "select", "small",
200    "source", "span", "strike", "strong", "style",
201    "sub", "summary", "sup", "table",
202    "tbody", "td", "textarea", "tfoot", "th", "thead", "time",
203    "title", "tr", "track", "tt", "u", "ul", "var", "video", "wbr"]
204  InlineTags* = {tagA, tagAbbr, tagAcronym, tagApplet, tagB, tagBasefont,
205    tagBdo, tagBig, tagBr, tagButton, tagCite, tagCode, tagDel, tagDfn,
206    tagEm, tagFont, tagI, tagImg, tagIns, tagInput, tagIframe, tagKbd,
207    tagLabel, tagMap, tagObject, tagQ, tagSamp, tagScript, tagSelect,
208    tagSmall, tagSpan, tagStrong, tagSub, tagSup, tagTextarea, tagTt,
209    tagVar, tagApplet, tagBasefont, tagFont, tagIframe, tagU, tagS,
210    tagStrike, tagWbr}
211  BlockTags* = {tagAddress, tagBlockquote, tagCenter, tagDel, tagDir, tagDiv,
212    tagDl, tagFieldset, tagForm, tagH1, tagH2, tagH3, tagH4,
213    tagH5, tagH6, tagHr, tagIns, tagIsindex, tagMenu, tagNoframes, tagNoscript,
214    tagOl, tagP, tagPre, tagTable, tagUl, tagCenter, tagDir, tagIsindex,
215    tagMenu, tagNoframes}
216  SingleTags* = {tagArea, tagBase, tagBasefont,
217    tagBr, tagCol, tagFrame, tagHr, tagImg, tagIsindex,
218    tagLink, tagMeta, tagParam, tagWbr, tagSource}
219
220proc allLower(s: string): bool =
221  for c in s:
222    if c < 'a' or c > 'z': return false
223  return true
224
225proc toHtmlTag(s: string): HtmlTag =
226  case s
227  of "a": tagA
228  of "abbr": tagAbbr
229  of "acronym": tagAcronym
230  of "address": tagAddress
231  of "applet": tagApplet
232  of "area": tagArea
233  of "article": tagArticle
234  of "aside": tagAside
235  of "audio": tagAudio
236  of "b": tagB
237  of "base": tagBase
238  of "basefont": tagBasefont
239  of "bdi": tagBdi
240  of "bdo": tagBdo
241  of "big": tagBig
242  of "blockquote": tagBlockquote
243  of "body": tagBody
244  of "br": tagBr
245  of "button": tagButton
246  of "canvas": tagCanvas
247  of "caption": tagCaption
248  of "center": tagCenter
249  of "cite": tagCite
250  of "code": tagCode
251  of "col": tagCol
252  of "colgroup": tagColgroup
253  of "command": tagCommand
254  of "datalist": tagDatalist
255  of "dd": tagDd
256  of "del": tagDel
257  of "details": tagDetails
258  of "dfn": tagDfn
259  of "dialog": tagDialog
260  of "div": tagDiv
261  of "dir": tagDir
262  of "dl": tagDl
263  of "dt": tagDt
264  of "em": tagEm
265  of "embed": tagEmbed
266  of "fieldset": tagFieldset
267  of "figcaption": tagFigcaption
268  of "figure": tagFigure
269  of "font": tagFont
270  of "footer": tagFooter
271  of "form": tagForm
272  of "frame": tagFrame
273  of "frameset": tagFrameset
274  of "h1": tagH1
275  of "h2": tagH2
276  of "h3": tagH3
277  of "h4": tagH4
278  of "h5": tagH5
279  of "h6": tagH6
280  of "head": tagHead
281  of "header": tagHeader
282  of "hgroup": tagHgroup
283  of "html": tagHtml
284  of "hr": tagHr
285  of "i": tagI
286  of "iframe": tagIframe
287  of "img": tagImg
288  of "input": tagInput
289  of "ins": tagIns
290  of "isindex": tagIsindex
291  of "kbd": tagKbd
292  of "keygen": tagKeygen
293  of "label": tagLabel
294  of "legend": tagLegend
295  of "li": tagLi
296  of "link": tagLink
297  of "map": tagMap
298  of "mark": tagMark
299  of "menu": tagMenu
300  of "meta": tagMeta
301  of "meter": tagMeter
302  of "nav": tagNav
303  of "nobr": tagNobr
304  of "noframes": tagNoframes
305  of "noscript": tagNoscript
306  of "object": tagObject
307  of "ol": tagOl
308  of "optgroup": tagOptgroup
309  of "option": tagOption
310  of "output": tagOutput
311  of "p": tagP
312  of "param": tagParam
313  of "pre": tagPre
314  of "progress": tagProgress
315  of "q": tagQ
316  of "rp": tagRp
317  of "rt": tagRt
318  of "ruby": tagRuby
319  of "s": tagS
320  of "samp": tagSamp
321  of "script": tagScript
322  of "section": tagSection
323  of "select": tagSelect
324  of "small": tagSmall
325  of "source": tagSource
326  of "span": tagSpan
327  of "strike": tagStrike
328  of "strong": tagStrong
329  of "style": tagStyle
330  of "sub": tagSub
331  of "summary": tagSummary
332  of "sup": tagSup
333  of "table": tagTable
334  of "tbody": tagTbody
335  of "td": tagTd
336  of "textarea": tagTextarea
337  of "tfoot": tagTfoot
338  of "th": tagTh
339  of "thead": tagThead
340  of "time": tagTime
341  of "title": tagTitle
342  of "tr": tagTr
343  of "track": tagTrack
344  of "tt": tagTt
345  of "u": tagU
346  of "ul": tagUl
347  of "var": tagVar
348  of "video": tagVideo
349  of "wbr": tagWbr
350  else: tagUnknown
351
352
353proc htmlTag*(n: XmlNode): HtmlTag =
354  ## Gets `n`'s tag as a `HtmlTag`.
355  if n.clientData == 0:
356    n.clientData = toHtmlTag(n.tag).ord
357  result = HtmlTag(n.clientData)
358
359proc htmlTag*(s: string): HtmlTag =
360  ## Converts `s` to a `HtmlTag`. If `s` is no HTML tag, `tagUnknown` is
361  ## returned.
362  let s = if allLower(s): s else: toLowerAscii(s)
363  result = toHtmlTag(s)
364
365proc runeToEntity*(rune: Rune): string =
366  ## converts a Rune to its numeric HTML entity equivalent.
367  runnableExamples:
368    import std/unicode
369    doAssert runeToEntity(Rune(0)) == ""
370    doAssert runeToEntity(Rune(-1)) == ""
371    doAssert runeToEntity("Ü".runeAt(0)) == "#220"
372    doAssert runeToEntity("∈".runeAt(0)) == "#8712"
373  if rune.ord <= 0: result = ""
374  else: result = '#' & $rune.ord
375
376proc entityToRune*(entity: string): Rune =
377  ## Converts an HTML entity name like `&Uuml;` or values like `&#220;`
378  ## or `&#x000DC;` to its UTF-8 equivalent.
379  ## Rune(0) is returned if the entity name is unknown.
380  runnableExamples:
381    import std/unicode
382    doAssert entityToRune("") == Rune(0)
383    doAssert entityToRune("a") == Rune(0)
384    doAssert entityToRune("gt") == ">".runeAt(0)
385    doAssert entityToRune("Uuml") == "Ü".runeAt(0)
386    doAssert entityToRune("quest") == "?".runeAt(0)
387    doAssert entityToRune("#x0003F") == "?".runeAt(0)
388  if entity.len < 2: return # smallest entity has length 2
389  if entity[0] == '#':
390    var runeValue = 0
391    case entity[1]
392    of '0'..'9':
393      try: runeValue = parseInt(entity[1..^1])
394      except: discard
395    of 'x', 'X': # not case sensitive here
396      try: runeValue = parseHexInt(entity[2..^1])
397      except: discard
398    else: discard # other entities are not defined with prefix `#`
399    if runeValue notin 0..0x10FFFF: runeValue = 0 # only return legal values
400    return Rune(runeValue)
401  case entity # entity names are case sensitive
402  of "Tab": Rune(0x00009)
403  of "NewLine": Rune(0x0000A)
404  of "excl": Rune(0x00021)
405  of "quot", "QUOT": Rune(0x00022)
406  of "num": Rune(0x00023)
407  of "dollar": Rune(0x00024)
408  of "percnt": Rune(0x00025)
409  of "amp", "AMP": Rune(0x00026)
410  of "apos": Rune(0x00027)
411  of "lpar": Rune(0x00028)
412  of "rpar": Rune(0x00029)
413  of "ast", "midast": Rune(0x0002A)
414  of "plus": Rune(0x0002B)
415  of "comma": Rune(0x0002C)
416  of "period": Rune(0x0002E)
417  of "sol": Rune(0x0002F)
418  of "colon": Rune(0x0003A)
419  of "semi": Rune(0x0003B)
420  of "lt", "LT": Rune(0x0003C)
421  of "equals": Rune(0x0003D)
422  of "gt", "GT": Rune(0x0003E)
423  of "quest": Rune(0x0003F)
424  of "commat": Rune(0x00040)
425  of "lsqb", "lbrack": Rune(0x0005B)
426  of "bsol": Rune(0x0005C)
427  of "rsqb", "rbrack": Rune(0x0005D)
428  of "Hat": Rune(0x0005E)
429  of "lowbar": Rune(0x0005F)
430  of "grave", "DiacriticalGrave": Rune(0x00060)
431  of "lcub", "lbrace": Rune(0x0007B)
432  of "verbar", "vert", "VerticalLine": Rune(0x0007C)
433  of "rcub", "rbrace": Rune(0x0007D)
434  of "nbsp", "NonBreakingSpace": Rune(0x000A0)
435  of "iexcl": Rune(0x000A1)
436  of "cent": Rune(0x000A2)
437  of "pound": Rune(0x000A3)
438  of "curren": Rune(0x000A4)
439  of "yen": Rune(0x000A5)
440  of "brvbar": Rune(0x000A6)
441  of "sect": Rune(0x000A7)
442  of "Dot", "die", "DoubleDot", "uml": Rune(0x000A8)
443  of "copy", "COPY": Rune(0x000A9)
444  of "ordf": Rune(0x000AA)
445  of "laquo": Rune(0x000AB)
446  of "not": Rune(0x000AC)
447  of "shy": Rune(0x000AD)
448  of "reg", "circledR", "REG": Rune(0x000AE)
449  of "macr", "OverBar", "strns": Rune(0x000AF)
450  of "deg": Rune(0x000B0)
451  of "plusmn", "pm", "PlusMinus": Rune(0x000B1)
452  of "sup2": Rune(0x000B2)
453  of "sup3": Rune(0x000B3)
454  of "acute", "DiacriticalAcute": Rune(0x000B4)
455  of "micro": Rune(0x000B5)
456  of "para": Rune(0x000B6)
457  of "middot", "centerdot", "CenterDot": Rune(0x000B7)
458  of "cedil", "Cedilla": Rune(0x000B8)
459  of "sup1": Rune(0x000B9)
460  of "ordm": Rune(0x000BA)
461  of "raquo": Rune(0x000BB)
462  of "frac14": Rune(0x000BC)
463  of "frac12", "half": Rune(0x000BD)
464  of "frac34": Rune(0x000BE)
465  of "iquest": Rune(0x000BF)
466  of "Agrave": Rune(0x000C0)
467  of "Aacute": Rune(0x000C1)
468  of "Acirc": Rune(0x000C2)
469  of "Atilde": Rune(0x000C3)
470  of "Auml": Rune(0x000C4)
471  of "Aring": Rune(0x000C5)
472  of "AElig": Rune(0x000C6)
473  of "Ccedil": Rune(0x000C7)
474  of "Egrave": Rune(0x000C8)
475  of "Eacute": Rune(0x000C9)
476  of "Ecirc": Rune(0x000CA)
477  of "Euml": Rune(0x000CB)
478  of "Igrave": Rune(0x000CC)
479  of "Iacute": Rune(0x000CD)
480  of "Icirc": Rune(0x000CE)
481  of "Iuml": Rune(0x000CF)
482  of "ETH": Rune(0x000D0)
483  of "Ntilde": Rune(0x000D1)
484  of "Ograve": Rune(0x000D2)
485  of "Oacute": Rune(0x000D3)
486  of "Ocirc": Rune(0x000D4)
487  of "Otilde": Rune(0x000D5)
488  of "Ouml": Rune(0x000D6)
489  of "times": Rune(0x000D7)
490  of "Oslash": Rune(0x000D8)
491  of "Ugrave": Rune(0x000D9)
492  of "Uacute": Rune(0x000DA)
493  of "Ucirc": Rune(0x000DB)
494  of "Uuml": Rune(0x000DC)
495  of "Yacute": Rune(0x000DD)
496  of "THORN": Rune(0x000DE)
497  of "szlig": Rune(0x000DF)
498  of "agrave": Rune(0x000E0)
499  of "aacute": Rune(0x000E1)
500  of "acirc": Rune(0x000E2)
501  of "atilde": Rune(0x000E3)
502  of "auml": Rune(0x000E4)
503  of "aring": Rune(0x000E5)
504  of "aelig": Rune(0x000E6)
505  of "ccedil": Rune(0x000E7)
506  of "egrave": Rune(0x000E8)
507  of "eacute": Rune(0x000E9)
508  of "ecirc": Rune(0x000EA)
509  of "euml": Rune(0x000EB)
510  of "igrave": Rune(0x000EC)
511  of "iacute": Rune(0x000ED)
512  of "icirc": Rune(0x000EE)
513  of "iuml": Rune(0x000EF)
514  of "eth": Rune(0x000F0)
515  of "ntilde": Rune(0x000F1)
516  of "ograve": Rune(0x000F2)
517  of "oacute": Rune(0x000F3)
518  of "ocirc": Rune(0x000F4)
519  of "otilde": Rune(0x000F5)
520  of "ouml": Rune(0x000F6)
521  of "divide", "div": Rune(0x000F7)
522  of "oslash": Rune(0x000F8)
523  of "ugrave": Rune(0x000F9)
524  of "uacute": Rune(0x000FA)
525  of "ucirc": Rune(0x000FB)
526  of "uuml": Rune(0x000FC)
527  of "yacute": Rune(0x000FD)
528  of "thorn": Rune(0x000FE)
529  of "yuml": Rune(0x000FF)
530  of "Amacr": Rune(0x00100)
531  of "amacr": Rune(0x00101)
532  of "Abreve": Rune(0x00102)
533  of "abreve": Rune(0x00103)
534  of "Aogon": Rune(0x00104)
535  of "aogon": Rune(0x00105)
536  of "Cacute": Rune(0x00106)
537  of "cacute": Rune(0x00107)
538  of "Ccirc": Rune(0x00108)
539  of "ccirc": Rune(0x00109)
540  of "Cdot": Rune(0x0010A)
541  of "cdot": Rune(0x0010B)
542  of "Ccaron": Rune(0x0010C)
543  of "ccaron": Rune(0x0010D)
544  of "Dcaron": Rune(0x0010E)
545  of "dcaron": Rune(0x0010F)
546  of "Dstrok": Rune(0x00110)
547  of "dstrok": Rune(0x00111)
548  of "Emacr": Rune(0x00112)
549  of "emacr": Rune(0x00113)
550  of "Edot": Rune(0x00116)
551  of "edot": Rune(0x00117)
552  of "Eogon": Rune(0x00118)
553  of "eogon": Rune(0x00119)
554  of "Ecaron": Rune(0x0011A)
555  of "ecaron": Rune(0x0011B)
556  of "Gcirc": Rune(0x0011C)
557  of "gcirc": Rune(0x0011D)
558  of "Gbreve": Rune(0x0011E)
559  of "gbreve": Rune(0x0011F)
560  of "Gdot": Rune(0x00120)
561  of "gdot": Rune(0x00121)
562  of "Gcedil": Rune(0x00122)
563  of "Hcirc": Rune(0x00124)
564  of "hcirc": Rune(0x00125)
565  of "Hstrok": Rune(0x00126)
566  of "hstrok": Rune(0x00127)
567  of "Itilde": Rune(0x00128)
568  of "itilde": Rune(0x00129)
569  of "Imacr": Rune(0x0012A)
570  of "imacr": Rune(0x0012B)
571  of "Iogon": Rune(0x0012E)
572  of "iogon": Rune(0x0012F)
573  of "Idot": Rune(0x00130)
574  of "imath", "inodot": Rune(0x00131)
575  of "IJlig": Rune(0x00132)
576  of "ijlig": Rune(0x00133)
577  of "Jcirc": Rune(0x00134)
578  of "jcirc": Rune(0x00135)
579  of "Kcedil": Rune(0x00136)
580  of "kcedil": Rune(0x00137)
581  of "kgreen": Rune(0x00138)
582  of "Lacute": Rune(0x00139)
583  of "lacute": Rune(0x0013A)
584  of "Lcedil": Rune(0x0013B)
585  of "lcedil": Rune(0x0013C)
586  of "Lcaron": Rune(0x0013D)
587  of "lcaron": Rune(0x0013E)
588  of "Lmidot": Rune(0x0013F)
589  of "lmidot": Rune(0x00140)
590  of "Lstrok": Rune(0x00141)
591  of "lstrok": Rune(0x00142)
592  of "Nacute": Rune(0x00143)
593  of "nacute": Rune(0x00144)
594  of "Ncedil": Rune(0x00145)
595  of "ncedil": Rune(0x00146)
596  of "Ncaron": Rune(0x00147)
597  of "ncaron": Rune(0x00148)
598  of "napos": Rune(0x00149)
599  of "ENG": Rune(0x0014A)
600  of "eng": Rune(0x0014B)
601  of "Omacr": Rune(0x0014C)
602  of "omacr": Rune(0x0014D)
603  of "Odblac": Rune(0x00150)
604  of "odblac": Rune(0x00151)
605  of "OElig": Rune(0x00152)
606  of "oelig": Rune(0x00153)
607  of "Racute": Rune(0x00154)
608  of "racute": Rune(0x00155)
609  of "Rcedil": Rune(0x00156)
610  of "rcedil": Rune(0x00157)
611  of "Rcaron": Rune(0x00158)
612  of "rcaron": Rune(0x00159)
613  of "Sacute": Rune(0x0015A)
614  of "sacute": Rune(0x0015B)
615  of "Scirc": Rune(0x0015C)
616  of "scirc": Rune(0x0015D)
617  of "Scedil": Rune(0x0015E)
618  of "scedil": Rune(0x0015F)
619  of "Scaron": Rune(0x00160)
620  of "scaron": Rune(0x00161)
621  of "Tcedil": Rune(0x00162)
622  of "tcedil": Rune(0x00163)
623  of "Tcaron": Rune(0x00164)
624  of "tcaron": Rune(0x00165)
625  of "Tstrok": Rune(0x00166)
626  of "tstrok": Rune(0x00167)
627  of "Utilde": Rune(0x00168)
628  of "utilde": Rune(0x00169)
629  of "Umacr": Rune(0x0016A)
630  of "umacr": Rune(0x0016B)
631  of "Ubreve": Rune(0x0016C)
632  of "ubreve": Rune(0x0016D)
633  of "Uring": Rune(0x0016E)
634  of "uring": Rune(0x0016F)
635  of "Udblac": Rune(0x00170)
636  of "udblac": Rune(0x00171)
637  of "Uogon": Rune(0x00172)
638  of "uogon": Rune(0x00173)
639  of "Wcirc": Rune(0x00174)
640  of "wcirc": Rune(0x00175)
641  of "Ycirc": Rune(0x00176)
642  of "ycirc": Rune(0x00177)
643  of "Yuml": Rune(0x00178)
644  of "Zacute": Rune(0x00179)
645  of "zacute": Rune(0x0017A)
646  of "Zdot": Rune(0x0017B)
647  of "zdot": Rune(0x0017C)
648  of "Zcaron": Rune(0x0017D)
649  of "zcaron": Rune(0x0017E)
650  of "fnof": Rune(0x00192)
651  of "imped": Rune(0x001B5)
652  of "gacute": Rune(0x001F5)
653  of "jmath": Rune(0x00237)
654  of "circ": Rune(0x002C6)
655  of "caron", "Hacek": Rune(0x002C7)
656  of "breve", "Breve": Rune(0x002D8)
657  of "dot", "DiacriticalDot": Rune(0x002D9)
658  of "ring": Rune(0x002DA)
659  of "ogon": Rune(0x002DB)
660  of "tilde", "DiacriticalTilde": Rune(0x002DC)
661  of "dblac", "DiacriticalDoubleAcute": Rune(0x002DD)
662  of "DownBreve": Rune(0x00311)
663  of "UnderBar": Rune(0x00332)
664  of "Alpha": Rune(0x00391)
665  of "Beta": Rune(0x00392)
666  of "Gamma": Rune(0x00393)
667  of "Delta": Rune(0x00394)
668  of "Epsilon": Rune(0x00395)
669  of "Zeta": Rune(0x00396)
670  of "Eta": Rune(0x00397)
671  of "Theta": Rune(0x00398)
672  of "Iota": Rune(0x00399)
673  of "Kappa": Rune(0x0039A)
674  of "Lambda": Rune(0x0039B)
675  of "Mu": Rune(0x0039C)
676  of "Nu": Rune(0x0039D)
677  of "Xi": Rune(0x0039E)
678  of "Omicron": Rune(0x0039F)
679  of "Pi": Rune(0x003A0)
680  of "Rho": Rune(0x003A1)
681  of "Sigma": Rune(0x003A3)
682  of "Tau": Rune(0x003A4)
683  of "Upsilon": Rune(0x003A5)
684  of "Phi": Rune(0x003A6)
685  of "Chi": Rune(0x003A7)
686  of "Psi": Rune(0x003A8)
687  of "Omega": Rune(0x003A9)
688  of "alpha": Rune(0x003B1)
689  of "beta": Rune(0x003B2)
690  of "gamma": Rune(0x003B3)
691  of "delta": Rune(0x003B4)
692  of "epsiv", "varepsilon", "epsilon": Rune(0x003B5)
693  of "zeta": Rune(0x003B6)
694  of "eta": Rune(0x003B7)
695  of "theta": Rune(0x003B8)
696  of "iota": Rune(0x003B9)
697  of "kappa": Rune(0x003BA)
698  of "lambda": Rune(0x003BB)
699  of "mu": Rune(0x003BC)
700  of "nu": Rune(0x003BD)
701  of "xi": Rune(0x003BE)
702  of "omicron": Rune(0x003BF)
703  of "pi": Rune(0x003C0)
704  of "rho": Rune(0x003C1)
705  of "sigmav", "varsigma", "sigmaf": Rune(0x003C2)
706  of "sigma": Rune(0x003C3)
707  of "tau": Rune(0x003C4)
708  of "upsi", "upsilon": Rune(0x003C5)
709  of "phi", "phiv", "varphi": Rune(0x003C6)
710  of "chi": Rune(0x003C7)
711  of "psi": Rune(0x003C8)
712  of "omega": Rune(0x003C9)
713  of "thetav", "vartheta", "thetasym": Rune(0x003D1)
714  of "Upsi", "upsih": Rune(0x003D2)
715  of "straightphi": Rune(0x003D5)
716  of "piv", "varpi": Rune(0x003D6)
717  of "Gammad": Rune(0x003DC)
718  of "gammad", "digamma": Rune(0x003DD)
719  of "kappav", "varkappa": Rune(0x003F0)
720  of "rhov", "varrho": Rune(0x003F1)
721  of "epsi", "straightepsilon": Rune(0x003F5)
722  of "bepsi", "backepsilon": Rune(0x003F6)
723  of "IOcy": Rune(0x00401)
724  of "DJcy": Rune(0x00402)
725  of "GJcy": Rune(0x00403)
726  of "Jukcy": Rune(0x00404)
727  of "DScy": Rune(0x00405)
728  of "Iukcy": Rune(0x00406)
729  of "YIcy": Rune(0x00407)
730  of "Jsercy": Rune(0x00408)
731  of "LJcy": Rune(0x00409)
732  of "NJcy": Rune(0x0040A)
733  of "TSHcy": Rune(0x0040B)
734  of "KJcy": Rune(0x0040C)
735  of "Ubrcy": Rune(0x0040E)
736  of "DZcy": Rune(0x0040F)
737  of "Acy": Rune(0x00410)
738  of "Bcy": Rune(0x00411)
739  of "Vcy": Rune(0x00412)
740  of "Gcy": Rune(0x00413)
741  of "Dcy": Rune(0x00414)
742  of "IEcy": Rune(0x00415)
743  of "ZHcy": Rune(0x00416)
744  of "Zcy": Rune(0x00417)
745  of "Icy": Rune(0x00418)
746  of "Jcy": Rune(0x00419)
747  of "Kcy": Rune(0x0041A)
748  of "Lcy": Rune(0x0041B)
749  of "Mcy": Rune(0x0041C)
750  of "Ncy": Rune(0x0041D)
751  of "Ocy": Rune(0x0041E)
752  of "Pcy": Rune(0x0041F)
753  of "Rcy": Rune(0x00420)
754  of "Scy": Rune(0x00421)
755  of "Tcy": Rune(0x00422)
756  of "Ucy": Rune(0x00423)
757  of "Fcy": Rune(0x00424)
758  of "KHcy": Rune(0x00425)
759  of "TScy": Rune(0x00426)
760  of "CHcy": Rune(0x00427)
761  of "SHcy": Rune(0x00428)
762  of "SHCHcy": Rune(0x00429)
763  of "HARDcy": Rune(0x0042A)
764  of "Ycy": Rune(0x0042B)
765  of "SOFTcy": Rune(0x0042C)
766  of "Ecy": Rune(0x0042D)
767  of "YUcy": Rune(0x0042E)
768  of "YAcy": Rune(0x0042F)
769  of "acy": Rune(0x00430)
770  of "bcy": Rune(0x00431)
771  of "vcy": Rune(0x00432)
772  of "gcy": Rune(0x00433)
773  of "dcy": Rune(0x00434)
774  of "iecy": Rune(0x00435)
775  of "zhcy": Rune(0x00436)
776  of "zcy": Rune(0x00437)
777  of "icy": Rune(0x00438)
778  of "jcy": Rune(0x00439)
779  of "kcy": Rune(0x0043A)
780  of "lcy": Rune(0x0043B)
781  of "mcy": Rune(0x0043C)
782  of "ncy": Rune(0x0043D)
783  of "ocy": Rune(0x0043E)
784  of "pcy": Rune(0x0043F)
785  of "rcy": Rune(0x00440)
786  of "scy": Rune(0x00441)
787  of "tcy": Rune(0x00442)
788  of "ucy": Rune(0x00443)
789  of "fcy": Rune(0x00444)
790  of "khcy": Rune(0x00445)
791  of "tscy": Rune(0x00446)
792  of "chcy": Rune(0x00447)
793  of "shcy": Rune(0x00448)
794  of "shchcy": Rune(0x00449)
795  of "hardcy": Rune(0x0044A)
796  of "ycy": Rune(0x0044B)
797  of "softcy": Rune(0x0044C)
798  of "ecy": Rune(0x0044D)
799  of "yucy": Rune(0x0044E)
800  of "yacy": Rune(0x0044F)
801  of "iocy": Rune(0x00451)
802  of "djcy": Rune(0x00452)
803  of "gjcy": Rune(0x00453)
804  of "jukcy": Rune(0x00454)
805  of "dscy": Rune(0x00455)
806  of "iukcy": Rune(0x00456)
807  of "yicy": Rune(0x00457)
808  of "jsercy": Rune(0x00458)
809  of "ljcy": Rune(0x00459)
810  of "njcy": Rune(0x0045A)
811  of "tshcy": Rune(0x0045B)
812  of "kjcy": Rune(0x0045C)
813  of "ubrcy": Rune(0x0045E)
814  of "dzcy": Rune(0x0045F)
815  of "ensp": Rune(0x02002)
816  of "emsp": Rune(0x02003)
817  of "emsp13": Rune(0x02004)
818  of "emsp14": Rune(0x02005)
819  of "numsp": Rune(0x02007)
820  of "puncsp": Rune(0x02008)
821  of "thinsp", "ThinSpace": Rune(0x02009)
822  of "hairsp", "VeryThinSpace": Rune(0x0200A)
823  of "ZeroWidthSpace", "NegativeVeryThinSpace", "NegativeThinSpace",
824    "NegativeMediumSpace", "NegativeThickSpace": Rune(0x0200B)
825  of "zwnj": Rune(0x0200C)
826  of "zwj": Rune(0x0200D)
827  of "lrm": Rune(0x0200E)
828  of "rlm": Rune(0x0200F)
829  of "hyphen", "dash": Rune(0x02010)
830  of "ndash": Rune(0x02013)
831  of "mdash": Rune(0x02014)
832  of "horbar": Rune(0x02015)
833  of "Verbar", "Vert": Rune(0x02016)
834  of "lsquo", "OpenCurlyQuote": Rune(0x02018)
835  of "rsquo", "rsquor", "CloseCurlyQuote": Rune(0x02019)
836  of "lsquor", "sbquo": Rune(0x0201A)
837  of "ldquo", "OpenCurlyDoubleQuote": Rune(0x0201C)
838  of "rdquo", "rdquor", "CloseCurlyDoubleQuote": Rune(0x0201D)
839  of "ldquor", "bdquo": Rune(0x0201E)
840  of "dagger": Rune(0x02020)
841  of "Dagger", "ddagger": Rune(0x02021)
842  of "bull", "bullet": Rune(0x02022)
843  of "nldr": Rune(0x02025)
844  of "hellip", "mldr": Rune(0x02026)
845  of "permil": Rune(0x02030)
846  of "pertenk": Rune(0x02031)
847  of "prime": Rune(0x02032)
848  of "Prime": Rune(0x02033)
849  of "tprime": Rune(0x02034)
850  of "bprime", "backprime": Rune(0x02035)
851  of "lsaquo": Rune(0x02039)
852  of "rsaquo": Rune(0x0203A)
853  of "oline": Rune(0x0203E)
854  of "caret": Rune(0x02041)
855  of "hybull": Rune(0x02043)
856  of "frasl": Rune(0x02044)
857  of "bsemi": Rune(0x0204F)
858  of "qprime": Rune(0x02057)
859  of "MediumSpace": Rune(0x0205F)
860  of "NoBreak": Rune(0x02060)
861  of "ApplyFunction", "af": Rune(0x02061)
862  of "InvisibleTimes", "it": Rune(0x02062)
863  of "InvisibleComma", "ic": Rune(0x02063)
864  of "euro": Rune(0x020AC)
865  of "tdot", "TripleDot": Rune(0x020DB)
866  of "DotDot": Rune(0x020DC)
867  of "Copf", "complexes": Rune(0x02102)
868  of "incare": Rune(0x02105)
869  of "gscr": Rune(0x0210A)
870  of "hamilt", "HilbertSpace", "Hscr": Rune(0x0210B)
871  of "Hfr", "Poincareplane": Rune(0x0210C)
872  of "quaternions", "Hopf": Rune(0x0210D)
873  of "planckh": Rune(0x0210E)
874  of "planck", "hbar", "plankv", "hslash": Rune(0x0210F)
875  of "Iscr", "imagline": Rune(0x02110)
876  of "image", "Im", "imagpart", "Ifr": Rune(0x02111)
877  of "Lscr", "lagran", "Laplacetrf": Rune(0x02112)
878  of "ell": Rune(0x02113)
879  of "Nopf", "naturals": Rune(0x02115)
880  of "numero": Rune(0x02116)
881  of "copysr": Rune(0x02117)
882  of "weierp", "wp": Rune(0x02118)
883  of "Popf", "primes": Rune(0x02119)
884  of "rationals", "Qopf": Rune(0x0211A)
885  of "Rscr", "realine": Rune(0x0211B)
886  of "real", "Re", "realpart", "Rfr": Rune(0x0211C)
887  of "reals", "Ropf": Rune(0x0211D)
888  of "rx": Rune(0x0211E)
889  of "trade", "TRADE": Rune(0x02122)
890  of "integers", "Zopf": Rune(0x02124)
891  of "ohm": Rune(0x02126)
892  of "mho": Rune(0x02127)
893  of "Zfr", "zeetrf": Rune(0x02128)
894  of "iiota": Rune(0x02129)
895  of "angst": Rune(0x0212B)
896  of "bernou", "Bernoullis", "Bscr": Rune(0x0212C)
897  of "Cfr", "Cayleys": Rune(0x0212D)
898  of "escr": Rune(0x0212F)
899  of "Escr", "expectation": Rune(0x02130)
900  of "Fscr", "Fouriertrf": Rune(0x02131)
901  of "phmmat", "Mellintrf", "Mscr": Rune(0x02133)
902  of "order", "orderof", "oscr": Rune(0x02134)
903  of "alefsym", "aleph": Rune(0x02135)
904  of "beth": Rune(0x02136)
905  of "gimel": Rune(0x02137)
906  of "daleth": Rune(0x02138)
907  of "CapitalDifferentialD", "DD": Rune(0x02145)
908  of "DifferentialD", "dd": Rune(0x02146)
909  of "ExponentialE", "exponentiale", "ee": Rune(0x02147)
910  of "ImaginaryI", "ii": Rune(0x02148)
911  of "frac13": Rune(0x02153)
912  of "frac23": Rune(0x02154)
913  of "frac15": Rune(0x02155)
914  of "frac25": Rune(0x02156)
915  of "frac35": Rune(0x02157)
916  of "frac45": Rune(0x02158)
917  of "frac16": Rune(0x02159)
918  of "frac56": Rune(0x0215A)
919  of "frac18": Rune(0x0215B)
920  of "frac38": Rune(0x0215C)
921  of "frac58": Rune(0x0215D)
922  of "frac78": Rune(0x0215E)
923  of "larr", "leftarrow", "LeftArrow", "slarr",
924    "ShortLeftArrow": Rune(0x02190)
925  of "uarr", "uparrow", "UpArrow", "ShortUpArrow": Rune(0x02191)
926  of "rarr", "rightarrow", "RightArrow", "srarr",
927    "ShortRightArrow": Rune(0x02192)
928  of "darr", "downarrow", "DownArrow",
929    "ShortDownArrow": Rune(0x02193)
930  of "harr", "leftrightarrow", "LeftRightArrow": Rune(0x02194)
931  of "varr", "updownarrow", "UpDownArrow": Rune(0x02195)
932  of "nwarr", "UpperLeftArrow", "nwarrow": Rune(0x02196)
933  of "nearr", "UpperRightArrow", "nearrow": Rune(0x02197)
934  of "searr", "searrow", "LowerRightArrow": Rune(0x02198)
935  of "swarr", "swarrow", "LowerLeftArrow": Rune(0x02199)
936  of "nlarr", "nleftarrow": Rune(0x0219A)
937  of "nrarr", "nrightarrow": Rune(0x0219B)
938  of "rarrw", "rightsquigarrow": Rune(0x0219D)
939  of "Larr", "twoheadleftarrow": Rune(0x0219E)
940  of "Uarr": Rune(0x0219F)
941  of "Rarr", "twoheadrightarrow": Rune(0x021A0)
942  of "Darr": Rune(0x021A1)
943  of "larrtl", "leftarrowtail": Rune(0x021A2)
944  of "rarrtl", "rightarrowtail": Rune(0x021A3)
945  of "LeftTeeArrow", "mapstoleft": Rune(0x021A4)
946  of "UpTeeArrow", "mapstoup": Rune(0x021A5)
947  of "map", "RightTeeArrow", "mapsto": Rune(0x021A6)
948  of "DownTeeArrow", "mapstodown": Rune(0x021A7)
949  of "larrhk", "hookleftarrow": Rune(0x021A9)
950  of "rarrhk", "hookrightarrow": Rune(0x021AA)
951  of "larrlp", "looparrowleft": Rune(0x021AB)
952  of "rarrlp", "looparrowright": Rune(0x021AC)
953  of "harrw", "leftrightsquigarrow": Rune(0x021AD)
954  of "nharr", "nleftrightarrow": Rune(0x021AE)
955  of "lsh", "Lsh": Rune(0x021B0)
956  of "rsh", "Rsh": Rune(0x021B1)
957  of "ldsh": Rune(0x021B2)
958  of "rdsh": Rune(0x021B3)
959  of "crarr": Rune(0x021B5)
960  of "cularr", "curvearrowleft": Rune(0x021B6)
961  of "curarr", "curvearrowright": Rune(0x021B7)
962  of "olarr", "circlearrowleft": Rune(0x021BA)
963  of "orarr", "circlearrowright": Rune(0x021BB)
964  of "lharu", "LeftVector", "leftharpoonup": Rune(0x021BC)
965  of "lhard", "leftharpoondown", "DownLeftVector": Rune(0x021BD)
966  of "uharr", "upharpoonright", "RightUpVector": Rune(0x021BE)
967  of "uharl", "upharpoonleft", "LeftUpVector": Rune(0x021BF)
968  of "rharu", "RightVector", "rightharpoonup": Rune(0x021C0)
969  of "rhard", "rightharpoondown", "DownRightVector": Rune(0x021C1)
970  of "dharr", "RightDownVector", "downharpoonright": Rune(0x021C2)
971  of "dharl", "LeftDownVector", "downharpoonleft": Rune(0x021C3)
972  of "rlarr", "rightleftarrows", "RightArrowLeftArrow": Rune(0x021C4)
973  of "udarr", "UpArrowDownArrow": Rune(0x021C5)
974  of "lrarr", "leftrightarrows", "LeftArrowRightArrow": Rune(0x021C6)
975  of "llarr", "leftleftarrows": Rune(0x021C7)
976  of "uuarr", "upuparrows": Rune(0x021C8)
977  of "rrarr", "rightrightarrows": Rune(0x021C9)
978  of "ddarr", "downdownarrows": Rune(0x021CA)
979  of "lrhar", "ReverseEquilibrium",
980    "leftrightharpoons": Rune(0x021CB)
981  of "rlhar", "rightleftharpoons", "Equilibrium": Rune(0x021CC)
982  of "nlArr", "nLeftarrow": Rune(0x021CD)
983  of "nhArr", "nLeftrightarrow": Rune(0x021CE)
984  of "nrArr", "nRightarrow": Rune(0x021CF)
985  of "lArr", "Leftarrow", "DoubleLeftArrow": Rune(0x021D0)
986  of "uArr", "Uparrow", "DoubleUpArrow": Rune(0x021D1)
987  of "rArr", "Rightarrow", "Implies",
988    "DoubleRightArrow": Rune(0x021D2)
989  of "dArr", "Downarrow", "DoubleDownArrow": Rune(0x021D3)
990  of "hArr", "Leftrightarrow", "DoubleLeftRightArrow",
991    "iff": Rune(0x021D4)
992  of "vArr", "Updownarrow", "DoubleUpDownArrow": Rune(0x021D5)
993  of "nwArr": Rune(0x021D6)
994  of "neArr": Rune(0x021D7)
995  of "seArr": Rune(0x021D8)
996  of "swArr": Rune(0x021D9)
997  of "lAarr", "Lleftarrow": Rune(0x021DA)
998  of "rAarr", "Rrightarrow": Rune(0x021DB)
999  of "zigrarr": Rune(0x021DD)
1000  of "larrb", "LeftArrowBar": Rune(0x021E4)
1001  of "rarrb", "RightArrowBar": Rune(0x021E5)
1002  of "duarr", "DownArrowUpArrow": Rune(0x021F5)
1003  of "loarr": Rune(0x021FD)
1004  of "roarr": Rune(0x021FE)
1005  of "hoarr": Rune(0x021FF)
1006  of "forall", "ForAll": Rune(0x02200)
1007  of "comp", "complement": Rune(0x02201)
1008  of "part", "PartialD": Rune(0x02202)
1009  of "exist", "Exists": Rune(0x02203)
1010  of "nexist", "NotExists", "nexists": Rune(0x02204)
1011  of "empty", "emptyset", "emptyv", "varnothing": Rune(0x02205)
1012  of "nabla", "Del": Rune(0x02207)
1013  of "isin", "isinv", "Element", "in": Rune(0x02208)
1014  of "notin", "NotElement", "notinva": Rune(0x02209)
1015  of "niv", "ReverseElement", "ni", "SuchThat": Rune(0x0220B)
1016  of "notni", "notniva", "NotReverseElement": Rune(0x0220C)
1017  of "prod", "Product": Rune(0x0220F)
1018  of "coprod", "Coproduct": Rune(0x02210)
1019  of "sum", "Sum": Rune(0x02211)
1020  of "minus": Rune(0x02212)
1021  of "mnplus", "mp", "MinusPlus": Rune(0x02213)
1022  of "plusdo", "dotplus": Rune(0x02214)
1023  of "setmn", "setminus", "Backslash", "ssetmn",
1024    "smallsetminus": Rune(0x02216)
1025  of "lowast": Rune(0x02217)
1026  of "compfn", "SmallCircle": Rune(0x02218)
1027  of "radic", "Sqrt": Rune(0x0221A)
1028  of "prop", "propto", "Proportional", "vprop",
1029    "varpropto": Rune(0x0221D)
1030  of "infin": Rune(0x0221E)
1031  of "angrt": Rune(0x0221F)
1032  of "ang", "angle": Rune(0x02220)
1033  of "angmsd", "measuredangle": Rune(0x02221)
1034  of "angsph": Rune(0x02222)
1035  of "mid", "VerticalBar", "smid", "shortmid": Rune(0x02223)
1036  of "nmid", "NotVerticalBar", "nsmid", "nshortmid": Rune(0x02224)
1037  of "par", "parallel", "DoubleVerticalBar", "spar",
1038    "shortparallel": Rune(0x02225)
1039  of "npar", "nparallel", "NotDoubleVerticalBar", "nspar",
1040    "nshortparallel": Rune(0x02226)
1041  of "and", "wedge": Rune(0x02227)
1042  of "or", "vee": Rune(0x02228)
1043  of "cap": Rune(0x02229)
1044  of "cup": Rune(0x0222A)
1045  of "int", "Integral": Rune(0x0222B)
1046  of "Int": Rune(0x0222C)
1047  of "tint", "iiint": Rune(0x0222D)
1048  of "conint", "oint", "ContourIntegral": Rune(0x0222E)
1049  of "Conint", "DoubleContourIntegral": Rune(0x0222F)
1050  of "Cconint": Rune(0x02230)
1051  of "cwint": Rune(0x02231)
1052  of "cwconint", "ClockwiseContourIntegral": Rune(0x02232)
1053  of "awconint", "CounterClockwiseContourIntegral": Rune(0x02233)
1054  of "there4", "therefore", "Therefore": Rune(0x02234)
1055  of "becaus", "because", "Because": Rune(0x02235)
1056  of "ratio": Rune(0x02236)
1057  of "Colon", "Proportion": Rune(0x02237)
1058  of "minusd", "dotminus": Rune(0x02238)
1059  of "mDDot": Rune(0x0223A)
1060  of "homtht": Rune(0x0223B)
1061  of "sim", "Tilde", "thksim", "thicksim": Rune(0x0223C)
1062  of "bsim", "backsim": Rune(0x0223D)
1063  of "ac", "mstpos": Rune(0x0223E)
1064  of "acd": Rune(0x0223F)
1065  of "wreath", "VerticalTilde", "wr": Rune(0x02240)
1066  of "nsim", "NotTilde": Rune(0x02241)
1067  of "esim", "EqualTilde", "eqsim": Rune(0x02242)
1068  of "sime", "TildeEqual", "simeq": Rune(0x02243)
1069  of "nsime", "nsimeq", "NotTildeEqual": Rune(0x02244)
1070  of "cong", "TildeFullEqual": Rune(0x02245)
1071  of "simne": Rune(0x02246)
1072  of "ncong", "NotTildeFullEqual": Rune(0x02247)
1073  of "asymp", "ap", "TildeTilde", "approx", "thkap",
1074    "thickapprox": Rune(0x02248)
1075  of "nap", "NotTildeTilde", "napprox": Rune(0x02249)
1076  of "ape", "approxeq": Rune(0x0224A)
1077  of "apid": Rune(0x0224B)
1078  of "bcong", "backcong": Rune(0x0224C)
1079  of "asympeq", "CupCap": Rune(0x0224D)
1080  of "bump", "HumpDownHump", "Bumpeq": Rune(0x0224E)
1081  of "bumpe", "HumpEqual", "bumpeq": Rune(0x0224F)
1082  of "esdot", "DotEqual", "doteq": Rune(0x02250)
1083  of "eDot", "doteqdot": Rune(0x02251)
1084  of "efDot", "fallingdotseq": Rune(0x02252)
1085  of "erDot", "risingdotseq": Rune(0x02253)
1086  of "colone", "coloneq", "Assign": Rune(0x02254)
1087  of "ecolon", "eqcolon": Rune(0x02255)
1088  of "ecir", "eqcirc": Rune(0x02256)
1089  of "cire", "circeq": Rune(0x02257)
1090  of "wedgeq": Rune(0x02259)
1091  of "veeeq": Rune(0x0225A)
1092  of "trie", "triangleq": Rune(0x0225C)
1093  of "equest", "questeq": Rune(0x0225F)
1094  of "ne", "NotEqual": Rune(0x02260)
1095  of "equiv", "Congruent": Rune(0x02261)
1096  of "nequiv", "NotCongruent": Rune(0x02262)
1097  of "le", "leq": Rune(0x02264)
1098  of "ge", "GreaterEqual", "geq": Rune(0x02265)
1099  of "lE", "LessFullEqual", "leqq": Rune(0x02266)
1100  of "gE", "GreaterFullEqual", "geqq": Rune(0x02267)
1101  of "lnE", "lneqq": Rune(0x02268)
1102  of "gnE", "gneqq": Rune(0x02269)
1103  of "Lt", "NestedLessLess", "ll": Rune(0x0226A)
1104  of "Gt", "NestedGreaterGreater", "gg": Rune(0x0226B)
1105  of "twixt", "between": Rune(0x0226C)
1106  of "NotCupCap": Rune(0x0226D)
1107  of "nlt", "NotLess", "nless": Rune(0x0226E)
1108  of "ngt", "NotGreater", "ngtr": Rune(0x0226F)
1109  of "nle", "NotLessEqual", "nleq": Rune(0x02270)
1110  of "nge", "NotGreaterEqual", "ngeq": Rune(0x02271)
1111  of "lsim", "LessTilde", "lesssim": Rune(0x02272)
1112  of "gsim", "gtrsim", "GreaterTilde": Rune(0x02273)
1113  of "nlsim", "NotLessTilde": Rune(0x02274)
1114  of "ngsim", "NotGreaterTilde": Rune(0x02275)
1115  of "lg", "lessgtr", "LessGreater": Rune(0x02276)
1116  of "gl", "gtrless", "GreaterLess": Rune(0x02277)
1117  of "ntlg", "NotLessGreater": Rune(0x02278)
1118  of "ntgl", "NotGreaterLess": Rune(0x02279)
1119  of "pr", "Precedes", "prec": Rune(0x0227A)
1120  of "sc", "Succeeds", "succ": Rune(0x0227B)
1121  of "prcue", "PrecedesSlantEqual", "preccurlyeq": Rune(0x0227C)
1122  of "sccue", "SucceedsSlantEqual", "succcurlyeq": Rune(0x0227D)
1123  of "prsim", "precsim", "PrecedesTilde": Rune(0x0227E)
1124  of "scsim", "succsim", "SucceedsTilde": Rune(0x0227F)
1125  of "npr", "nprec", "NotPrecedes": Rune(0x02280)
1126  of "nsc", "nsucc", "NotSucceeds": Rune(0x02281)
1127  of "sub", "subset": Rune(0x02282)
1128  of "sup", "supset", "Superset": Rune(0x02283)
1129  of "nsub": Rune(0x02284)
1130  of "nsup": Rune(0x02285)
1131  of "sube", "SubsetEqual", "subseteq": Rune(0x02286)
1132  of "supe", "supseteq", "SupersetEqual": Rune(0x02287)
1133  of "nsube", "nsubseteq", "NotSubsetEqual": Rune(0x02288)
1134  of "nsupe", "nsupseteq", "NotSupersetEqual": Rune(0x02289)
1135  of "subne", "subsetneq": Rune(0x0228A)
1136  of "supne", "supsetneq": Rune(0x0228B)
1137  of "cupdot": Rune(0x0228D)
1138  of "uplus", "UnionPlus": Rune(0x0228E)
1139  of "sqsub", "SquareSubset", "sqsubset": Rune(0x0228F)
1140  of "sqsup", "SquareSuperset", "sqsupset": Rune(0x02290)
1141  of "sqsube", "SquareSubsetEqual", "sqsubseteq": Rune(0x02291)
1142  of "sqsupe", "SquareSupersetEqual", "sqsupseteq": Rune(0x02292)
1143  of "sqcap", "SquareIntersection": Rune(0x02293)
1144  of "sqcup", "SquareUnion": Rune(0x02294)
1145  of "oplus", "CirclePlus": Rune(0x02295)
1146  of "ominus", "CircleMinus": Rune(0x02296)
1147  of "otimes", "CircleTimes": Rune(0x02297)
1148  of "osol": Rune(0x02298)
1149  of "odot", "CircleDot": Rune(0x02299)
1150  of "ocir", "circledcirc": Rune(0x0229A)
1151  of "oast", "circledast": Rune(0x0229B)
1152  of "odash", "circleddash": Rune(0x0229D)
1153  of "plusb", "boxplus": Rune(0x0229E)
1154  of "minusb", "boxminus": Rune(0x0229F)
1155  of "timesb", "boxtimes": Rune(0x022A0)
1156  of "sdotb", "dotsquare": Rune(0x022A1)
1157  of "vdash", "RightTee": Rune(0x022A2)
1158  of "dashv", "LeftTee": Rune(0x022A3)
1159  of "top", "DownTee": Rune(0x022A4)
1160  of "bottom", "bot", "perp", "UpTee": Rune(0x022A5)
1161  of "models": Rune(0x022A7)
1162  of "vDash", "DoubleRightTee": Rune(0x022A8)
1163  of "Vdash": Rune(0x022A9)
1164  of "Vvdash": Rune(0x022AA)
1165  of "VDash": Rune(0x022AB)
1166  of "nvdash": Rune(0x022AC)
1167  of "nvDash": Rune(0x022AD)
1168  of "nVdash": Rune(0x022AE)
1169  of "nVDash": Rune(0x022AF)
1170  of "prurel": Rune(0x022B0)
1171  of "vltri", "vartriangleleft", "LeftTriangle": Rune(0x022B2)
1172  of "vrtri", "vartriangleright", "RightTriangle": Rune(0x022B3)
1173  of "ltrie", "trianglelefteq", "LeftTriangleEqual": Rune(0x022B4)
1174  of "rtrie", "trianglerighteq", "RightTriangleEqual": Rune(0x022B5)
1175  of "origof": Rune(0x022B6)
1176  of "imof": Rune(0x022B7)
1177  of "mumap", "multimap": Rune(0x022B8)
1178  of "hercon": Rune(0x022B9)
1179  of "intcal", "intercal": Rune(0x022BA)
1180  of "veebar": Rune(0x022BB)
1181  of "barvee": Rune(0x022BD)
1182  of "angrtvb": Rune(0x022BE)
1183  of "lrtri": Rune(0x022BF)
1184  of "xwedge", "Wedge", "bigwedge": Rune(0x022C0)
1185  of "xvee", "Vee", "bigvee": Rune(0x022C1)
1186  of "xcap", "Intersection", "bigcap": Rune(0x022C2)
1187  of "xcup", "Union", "bigcup": Rune(0x022C3)
1188  of "diam", "diamond", "Diamond": Rune(0x022C4)
1189  of "sdot": Rune(0x022C5)
1190  of "sstarf", "Star": Rune(0x022C6)
1191  of "divonx", "divideontimes": Rune(0x022C7)
1192  of "bowtie": Rune(0x022C8)
1193  of "ltimes": Rune(0x022C9)
1194  of "rtimes": Rune(0x022CA)
1195  of "lthree", "leftthreetimes": Rune(0x022CB)
1196  of "rthree", "rightthreetimes": Rune(0x022CC)
1197  of "bsime", "backsimeq": Rune(0x022CD)
1198  of "cuvee", "curlyvee": Rune(0x022CE)
1199  of "cuwed", "curlywedge": Rune(0x022CF)
1200  of "Sub", "Subset": Rune(0x022D0)
1201  of "Sup", "Supset": Rune(0x022D1)
1202  of "Cap": Rune(0x022D2)
1203  of "Cup": Rune(0x022D3)
1204  of "fork", "pitchfork": Rune(0x022D4)
1205  of "epar": Rune(0x022D5)
1206  of "ltdot", "lessdot": Rune(0x022D6)
1207  of "gtdot", "gtrdot": Rune(0x022D7)
1208  of "Ll": Rune(0x022D8)
1209  of "Gg", "ggg": Rune(0x022D9)
1210  of "leg", "LessEqualGreater", "lesseqgtr": Rune(0x022DA)
1211  of "gel", "gtreqless", "GreaterEqualLess": Rune(0x022DB)
1212  of "cuepr", "curlyeqprec": Rune(0x022DE)
1213  of "cuesc", "curlyeqsucc": Rune(0x022DF)
1214  of "nprcue", "NotPrecedesSlantEqual": Rune(0x022E0)
1215  of "nsccue", "NotSucceedsSlantEqual": Rune(0x022E1)
1216  of "nsqsube", "NotSquareSubsetEqual": Rune(0x022E2)
1217  of "nsqsupe", "NotSquareSupersetEqual": Rune(0x022E3)
1218  of "lnsim": Rune(0x022E6)
1219  of "gnsim": Rune(0x022E7)
1220  of "prnsim", "precnsim": Rune(0x022E8)
1221  of "scnsim", "succnsim": Rune(0x022E9)
1222  of "nltri", "ntriangleleft", "NotLeftTriangle": Rune(0x022EA)
1223  of "nrtri", "ntriangleright", "NotRightTriangle": Rune(0x022EB)
1224  of "nltrie", "ntrianglelefteq",
1225    "NotLeftTriangleEqual": Rune(0x022EC)
1226  of "nrtrie", "ntrianglerighteq",
1227    "NotRightTriangleEqual": Rune(0x022ED)
1228  of "vellip": Rune(0x022EE)
1229  of "ctdot": Rune(0x022EF)
1230  of "utdot": Rune(0x022F0)
1231  of "dtdot": Rune(0x022F1)
1232  of "disin": Rune(0x022F2)
1233  of "isinsv": Rune(0x022F3)
1234  of "isins": Rune(0x022F4)
1235  of "isindot": Rune(0x022F5)
1236  of "notinvc": Rune(0x022F6)
1237  of "notinvb": Rune(0x022F7)
1238  of "isinE": Rune(0x022F9)
1239  of "nisd": Rune(0x022FA)
1240  of "xnis": Rune(0x022FB)
1241  of "nis": Rune(0x022FC)
1242  of "notnivc": Rune(0x022FD)
1243  of "notnivb": Rune(0x022FE)
1244  of "barwed", "barwedge": Rune(0x02305)
1245  of "Barwed", "doublebarwedge": Rune(0x02306)
1246  of "lceil", "LeftCeiling": Rune(0x02308)
1247  of "rceil", "RightCeiling": Rune(0x02309)
1248  of "lfloor", "LeftFloor": Rune(0x0230A)
1249  of "rfloor", "RightFloor": Rune(0x0230B)
1250  of "drcrop": Rune(0x0230C)
1251  of "dlcrop": Rune(0x0230D)
1252  of "urcrop": Rune(0x0230E)
1253  of "ulcrop": Rune(0x0230F)
1254  of "bnot": Rune(0x02310)
1255  of "profline": Rune(0x02312)
1256  of "profsurf": Rune(0x02313)
1257  of "telrec": Rune(0x02315)
1258  of "target": Rune(0x02316)
1259  of "ulcorn", "ulcorner": Rune(0x0231C)
1260  of "urcorn", "urcorner": Rune(0x0231D)
1261  of "dlcorn", "llcorner": Rune(0x0231E)
1262  of "drcorn", "lrcorner": Rune(0x0231F)
1263  of "frown", "sfrown": Rune(0x02322)
1264  of "smile", "ssmile": Rune(0x02323)
1265  of "cylcty": Rune(0x0232D)
1266  of "profalar": Rune(0x0232E)
1267  of "topbot": Rune(0x02336)
1268  of "ovbar": Rune(0x0233D)
1269  of "solbar": Rune(0x0233F)
1270  of "angzarr": Rune(0x0237C)
1271  of "lmoust", "lmoustache": Rune(0x023B0)
1272  of "rmoust", "rmoustache": Rune(0x023B1)
1273  of "tbrk", "OverBracket": Rune(0x023B4)
1274  of "bbrk", "UnderBracket": Rune(0x023B5)
1275  of "bbrktbrk": Rune(0x023B6)
1276  of "OverParenthesis": Rune(0x023DC)
1277  of "UnderParenthesis": Rune(0x023DD)
1278  of "OverBrace": Rune(0x023DE)
1279  of "UnderBrace": Rune(0x023DF)
1280  of "trpezium": Rune(0x023E2)
1281  of "elinters": Rune(0x023E7)
1282  of "blank": Rune(0x02423)
1283  of "oS", "circledS": Rune(0x024C8)
1284  of "boxh", "HorizontalLine": Rune(0x02500)
1285  of "boxv": Rune(0x02502)
1286  of "boxdr": Rune(0x0250C)
1287  of "boxdl": Rune(0x02510)
1288  of "boxur": Rune(0x02514)
1289  of "boxul": Rune(0x02518)
1290  of "boxvr": Rune(0x0251C)
1291  of "boxvl": Rune(0x02524)
1292  of "boxhd": Rune(0x0252C)
1293  of "boxhu": Rune(0x02534)
1294  of "boxvh": Rune(0x0253C)
1295  of "boxH": Rune(0x02550)
1296  of "boxV": Rune(0x02551)
1297  of "boxdR": Rune(0x02552)
1298  of "boxDr": Rune(0x02553)
1299  of "boxDR": Rune(0x02554)
1300  of "boxdL": Rune(0x02555)
1301  of "boxDl": Rune(0x02556)
1302  of "boxDL": Rune(0x02557)
1303  of "boxuR": Rune(0x02558)
1304  of "boxUr": Rune(0x02559)
1305  of "boxUR": Rune(0x0255A)
1306  of "boxuL": Rune(0x0255B)
1307  of "boxUl": Rune(0x0255C)
1308  of "boxUL": Rune(0x0255D)
1309  of "boxvR": Rune(0x0255E)
1310  of "boxVr": Rune(0x0255F)
1311  of "boxVR": Rune(0x02560)
1312  of "boxvL": Rune(0x02561)
1313  of "boxVl": Rune(0x02562)
1314  of "boxVL": Rune(0x02563)
1315  of "boxHd": Rune(0x02564)
1316  of "boxhD": Rune(0x02565)
1317  of "boxHD": Rune(0x02566)
1318  of "boxHu": Rune(0x02567)
1319  of "boxhU": Rune(0x02568)
1320  of "boxHU": Rune(0x02569)
1321  of "boxvH": Rune(0x0256A)
1322  of "boxVh": Rune(0x0256B)
1323  of "boxVH": Rune(0x0256C)
1324  of "uhblk": Rune(0x02580)
1325  of "lhblk": Rune(0x02584)
1326  of "block": Rune(0x02588)
1327  of "blk14": Rune(0x02591)
1328  of "blk12": Rune(0x02592)
1329  of "blk34": Rune(0x02593)
1330  of "squ", "square", "Square": Rune(0x025A1)
1331  of "squf", "squarf", "blacksquare",
1332    "FilledVerySmallSquare": Rune(0x025AA)
1333  of "EmptyVerySmallSquare": Rune(0x025AB)
1334  of "rect": Rune(0x025AD)
1335  of "marker": Rune(0x025AE)
1336  of "fltns": Rune(0x025B1)
1337  of "xutri", "bigtriangleup": Rune(0x025B3)
1338  of "utrif", "blacktriangle": Rune(0x025B4)
1339  of "utri", "triangle": Rune(0x025B5)
1340  of "rtrif", "blacktriangleright": Rune(0x025B8)
1341  of "rtri", "triangleright": Rune(0x025B9)
1342  of "xdtri", "bigtriangledown": Rune(0x025BD)
1343  of "dtrif", "blacktriangledown": Rune(0x025BE)
1344  of "dtri", "triangledown": Rune(0x025BF)
1345  of "ltrif", "blacktriangleleft": Rune(0x025C2)
1346  of "ltri", "triangleleft": Rune(0x025C3)
1347  of "loz", "lozenge": Rune(0x025CA)
1348  of "cir": Rune(0x025CB)
1349  of "tridot": Rune(0x025EC)
1350  of "xcirc", "bigcirc": Rune(0x025EF)
1351  of "ultri": Rune(0x025F8)
1352  of "urtri": Rune(0x025F9)
1353  of "lltri": Rune(0x025FA)
1354  of "EmptySmallSquare": Rune(0x025FB)
1355  of "FilledSmallSquare": Rune(0x025FC)
1356  of "starf", "bigstar": Rune(0x02605)
1357  of "star": Rune(0x02606)
1358  of "phone": Rune(0x0260E)
1359  of "female": Rune(0x02640)
1360  of "male": Rune(0x02642)
1361  of "spades", "spadesuit": Rune(0x02660)
1362  of "clubs", "clubsuit": Rune(0x02663)
1363  of "hearts", "heartsuit": Rune(0x02665)
1364  of "diams", "diamondsuit": Rune(0x02666)
1365  of "sung": Rune(0x0266A)
1366  of "flat": Rune(0x0266D)
1367  of "natur", "natural": Rune(0x0266E)
1368  of "sharp": Rune(0x0266F)
1369  of "check", "checkmark": Rune(0x02713)
1370  of "cross": Rune(0x02717)
1371  of "malt", "maltese": Rune(0x02720)
1372  of "sext": Rune(0x02736)
1373  of "VerticalSeparator": Rune(0x02758)
1374  of "lbbrk": Rune(0x02772)
1375  of "rbbrk": Rune(0x02773)
1376  of "lobrk", "LeftDoubleBracket": Rune(0x027E6)
1377  of "robrk", "RightDoubleBracket": Rune(0x027E7)
1378  of "lang", "LeftAngleBracket", "langle": Rune(0x027E8)
1379  of "rang", "RightAngleBracket", "rangle": Rune(0x027E9)
1380  of "Lang": Rune(0x027EA)
1381  of "Rang": Rune(0x027EB)
1382  of "loang": Rune(0x027EC)
1383  of "roang": Rune(0x027ED)
1384  of "xlarr", "longleftarrow", "LongLeftArrow": Rune(0x027F5)
1385  of "xrarr", "longrightarrow", "LongRightArrow": Rune(0x027F6)
1386  of "xharr", "longleftrightarrow",
1387    "LongLeftRightArrow": Rune(0x027F7)
1388  of "xlArr", "Longleftarrow", "DoubleLongLeftArrow": Rune(0x027F8)
1389  of "xrArr", "Longrightarrow", "DoubleLongRightArrow": Rune(0x027F9)
1390  of "xhArr", "Longleftrightarrow",
1391    "DoubleLongLeftRightArrow": Rune(0x027FA)
1392  of "xmap", "longmapsto": Rune(0x027FC)
1393  of "dzigrarr": Rune(0x027FF)
1394  of "nvlArr": Rune(0x02902)
1395  of "nvrArr": Rune(0x02903)
1396  of "nvHarr": Rune(0x02904)
1397  of "Map": Rune(0x02905)
1398  of "lbarr": Rune(0x0290C)
1399  of "rbarr", "bkarow": Rune(0x0290D)
1400  of "lBarr": Rune(0x0290E)
1401  of "rBarr", "dbkarow": Rune(0x0290F)
1402  of "RBarr", "drbkarow": Rune(0x02910)
1403  of "DDotrahd": Rune(0x02911)
1404  of "UpArrowBar": Rune(0x02912)
1405  of "DownArrowBar": Rune(0x02913)
1406  of "Rarrtl": Rune(0x02916)
1407  of "latail": Rune(0x02919)
1408  of "ratail": Rune(0x0291A)
1409  of "lAtail": Rune(0x0291B)
1410  of "rAtail": Rune(0x0291C)
1411  of "larrfs": Rune(0x0291D)
1412  of "rarrfs": Rune(0x0291E)
1413  of "larrbfs": Rune(0x0291F)
1414  of "rarrbfs": Rune(0x02920)
1415  of "nwarhk": Rune(0x02923)
1416  of "nearhk": Rune(0x02924)
1417  of "searhk", "hksearow": Rune(0x02925)
1418  of "swarhk", "hkswarow": Rune(0x02926)
1419  of "nwnear": Rune(0x02927)
1420  of "nesear", "toea": Rune(0x02928)
1421  of "seswar", "tosa": Rune(0x02929)
1422  of "swnwar": Rune(0x0292A)
1423  of "rarrc": Rune(0x02933)
1424  of "cudarrr": Rune(0x02935)
1425  of "ldca": Rune(0x02936)
1426  of "rdca": Rune(0x02937)
1427  of "cudarrl": Rune(0x02938)
1428  of "larrpl": Rune(0x02939)
1429  of "curarrm": Rune(0x0293C)
1430  of "cularrp": Rune(0x0293D)
1431  of "rarrpl": Rune(0x02945)
1432  of "harrcir": Rune(0x02948)
1433  of "Uarrocir": Rune(0x02949)
1434  of "lurdshar": Rune(0x0294A)
1435  of "ldrushar": Rune(0x0294B)
1436  of "LeftRightVector": Rune(0x0294E)
1437  of "RightUpDownVector": Rune(0x0294F)
1438  of "DownLeftRightVector": Rune(0x02950)
1439  of "LeftUpDownVector": Rune(0x02951)
1440  of "LeftVectorBar": Rune(0x02952)
1441  of "RightVectorBar": Rune(0x02953)
1442  of "RightUpVectorBar": Rune(0x02954)
1443  of "RightDownVectorBar": Rune(0x02955)
1444  of "DownLeftVectorBar": Rune(0x02956)
1445  of "DownRightVectorBar": Rune(0x02957)
1446  of "LeftUpVectorBar": Rune(0x02958)
1447  of "LeftDownVectorBar": Rune(0x02959)
1448  of "LeftTeeVector": Rune(0x0295A)
1449  of "RightTeeVector": Rune(0x0295B)
1450  of "RightUpTeeVector": Rune(0x0295C)
1451  of "RightDownTeeVector": Rune(0x0295D)
1452  of "DownLeftTeeVector": Rune(0x0295E)
1453  of "DownRightTeeVector": Rune(0x0295F)
1454  of "LeftUpTeeVector": Rune(0x02960)
1455  of "LeftDownTeeVector": Rune(0x02961)
1456  of "lHar": Rune(0x02962)
1457  of "uHar": Rune(0x02963)
1458  of "rHar": Rune(0x02964)
1459  of "dHar": Rune(0x02965)
1460  of "luruhar": Rune(0x02966)
1461  of "ldrdhar": Rune(0x02967)
1462  of "ruluhar": Rune(0x02968)
1463  of "rdldhar": Rune(0x02969)
1464  of "lharul": Rune(0x0296A)
1465  of "llhard": Rune(0x0296B)
1466  of "rharul": Rune(0x0296C)
1467  of "lrhard": Rune(0x0296D)
1468  of "udhar", "UpEquilibrium": Rune(0x0296E)
1469  of "duhar", "ReverseUpEquilibrium": Rune(0x0296F)
1470  of "RoundImplies": Rune(0x02970)
1471  of "erarr": Rune(0x02971)
1472  of "simrarr": Rune(0x02972)
1473  of "larrsim": Rune(0x02973)
1474  of "rarrsim": Rune(0x02974)
1475  of "rarrap": Rune(0x02975)
1476  of "ltlarr": Rune(0x02976)
1477  of "gtrarr": Rune(0x02978)
1478  of "subrarr": Rune(0x02979)
1479  of "suplarr": Rune(0x0297B)
1480  of "lfisht": Rune(0x0297C)
1481  of "rfisht": Rune(0x0297D)
1482  of "ufisht": Rune(0x0297E)
1483  of "dfisht": Rune(0x0297F)
1484  of "lopar": Rune(0x02985)
1485  of "ropar": Rune(0x02986)
1486  of "lbrke": Rune(0x0298B)
1487  of "rbrke": Rune(0x0298C)
1488  of "lbrkslu": Rune(0x0298D)
1489  of "rbrksld": Rune(0x0298E)
1490  of "lbrksld": Rune(0x0298F)
1491  of "rbrkslu": Rune(0x02990)
1492  of "langd": Rune(0x02991)
1493  of "rangd": Rune(0x02992)
1494  of "lparlt": Rune(0x02993)
1495  of "rpargt": Rune(0x02994)
1496  of "gtlPar": Rune(0x02995)
1497  of "ltrPar": Rune(0x02996)
1498  of "vzigzag": Rune(0x0299A)
1499  of "vangrt": Rune(0x0299C)
1500  of "angrtvbd": Rune(0x0299D)
1501  of "ange": Rune(0x029A4)
1502  of "range": Rune(0x029A5)
1503  of "dwangle": Rune(0x029A6)
1504  of "uwangle": Rune(0x029A7)
1505  of "angmsdaa": Rune(0x029A8)
1506  of "angmsdab": Rune(0x029A9)
1507  of "angmsdac": Rune(0x029AA)
1508  of "angmsdad": Rune(0x029AB)
1509  of "angmsdae": Rune(0x029AC)
1510  of "angmsdaf": Rune(0x029AD)
1511  of "angmsdag": Rune(0x029AE)
1512  of "angmsdah": Rune(0x029AF)
1513  of "bemptyv": Rune(0x029B0)
1514  of "demptyv": Rune(0x029B1)
1515  of "cemptyv": Rune(0x029B2)
1516  of "raemptyv": Rune(0x029B3)
1517  of "laemptyv": Rune(0x029B4)
1518  of "ohbar": Rune(0x029B5)
1519  of "omid": Rune(0x029B6)
1520  of "opar": Rune(0x029B7)
1521  of "operp": Rune(0x029B9)
1522  of "olcross": Rune(0x029BB)
1523  of "odsold": Rune(0x029BC)
1524  of "olcir": Rune(0x029BE)
1525  of "ofcir": Rune(0x029BF)
1526  of "olt": Rune(0x029C0)
1527  of "ogt": Rune(0x029C1)
1528  of "cirscir": Rune(0x029C2)
1529  of "cirE": Rune(0x029C3)
1530  of "solb": Rune(0x029C4)
1531  of "bsolb": Rune(0x029C5)
1532  of "boxbox": Rune(0x029C9)
1533  of "trisb": Rune(0x029CD)
1534  of "rtriltri": Rune(0x029CE)
1535  of "LeftTriangleBar": Rune(0x029CF)
1536  of "RightTriangleBar": Rune(0x029D0)
1537  of "race": Rune(0x029DA)
1538  of "iinfin": Rune(0x029DC)
1539  of "infintie": Rune(0x029DD)
1540  of "nvinfin": Rune(0x029DE)
1541  of "eparsl": Rune(0x029E3)
1542  of "smeparsl": Rune(0x029E4)
1543  of "eqvparsl": Rune(0x029E5)
1544  of "lozf", "blacklozenge": Rune(0x029EB)
1545  of "RuleDelayed": Rune(0x029F4)
1546  of "dsol": Rune(0x029F6)
1547  of "xodot", "bigodot": Rune(0x02A00)
1548  of "xoplus", "bigoplus": Rune(0x02A01)
1549  of "xotime", "bigotimes": Rune(0x02A02)
1550  of "xuplus", "biguplus": Rune(0x02A04)
1551  of "xsqcup", "bigsqcup": Rune(0x02A06)
1552  of "qint", "iiiint": Rune(0x02A0C)
1553  of "fpartint": Rune(0x02A0D)
1554  of "cirfnint": Rune(0x02A10)
1555  of "awint": Rune(0x02A11)
1556  of "rppolint": Rune(0x02A12)
1557  of "scpolint": Rune(0x02A13)
1558  of "npolint": Rune(0x02A14)
1559  of "pointint": Rune(0x02A15)
1560  of "quatint": Rune(0x02A16)
1561  of "intlarhk": Rune(0x02A17)
1562  of "pluscir": Rune(0x02A22)
1563  of "plusacir": Rune(0x02A23)
1564  of "simplus": Rune(0x02A24)
1565  of "plusdu": Rune(0x02A25)
1566  of "plussim": Rune(0x02A26)
1567  of "plustwo": Rune(0x02A27)
1568  of "mcomma": Rune(0x02A29)
1569  of "minusdu": Rune(0x02A2A)
1570  of "loplus": Rune(0x02A2D)
1571  of "roplus": Rune(0x02A2E)
1572  of "Cross": Rune(0x02A2F)
1573  of "timesd": Rune(0x02A30)
1574  of "timesbar": Rune(0x02A31)
1575  of "smashp": Rune(0x02A33)
1576  of "lotimes": Rune(0x02A34)
1577  of "rotimes": Rune(0x02A35)
1578  of "otimesas": Rune(0x02A36)
1579  of "Otimes": Rune(0x02A37)
1580  of "odiv": Rune(0x02A38)
1581  of "triplus": Rune(0x02A39)
1582  of "triminus": Rune(0x02A3A)
1583  of "tritime": Rune(0x02A3B)
1584  of "iprod", "intprod": Rune(0x02A3C)
1585  of "amalg": Rune(0x02A3F)
1586  of "capdot": Rune(0x02A40)
1587  of "ncup": Rune(0x02A42)
1588  of "ncap": Rune(0x02A43)
1589  of "capand": Rune(0x02A44)
1590  of "cupor": Rune(0x02A45)
1591  of "cupcap": Rune(0x02A46)
1592  of "capcup": Rune(0x02A47)
1593  of "cupbrcap": Rune(0x02A48)
1594  of "capbrcup": Rune(0x02A49)
1595  of "cupcup": Rune(0x02A4A)
1596  of "capcap": Rune(0x02A4B)
1597  of "ccups": Rune(0x02A4C)
1598  of "ccaps": Rune(0x02A4D)
1599  of "ccupssm": Rune(0x02A50)
1600  of "And": Rune(0x02A53)
1601  of "Or": Rune(0x02A54)
1602  of "andand": Rune(0x02A55)
1603  of "oror": Rune(0x02A56)
1604  of "orslope": Rune(0x02A57)
1605  of "andslope": Rune(0x02A58)
1606  of "andv": Rune(0x02A5A)
1607  of "orv": Rune(0x02A5B)
1608  of "andd": Rune(0x02A5C)
1609  of "ord": Rune(0x02A5D)
1610  of "wedbar": Rune(0x02A5F)
1611  of "sdote": Rune(0x02A66)
1612  of "simdot": Rune(0x02A6A)
1613  of "congdot": Rune(0x02A6D)
1614  of "easter": Rune(0x02A6E)
1615  of "apacir": Rune(0x02A6F)
1616  of "apE": Rune(0x02A70)
1617  of "eplus": Rune(0x02A71)
1618  of "pluse": Rune(0x02A72)
1619  of "Esim": Rune(0x02A73)
1620  of "Colone": Rune(0x02A74)
1621  of "Equal": Rune(0x02A75)
1622  of "eDDot", "ddotseq": Rune(0x02A77)
1623  of "equivDD": Rune(0x02A78)
1624  of "ltcir": Rune(0x02A79)
1625  of "gtcir": Rune(0x02A7A)
1626  of "ltquest": Rune(0x02A7B)
1627  of "gtquest": Rune(0x02A7C)
1628  of "les", "LessSlantEqual", "leqslant": Rune(0x02A7D)
1629  of "ges", "GreaterSlantEqual", "geqslant": Rune(0x02A7E)
1630  of "lesdot": Rune(0x02A7F)
1631  of "gesdot": Rune(0x02A80)
1632  of "lesdoto": Rune(0x02A81)
1633  of "gesdoto": Rune(0x02A82)
1634  of "lesdotor": Rune(0x02A83)
1635  of "gesdotol": Rune(0x02A84)
1636  of "lap", "lessapprox": Rune(0x02A85)
1637  of "gap", "gtrapprox": Rune(0x02A86)
1638  of "lne", "lneq": Rune(0x02A87)
1639  of "gne", "gneq": Rune(0x02A88)
1640  of "lnap", "lnapprox": Rune(0x02A89)
1641  of "gnap", "gnapprox": Rune(0x02A8A)
1642  of "lEg", "lesseqqgtr": Rune(0x02A8B)
1643  of "gEl", "gtreqqless": Rune(0x02A8C)
1644  of "lsime": Rune(0x02A8D)
1645  of "gsime": Rune(0x02A8E)
1646  of "lsimg": Rune(0x02A8F)
1647  of "gsiml": Rune(0x02A90)
1648  of "lgE": Rune(0x02A91)
1649  of "glE": Rune(0x02A92)
1650  of "lesges": Rune(0x02A93)
1651  of "gesles": Rune(0x02A94)
1652  of "els", "eqslantless": Rune(0x02A95)
1653  of "egs", "eqslantgtr": Rune(0x02A96)
1654  of "elsdot": Rune(0x02A97)
1655  of "egsdot": Rune(0x02A98)
1656  of "el": Rune(0x02A99)
1657  of "eg": Rune(0x02A9A)
1658  of "siml": Rune(0x02A9D)
1659  of "simg": Rune(0x02A9E)
1660  of "simlE": Rune(0x02A9F)
1661  of "simgE": Rune(0x02AA0)
1662  of "LessLess": Rune(0x02AA1)
1663  of "GreaterGreater": Rune(0x02AA2)
1664  of "glj": Rune(0x02AA4)
1665  of "gla": Rune(0x02AA5)
1666  of "ltcc": Rune(0x02AA6)
1667  of "gtcc": Rune(0x02AA7)
1668  of "lescc": Rune(0x02AA8)
1669  of "gescc": Rune(0x02AA9)
1670  of "smt": Rune(0x02AAA)
1671  of "lat": Rune(0x02AAB)
1672  of "smte": Rune(0x02AAC)
1673  of "late": Rune(0x02AAD)
1674  of "bumpE": Rune(0x02AAE)
1675  of "pre", "preceq", "PrecedesEqual": Rune(0x02AAF)
1676  of "sce", "succeq", "SucceedsEqual": Rune(0x02AB0)
1677  of "prE": Rune(0x02AB3)
1678  of "scE": Rune(0x02AB4)
1679  of "prnE", "precneqq": Rune(0x02AB5)
1680  of "scnE", "succneqq": Rune(0x02AB6)
1681  of "prap", "precapprox": Rune(0x02AB7)
1682  of "scap", "succapprox": Rune(0x02AB8)
1683  of "prnap", "precnapprox": Rune(0x02AB9)
1684  of "scnap", "succnapprox": Rune(0x02ABA)
1685  of "Pr": Rune(0x02ABB)
1686  of "Sc": Rune(0x02ABC)
1687  of "subdot": Rune(0x02ABD)
1688  of "supdot": Rune(0x02ABE)
1689  of "subplus": Rune(0x02ABF)
1690  of "supplus": Rune(0x02AC0)
1691  of "submult": Rune(0x02AC1)
1692  of "supmult": Rune(0x02AC2)
1693  of "subedot": Rune(0x02AC3)
1694  of "supedot": Rune(0x02AC4)
1695  of "subE", "subseteqq": Rune(0x02AC5)
1696  of "supE", "supseteqq": Rune(0x02AC6)
1697  of "subsim": Rune(0x02AC7)
1698  of "supsim": Rune(0x02AC8)
1699  of "subnE", "subsetneqq": Rune(0x02ACB)
1700  of "supnE", "supsetneqq": Rune(0x02ACC)
1701  of "csub": Rune(0x02ACF)
1702  of "csup": Rune(0x02AD0)
1703  of "csube": Rune(0x02AD1)
1704  of "csupe": Rune(0x02AD2)
1705  of "subsup": Rune(0x02AD3)
1706  of "supsub": Rune(0x02AD4)
1707  of "subsub": Rune(0x02AD5)
1708  of "supsup": Rune(0x02AD6)
1709  of "suphsub": Rune(0x02AD7)
1710  of "supdsub": Rune(0x02AD8)
1711  of "forkv": Rune(0x02AD9)
1712  of "topfork": Rune(0x02ADA)
1713  of "mlcp": Rune(0x02ADB)
1714  of "Dashv", "DoubleLeftTee": Rune(0x02AE4)
1715  of "Vdashl": Rune(0x02AE6)
1716  of "Barv": Rune(0x02AE7)
1717  of "vBar": Rune(0x02AE8)
1718  of "vBarv": Rune(0x02AE9)
1719  of "Vbar": Rune(0x02AEB)
1720  of "Not": Rune(0x02AEC)
1721  of "bNot": Rune(0x02AED)
1722  of "rnmid": Rune(0x02AEE)
1723  of "cirmid": Rune(0x02AEF)
1724  of "midcir": Rune(0x02AF0)
1725  of "topcir": Rune(0x02AF1)
1726  of "nhpar": Rune(0x02AF2)
1727  of "parsim": Rune(0x02AF3)
1728  of "parsl": Rune(0x02AFD)
1729  of "fflig": Rune(0x0FB00)
1730  of "filig": Rune(0x0FB01)
1731  of "fllig": Rune(0x0FB02)
1732  of "ffilig": Rune(0x0FB03)
1733  of "ffllig": Rune(0x0FB04)
1734  of "Ascr": Rune(0x1D49C)
1735  of "Cscr": Rune(0x1D49E)
1736  of "Dscr": Rune(0x1D49F)
1737  of "Gscr": Rune(0x1D4A2)
1738  of "Jscr": Rune(0x1D4A5)
1739  of "Kscr": Rune(0x1D4A6)
1740  of "Nscr": Rune(0x1D4A9)
1741  of "Oscr": Rune(0x1D4AA)
1742  of "Pscr": Rune(0x1D4AB)
1743  of "Qscr": Rune(0x1D4AC)
1744  of "Sscr": Rune(0x1D4AE)
1745  of "Tscr": Rune(0x1D4AF)
1746  of "Uscr": Rune(0x1D4B0)
1747  of "Vscr": Rune(0x1D4B1)
1748  of "Wscr": Rune(0x1D4B2)
1749  of "Xscr": Rune(0x1D4B3)
1750  of "Yscr": Rune(0x1D4B4)
1751  of "Zscr": Rune(0x1D4B5)
1752  of "ascr": Rune(0x1D4B6)
1753  of "bscr": Rune(0x1D4B7)
1754  of "cscr": Rune(0x1D4B8)
1755  of "dscr": Rune(0x1D4B9)
1756  of "fscr": Rune(0x1D4BB)
1757  of "hscr": Rune(0x1D4BD)
1758  of "iscr": Rune(0x1D4BE)
1759  of "jscr": Rune(0x1D4BF)
1760  of "kscr": Rune(0x1D4C0)
1761  of "lscr": Rune(0x1D4C1)
1762  of "mscr": Rune(0x1D4C2)
1763  of "nscr": Rune(0x1D4C3)
1764  of "pscr": Rune(0x1D4C5)
1765  of "qscr": Rune(0x1D4C6)
1766  of "rscr": Rune(0x1D4C7)
1767  of "sscr": Rune(0x1D4C8)
1768  of "tscr": Rune(0x1D4C9)
1769  of "uscr": Rune(0x1D4CA)
1770  of "vscr": Rune(0x1D4CB)
1771  of "wscr": Rune(0x1D4CC)
1772  of "xscr": Rune(0x1D4CD)
1773  of "yscr": Rune(0x1D4CE)
1774  of "zscr": Rune(0x1D4CF)
1775  of "Afr": Rune(0x1D504)
1776  of "Bfr": Rune(0x1D505)
1777  of "Dfr": Rune(0x1D507)
1778  of "Efr": Rune(0x1D508)
1779  of "Ffr": Rune(0x1D509)
1780  of "Gfr": Rune(0x1D50A)
1781  of "Jfr": Rune(0x1D50D)
1782  of "Kfr": Rune(0x1D50E)
1783  of "Lfr": Rune(0x1D50F)
1784  of "Mfr": Rune(0x1D510)
1785  of "Nfr": Rune(0x1D511)
1786  of "Ofr": Rune(0x1D512)
1787  of "Pfr": Rune(0x1D513)
1788  of "Qfr": Rune(0x1D514)
1789  of "Sfr": Rune(0x1D516)
1790  of "Tfr": Rune(0x1D517)
1791  of "Ufr": Rune(0x1D518)
1792  of "Vfr": Rune(0x1D519)
1793  of "Wfr": Rune(0x1D51A)
1794  of "Xfr": Rune(0x1D51B)
1795  of "Yfr": Rune(0x1D51C)
1796  of "afr": Rune(0x1D51E)
1797  of "bfr": Rune(0x1D51F)
1798  of "cfr": Rune(0x1D520)
1799  of "dfr": Rune(0x1D521)
1800  of "efr": Rune(0x1D522)
1801  of "ffr": Rune(0x1D523)
1802  of "gfr": Rune(0x1D524)
1803  of "hfr": Rune(0x1D525)
1804  of "ifr": Rune(0x1D526)
1805  of "jfr": Rune(0x1D527)
1806  of "kfr": Rune(0x1D528)
1807  of "lfr": Rune(0x1D529)
1808  of "mfr": Rune(0x1D52A)
1809  of "nfr": Rune(0x1D52B)
1810  of "ofr": Rune(0x1D52C)
1811  of "pfr": Rune(0x1D52D)
1812  of "qfr": Rune(0x1D52E)
1813  of "rfr": Rune(0x1D52F)
1814  of "sfr": Rune(0x1D530)
1815  of "tfr": Rune(0x1D531)
1816  of "ufr": Rune(0x1D532)
1817  of "vfr": Rune(0x1D533)
1818  of "wfr": Rune(0x1D534)
1819  of "xfr": Rune(0x1D535)
1820  of "yfr": Rune(0x1D536)
1821  of "zfr": Rune(0x1D537)
1822  of "Aopf": Rune(0x1D538)
1823  of "Bopf": Rune(0x1D539)
1824  of "Dopf": Rune(0x1D53B)
1825  of "Eopf": Rune(0x1D53C)
1826  of "Fopf": Rune(0x1D53D)
1827  of "Gopf": Rune(0x1D53E)
1828  of "Iopf": Rune(0x1D540)
1829  of "Jopf": Rune(0x1D541)
1830  of "Kopf": Rune(0x1D542)
1831  of "Lopf": Rune(0x1D543)
1832  of "Mopf": Rune(0x1D544)
1833  of "Oopf": Rune(0x1D546)
1834  of "Sopf": Rune(0x1D54A)
1835  of "Topf": Rune(0x1D54B)
1836  of "Uopf": Rune(0x1D54C)
1837  of "Vopf": Rune(0x1D54D)
1838  of "Wopf": Rune(0x1D54E)
1839  of "Xopf": Rune(0x1D54F)
1840  of "Yopf": Rune(0x1D550)
1841  of "aopf": Rune(0x1D552)
1842  of "bopf": Rune(0x1D553)
1843  of "copf": Rune(0x1D554)
1844  of "dopf": Rune(0x1D555)
1845  of "eopf": Rune(0x1D556)
1846  of "fopf": Rune(0x1D557)
1847  of "gopf": Rune(0x1D558)
1848  of "hopf": Rune(0x1D559)
1849  of "iopf": Rune(0x1D55A)
1850  of "jopf": Rune(0x1D55B)
1851  of "kopf": Rune(0x1D55C)
1852  of "lopf": Rune(0x1D55D)
1853  of "mopf": Rune(0x1D55E)
1854  of "nopf": Rune(0x1D55F)
1855  of "oopf": Rune(0x1D560)
1856  of "popf": Rune(0x1D561)
1857  of "qopf": Rune(0x1D562)
1858  of "ropf": Rune(0x1D563)
1859  of "sopf": Rune(0x1D564)
1860  of "topf": Rune(0x1D565)
1861  of "uopf": Rune(0x1D566)
1862  of "vopf": Rune(0x1D567)
1863  of "wopf": Rune(0x1D568)
1864  of "xopf": Rune(0x1D569)
1865  of "yopf": Rune(0x1D56A)
1866  of "zopf": Rune(0x1D56B)
1867  else: Rune(0)
1868
1869proc entityToUtf8*(entity: string): string =
1870  ## Converts an HTML entity name like `&Uuml;` or values like `&#220;`
1871  ## or `&#x000DC;` to its UTF-8 equivalent.
1872  ## "" is returned if the entity name is unknown. The HTML parser
1873  ## already converts entities to UTF-8.
1874  runnableExamples:
1875    const sigma = "Σ"
1876    doAssert entityToUtf8("") == ""
1877    doAssert entityToUtf8("a") == ""
1878    doAssert entityToUtf8("gt") == ">"
1879    doAssert entityToUtf8("Uuml") == "Ü"
1880    doAssert entityToUtf8("quest") == "?"
1881    doAssert entityToUtf8("#63") == "?"
1882    doAssert entityToUtf8("Sigma") == sigma
1883    doAssert entityToUtf8("#931") == sigma
1884    doAssert entityToUtf8("#0931") == sigma
1885    doAssert entityToUtf8("#x3A3") == sigma
1886    doAssert entityToUtf8("#x03A3") == sigma
1887    doAssert entityToUtf8("#x3a3") == sigma
1888    doAssert entityToUtf8("#X3a3") == sigma
1889  let rune = entityToRune(entity)
1890  if rune.ord <= 0: result = ""
1891  else: result = toUTF8(rune)
1892
1893proc addNode(father, son: XmlNode) =
1894  if son != nil: add(father, son)
1895
1896proc parse(x: var XmlParser, errors: var seq[string]): XmlNode {.gcsafe.}
1897
1898proc expected(x: var XmlParser, n: XmlNode): string =
1899  result = errorMsg(x, "</" & n.tag & "> expected")
1900
1901template elemName(x: untyped): untyped = rawData(x)
1902
1903template adderr(x: untyped) =
1904  errors.add(x)
1905
1906proc untilElementEnd(x: var XmlParser, result: XmlNode,
1907                     errors: var seq[string]) =
1908  # we parsed e.g. `<br>` and don't really expect a `</br>`:
1909  if result.htmlTag in SingleTags:
1910    if x.kind != xmlElementEnd or cmpIgnoreCase(x.elemName, result.tag) != 0:
1911      return
1912  while true:
1913    case x.kind
1914    of xmlElementStart, xmlElementOpen:
1915      case result.htmlTag
1916      of tagP, tagInput, tagOption:
1917        # some tags are common to have no `</end>`, like `<li>` but
1918        # allow `<p>` in `<dd>`, `<dt>` and `<li>` in next case
1919        if htmlTag(x.elemName) in {tagLi, tagP, tagDt, tagDd, tagInput,
1920                                   tagOption}:
1921          adderr(expected(x, result))
1922          break
1923      of tagDd, tagDt, tagLi:
1924        if htmlTag(x.elemName) in {tagLi, tagDt, tagDd, tagInput,
1925                                   tagOption}:
1926          adderr(expected(x, result))
1927          break
1928      of tagTd, tagTh:
1929        if htmlTag(x.elemName) in {tagTr, tagTd, tagTh, tagTfoot, tagThead}:
1930          adderr(expected(x, result))
1931          break
1932      of tagTr:
1933        if htmlTag(x.elemName) == tagTr:
1934          adderr(expected(x, result))
1935          break
1936      of tagOptgroup:
1937        if htmlTag(x.elemName) in {tagOption, tagOptgroup}:
1938          adderr(expected(x, result))
1939          break
1940      else: discard
1941      result.addNode(parse(x, errors))
1942    of xmlElementEnd:
1943      if cmpIgnoreCase(x.elemName, result.tag) != 0:
1944        #echo "5; expected: ", result.htmltag, " ", x.elemName
1945        adderr(expected(x, result))
1946        # this seems to do better match error corrections in browsers:
1947        while x.kind in {xmlElementEnd, xmlWhitespace}:
1948          if x.kind == xmlElementEnd and cmpIgnoreCase(x.elemName,
1949              result.tag) == 0:
1950            break
1951          next(x)
1952      next(x)
1953      break
1954    of xmlEof:
1955      adderr(expected(x, result))
1956      break
1957    else:
1958      result.addNode(parse(x, errors))
1959
1960proc parse(x: var XmlParser, errors: var seq[string]): XmlNode =
1961  case x.kind
1962  of xmlComment:
1963    result = newComment(x.rawData)
1964    next(x)
1965  of xmlCharData, xmlWhitespace:
1966    result = newText(x.rawData)
1967    next(x)
1968  of xmlPI, xmlSpecial:
1969    # we just ignore processing instructions for now
1970    next(x)
1971  of xmlError:
1972    adderr(errorMsg(x))
1973    next(x)
1974  of xmlElementStart:
1975    result = newElement(toLowerAscii(x.elemName))
1976    next(x)
1977    untilElementEnd(x, result, errors)
1978  of xmlElementEnd:
1979    adderr(errorMsg(x, "unexpected ending tag: " & x.elemName))
1980  of xmlElementOpen:
1981    result = newElement(toLowerAscii(x.elemName))
1982    next(x)
1983    result.attrs = newStringTable()
1984    while true:
1985      case x.kind
1986      of xmlAttribute:
1987        result.attrs[x.rawData] = x.rawData2
1988        next(x)
1989      of xmlElementClose:
1990        next(x)
1991        break
1992      of xmlError:
1993        adderr(errorMsg(x))
1994        next(x)
1995        break
1996      else:
1997        adderr(errorMsg(x, "'>' expected"))
1998        next(x)
1999        break
2000    untilElementEnd(x, result, errors)
2001  of xmlAttribute, xmlElementClose:
2002    adderr(errorMsg(x, "<some_tag> expected"))
2003    next(x)
2004  of xmlCData:
2005    result = newCData(x.rawData)
2006    next(x)
2007  of xmlEntity:
2008    var u = entityToUtf8(x.rawData)
2009    if u.len != 0: result = newText(u)
2010    next(x)
2011  of xmlEof: discard
2012
2013proc parseHtml*(s: Stream, filename: string,
2014                errors: var seq[string]): XmlNode =
2015  ## Parses the XML from stream `s` and returns a `XmlNode`. Every
2016  ## occurred parsing error is added to the `errors` sequence.
2017  var x: XmlParser
2018  open(x, s, filename, {reportComments, reportWhitespace, allowUnquotedAttribs,
2019    allowEmptyAttribs})
2020  next(x)
2021  # skip the DOCTYPE:
2022  if x.kind == xmlSpecial: next(x)
2023
2024  result = newElement("document")
2025  result.addNode(parse(x, errors))
2026  #if x.kind != xmlEof:
2027  #  adderr(errorMsg(x, "EOF expected"))
2028  while x.kind != xmlEof:
2029    var oldPos = x.bufpos # little hack to see if we made any progress
2030    result.addNode(parse(x, errors))
2031    if x.bufpos == oldPos:
2032      # force progress!
2033      next(x)
2034  close(x)
2035  if result.len == 1:
2036    result = result[0]
2037
2038proc parseHtml*(s: Stream): XmlNode =
2039  ## Parses the HTML from stream `s` and returns a `XmlNode`. All parsing
2040  ## errors are ignored.
2041  var errors: seq[string] = @[]
2042  result = parseHtml(s, "unknown_html_doc", errors)
2043
2044proc parseHtml*(html: string): XmlNode =
2045  ## Parses the HTML from string `html` and returns a `XmlNode`. All parsing
2046  ## errors are ignored.
2047  parseHtml(newStringStream(html))
2048
2049proc loadHtml*(path: string, errors: var seq[string]): XmlNode =
2050  ## Loads and parses HTML from file specified by `path`, and returns
2051  ## a `XmlNode`. Every occurred parsing error is added to
2052  ## the `errors` sequence.
2053  var s = newFileStream(path, fmRead)
2054  if s == nil: raise newException(IOError, "Unable to read file: " & path)
2055  result = parseHtml(s, path, errors)
2056
2057proc loadHtml*(path: string): XmlNode =
2058  ## Loads and parses HTML from file specified by `path`, and returns
2059  ## a `XmlNode`. All parsing errors are ignored.
2060  var errors: seq[string] = @[]
2061  result = loadHtml(path, errors)
2062
2063when not defined(testing) and isMainModule:
2064  import os
2065
2066  var errors: seq[string] = @[]
2067  var x = loadHtml(paramStr(1), errors)
2068  for e in items(errors): echo e
2069
2070  var f: File
2071  if open(f, "test.txt", fmWrite):
2072    f.write($x)
2073    f.close()
2074  else:
2075    quit("cannot write test.txt")
2076