├── .gitignore ├── .gitmodules ├── CHANGELOG.md ├── LICENSE ├── README.md ├── build.zig ├── gyro.zzz ├── src ├── lib.zig ├── namedCharacterReference.zig ├── node.zig ├── parse_error.zig ├── parser.zig ├── token.zig └── tokenizer.zig └── test └── tokenizer-html5lib.zig /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /zig-cache 3 | /.vscode -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "test/html5lib-tests"] 2 | path = test/html5lib-tests 3 | url = https://github.com/html5lib/html5lib-tests.git 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 0.2.0 4 | 5 | Updated for Zig 0.10.0 6 | 7 | ## 0.1.0 8 | 9 | Mostly spec compliant HTML parser implementaiton in Zig -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2022 Chris Watson 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Z-HTML 2 | 3 | This is a work in progress, spec compliant, HTML parser built with [Zig](https://ziglang.org). Currently lots of things are broken. You can check the status of tests that _are not_ passing by checking out the `ignored_tests` in [test/tokenizer-html5lib.zig](test/tokenizer-html5lib.zig). 4 | 5 | ## Roadmap 6 | 7 | - [x] Tokenizer (missing a few edge cases) 8 | - [ ] Parser (in progress) 9 | - [ ] JavaScript DOM API support 10 | 11 | See the [CHANGELOG.md](changelog) for detailed information on past changes. 12 | 13 | ## Tokenizer 14 | 15 | The `Tokenizer` struct provides a (mostly) fully featured HTML tokenizer built according to the [WHATGW HTML Spec](https://html.spec.whatwg.org/multipage/parsing.html#tokenization). It is a streaming tokenizer which takes as input a full document, processes the document character by character, and emits both `Token`s and `ParseError`s. An example usage of it by itself could look like this: 16 | 17 | ```zig 18 | const std = @import("std"); 19 | const Tokenizer = @import("zhtml/tokenizer.zig").Tokenizer; 20 | 21 | pub fn main() void { 22 | var allocator = std.heap.page_allocator; 23 | var tokenizer = try Tokenizer.initWithFile(alloc, "./test.html"); 24 | while (true) { 25 | var token = self.tokenizer.nextToken() catch |err| { 26 | std.debug.warn("{} (line: {}, column: {})\n", .{ err, tokenizer.line, tokenizer.column }); 27 | continue; 28 | }; 29 | 30 | if (token) |tok| { 31 | switch (tok) { 32 | Token.EndOfFile => break, 33 | else => std.debug.warn("{}\n", .{ tok }); 34 | } 35 | } 36 | } 37 | } 38 | ``` 39 | 40 | though the `Tokenizer` is meant to be used in conjunction with the `Parser`. 41 | 42 | ## Parser 43 | 44 | Work in progress. Check back later. 45 | 46 | ## License 47 | 48 | Copyright 2022 Chris Watson 49 | 50 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 51 | 52 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 53 | 54 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 55 | -------------------------------------------------------------------------------- /build.zig: -------------------------------------------------------------------------------- 1 | const Builder = @import("std").build.Builder; 2 | 3 | pub fn build(b: *Builder) void { 4 | // Standard target options allows the person running `zig build` to choose 5 | // what target to build for. Here we do not override the defaults, which 6 | // means any target is allowed, and the default is native. Other options 7 | // for restricting supported target set are available. 8 | const target = b.standardTargetOptions(.{}); 9 | 10 | // Standard release options allow the person running `zig build` to select 11 | // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. 12 | const mode = b.standardReleaseOptions(); 13 | 14 | const exe = b.addExecutable("build", "src/main.zig"); 15 | exe.setTarget(target); 16 | exe.setBuildMode(mode); 17 | exe.install(); 18 | 19 | const run_cmd = exe.run(); 20 | run_cmd.step.dependOn(b.getInstallStep()); 21 | 22 | const run_step = b.step("run", "Run the app"); 23 | run_step.dependOn(&run_cmd.step); 24 | 25 | var html5lib_tests = b.addTest("test/tokenizer-html5lib.zig"); 26 | html5lib_tests.setBuildMode(mode); 27 | html5lib_tests.addPackagePath("zhtml/token", "src/token.zig"); 28 | html5lib_tests.addPackagePath("zhtml/parse_error", "src/parse_error.zig"); 29 | html5lib_tests.addPackagePath("zhtml/tokenizer", "src/tokenizer.zig"); 30 | const html5lib_test_step = b.step("test-html5lib", "Run the tests from html5lib/html5lib-tests"); 31 | html5lib_test_step.dependOn(&html5lib_tests.step); 32 | } 33 | 34 | // pub fn build(b: *Builder) void { 35 | // const mode = b.standardReleaseOptions(); 36 | // const lib = b.addStaticLibrary("zhtml", "src/main.zig"); 37 | // lib.setBuildMode(mode); 38 | // lib.install(); 39 | 40 | // var main_tests = b.addTest("src/main.zig"); 41 | // main_tests.setBuildMode(mode); 42 | 43 | // const test_step = b.step("test", "Run library tests"); 44 | // test_step.dependOn(&main_tests.step); 45 | // } 46 | -------------------------------------------------------------------------------- /gyro.zzz: -------------------------------------------------------------------------------- 1 | pkgs: 2 | zhtml: 3 | version: 0.2.0 4 | root: src/lib.zig 5 | description: A work in progress, spec compliant, HTML parser built with Zig 6 | license: MIT 7 | homepage_url: https://github.com/watzon/zhtml 8 | source_url: https://github.com/watzon/zhtml 9 | 10 | tags: 11 | - html 12 | - parser 13 | - whatwg 14 | - w3 15 | 16 | files: 17 | - LICENSE 18 | - README.md 19 | - build.zig 20 | - src/*.zig 21 | -------------------------------------------------------------------------------- /src/lib.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | pub const node = @import("node.zig"); 3 | pub const Token = @import("token.zig").Token; 4 | pub const Parser = @import("parser.zig").Parser; 5 | pub const Tokenizer = @import("tokenizer.zig").Tokenizer; 6 | pub const ParseError = @import("parse_error.zig").ParseError; 7 | -------------------------------------------------------------------------------- /src/namedCharacterReference.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const StringHashMap = std.StringHashMap; 3 | 4 | pub fn buildNamedCharacterReferenceTable(allocator: *std.mem.Allocator) StringHashMap([]const u8) { 5 | @setEvalBranchQuota(3000); 6 | 7 | const pairs = .{ 8 | .{"GT", ">"}, 9 | .{"gt", ">"}, 10 | .{"LT", "<"}, 11 | .{"lt", "<"}, 12 | .{"ac;", "∾"}, 13 | .{"af;", "⁡"}, 14 | .{"AMP", "&"}, 15 | .{"amp", "&"}, 16 | .{"ap;", "≈"}, 17 | .{"DD;", "ⅅ"}, 18 | .{"dd;", "ⅆ"}, 19 | .{"deg", "°"}, 20 | .{"ee;", "ⅇ"}, 21 | .{"eg;", "⪚"}, 22 | .{"el;", "⪙"}, 23 | .{"ETH", "Ð"}, 24 | .{"eth", "ð"}, 25 | .{"gE;", "≧"}, 26 | .{"ge;", "≥"}, 27 | .{"Gg;", "⋙"}, 28 | .{"gg;", "≫"}, 29 | .{"gl;", "≷"}, 30 | .{"GT;", ">"}, 31 | .{"Gt;", "≫"}, 32 | .{"gt;", ">"}, 33 | .{"ic;", "⁣"}, 34 | .{"ii;", "ⅈ"}, 35 | .{"Im;", "ℑ"}, 36 | .{"in;", "∈"}, 37 | .{"it;", "⁢"}, 38 | .{"lE;", "≦"}, 39 | .{"le;", "≤"}, 40 | .{"lg;", "≶"}, 41 | .{"Ll;", "⋘"}, 42 | .{"ll;", "≪"}, 43 | .{"LT;", "<"}, 44 | .{"Lt;", "≪"}, 45 | .{"lt;", "<"}, 46 | .{"mp;", "∓"}, 47 | .{"Mu;", "Μ"}, 48 | .{"mu;", "μ"}, 49 | .{"ne;", "≠"}, 50 | .{"ni;", "∋"}, 51 | .{"not", "¬"}, 52 | .{"Nu;", "Ν"}, 53 | .{"nu;", "ν"}, 54 | .{"Or;", "⩔"}, 55 | .{"or;", "∨"}, 56 | .{"oS;", "Ⓢ"}, 57 | .{"Pi;", "Π"}, 58 | .{"pi;", "π"}, 59 | .{"pm;", "±"}, 60 | .{"Pr;", "⪻"}, 61 | .{"pr;", "≺"}, 62 | .{"Re;", "ℜ"}, 63 | .{"REG", "®"}, 64 | .{"reg", "®"}, 65 | .{"rx;", "℞"}, 66 | .{"Sc;", "⪼"}, 67 | .{"sc;", "≻"}, 68 | .{"shy", "­"}, 69 | .{"uml", "¨"}, 70 | .{"wp;", "℘"}, 71 | .{"wr;", "≀"}, 72 | .{"Xi;", "Ξ"}, 73 | .{"xi;", "ξ"}, 74 | .{"yen", "¥"}, 75 | .{"acd;", "∿"}, 76 | .{"acE;", "∾̳"}, 77 | .{"Acy;", "А"}, 78 | .{"acy;", "а"}, 79 | .{"Afr;", "𝔄"}, 80 | .{"afr;", "𝔞"}, 81 | .{"AMP;", "&"}, 82 | .{"amp;", "&"}, 83 | .{"And;", "⩓"}, 84 | .{"and;", "∧"}, 85 | .{"ang;", "∠"}, 86 | .{"apE;", "⩰"}, 87 | .{"ape;", "≊"}, 88 | .{"ast;", "*"}, 89 | .{"Auml", "Ä"}, 90 | .{"auml", "ä"}, 91 | .{"Bcy;", "Б"}, 92 | .{"bcy;", "б"}, 93 | .{"Bfr;", "𝔅"}, 94 | .{"bfr;", "𝔟"}, 95 | .{"bne;", "=⃥"}, 96 | .{"bot;", "⊥"}, 97 | .{"Cap;", "⋒"}, 98 | .{"cap;", "∩"}, 99 | .{"cent", "¢"}, 100 | .{"Cfr;", "ℭ"}, 101 | .{"cfr;", "𝔠"}, 102 | .{"Chi;", "Χ"}, 103 | .{"chi;", "χ"}, 104 | .{"cir;", "○"}, 105 | .{"COPY", "©"}, 106 | .{"copy", "©"}, 107 | .{"Cup;", "⋓"}, 108 | .{"cup;", "∪"}, 109 | .{"Dcy;", "Д"}, 110 | .{"dcy;", "д"}, 111 | .{"deg;", "°"}, 112 | .{"Del;", "∇"}, 113 | .{"Dfr;", "𝔇"}, 114 | .{"dfr;", "𝔡"}, 115 | .{"die;", "¨"}, 116 | .{"div;", "÷"}, 117 | .{"Dot;", "¨"}, 118 | .{"dot;", "˙"}, 119 | .{"Ecy;", "Э"}, 120 | .{"ecy;", "э"}, 121 | .{"Efr;", "𝔈"}, 122 | .{"efr;", "𝔢"}, 123 | .{"egs;", "⪖"}, 124 | .{"ell;", "ℓ"}, 125 | .{"els;", "⪕"}, 126 | .{"ENG;", "Ŋ"}, 127 | .{"eng;", "ŋ"}, 128 | .{"Eta;", "Η"}, 129 | .{"eta;", "η"}, 130 | .{"ETH;", "Ð"}, 131 | .{"eth;", "ð"}, 132 | .{"Euml", "Ë"}, 133 | .{"euml", "ë"}, 134 | .{"Fcy;", "Ф"}, 135 | .{"fcy;", "ф"}, 136 | .{"Ffr;", "𝔉"}, 137 | .{"ffr;", "𝔣"}, 138 | .{"gap;", "⪆"}, 139 | .{"Gcy;", "Г"}, 140 | .{"gcy;", "г"}, 141 | .{"gEl;", "⪌"}, 142 | .{"gel;", "⋛"}, 143 | .{"geq;", "≥"}, 144 | .{"ges;", "⩾"}, 145 | .{"Gfr;", "𝔊"}, 146 | .{"gfr;", "𝔤"}, 147 | .{"ggg;", "⋙"}, 148 | .{"gla;", "⪥"}, 149 | .{"glE;", "⪒"}, 150 | .{"glj;", "⪤"}, 151 | .{"gnE;", "≩"}, 152 | .{"gne;", "⪈"}, 153 | .{"Hat;", "^"}, 154 | .{"Hfr;", "ℌ"}, 155 | .{"hfr;", "𝔥"}, 156 | .{"Icy;", "И"}, 157 | .{"icy;", "и"}, 158 | .{"iff;", "⇔"}, 159 | .{"Ifr;", "ℑ"}, 160 | .{"ifr;", "𝔦"}, 161 | .{"Int;", "∬"}, 162 | .{"int;", "∫"}, 163 | .{"Iuml", "Ï"}, 164 | .{"iuml", "ï"}, 165 | .{"Jcy;", "Й"}, 166 | .{"jcy;", "й"}, 167 | .{"Jfr;", "𝔍"}, 168 | .{"jfr;", "𝔧"}, 169 | .{"Kcy;", "К"}, 170 | .{"kcy;", "к"}, 171 | .{"Kfr;", "𝔎"}, 172 | .{"kfr;", "𝔨"}, 173 | .{"lap;", "⪅"}, 174 | .{"lat;", "⪫"}, 175 | .{"Lcy;", "Л"}, 176 | .{"lcy;", "л"}, 177 | .{"lEg;", "⪋"}, 178 | .{"leg;", "⋚"}, 179 | .{"leq;", "≤"}, 180 | .{"les;", "⩽"}, 181 | .{"Lfr;", "𝔏"}, 182 | .{"lfr;", "𝔩"}, 183 | .{"lgE;", "⪑"}, 184 | .{"lnE;", "≨"}, 185 | .{"lne;", "⪇"}, 186 | .{"loz;", "◊"}, 187 | // .{"lrm;", "‎"}, 188 | .{"Lsh;", "↰"}, 189 | .{"lsh;", "↰"}, 190 | .{"macr", "¯"}, 191 | .{"Map;", "⤅"}, 192 | .{"map;", "↦"}, 193 | .{"Mcy;", "М"}, 194 | .{"mcy;", "м"}, 195 | .{"Mfr;", "𝔐"}, 196 | .{"mfr;", "𝔪"}, 197 | .{"mho;", "℧"}, 198 | .{"mid;", "∣"}, 199 | .{"nap;", "≉"}, 200 | .{"nbsp", " "}, 201 | .{"Ncy;", "Н"}, 202 | .{"ncy;", "н"}, 203 | .{"Nfr;", "𝔑"}, 204 | .{"nfr;", "𝔫"}, 205 | .{"ngE;", "≧̸"}, 206 | .{"nge;", "≱"}, 207 | .{"nGg;", "⋙̸"}, 208 | .{"nGt;", "≫⃒"}, 209 | .{"ngt;", "≯"}, 210 | .{"nis;", "⋼"}, 211 | .{"niv;", "∋"}, 212 | .{"nlE;", "≦̸"}, 213 | .{"nle;", "≰"}, 214 | .{"nLl;", "⋘̸"}, 215 | .{"nLt;", "≪⃒"}, 216 | .{"nlt;", "≮"}, 217 | .{"Not;", "⫬"}, 218 | .{"not;", "¬"}, 219 | .{"npr;", "⊀"}, 220 | .{"nsc;", "⊁"}, 221 | .{"num;", "#"}, 222 | .{"Ocy;", "О"}, 223 | .{"ocy;", "о"}, 224 | .{"Ofr;", "𝔒"}, 225 | .{"ofr;", "𝔬"}, 226 | .{"ogt;", "⧁"}, 227 | .{"ohm;", "Ω"}, 228 | .{"olt;", "⧀"}, 229 | .{"ord;", "⩝"}, 230 | .{"ordf", "ª"}, 231 | .{"ordm", "º"}, 232 | .{"orv;", "⩛"}, 233 | .{"Ouml", "Ö"}, 234 | .{"ouml", "ö"}, 235 | .{"par;", "∥"}, 236 | .{"para", "¶"}, 237 | .{"Pcy;", "П"}, 238 | .{"pcy;", "п"}, 239 | .{"Pfr;", "𝔓"}, 240 | .{"pfr;", "𝔭"}, 241 | .{"Phi;", "Φ"}, 242 | .{"phi;", "φ"}, 243 | .{"piv;", "ϖ"}, 244 | .{"prE;", "⪳"}, 245 | .{"pre;", "⪯"}, 246 | .{"Psi;", "Ψ"}, 247 | .{"psi;", "ψ"}, 248 | .{"Qfr;", "𝔔"}, 249 | .{"qfr;", "𝔮"}, 250 | .{"QUOT", "\""}, 251 | .{"quot", "\""}, 252 | .{"Rcy;", "Р"}, 253 | .{"rcy;", "р"}, 254 | .{"REG;", "®"}, 255 | .{"reg;", "®"}, 256 | .{"Rfr;", "ℜ"}, 257 | .{"rfr;", "𝔯"}, 258 | .{"Rho;", "Ρ"}, 259 | .{"rho;", "ρ"}, 260 | // .{"rlm;", "‏"}, 261 | .{"Rsh;", "↱"}, 262 | .{"rsh;", "↱"}, 263 | .{"scE;", "⪴"}, 264 | .{"sce;", "⪰"}, 265 | .{"Scy;", "С"}, 266 | .{"scy;", "с"}, 267 | .{"sect", "§"}, 268 | .{"Sfr;", "𝔖"}, 269 | .{"sfr;", "𝔰"}, 270 | .{"shy;", "­"}, 271 | .{"sim;", "∼"}, 272 | .{"smt;", "⪪"}, 273 | .{"sol;", "/"}, 274 | .{"squ;", "□"}, 275 | .{"Sub;", "⋐"}, 276 | .{"sub;", "⊂"}, 277 | .{"Sum;", "∑"}, 278 | .{"sum;", "∑"}, 279 | .{"Sup;", "⋑"}, 280 | .{"sup;", "⊃"}, 281 | .{"sup1", "¹"}, 282 | .{"sup2", "²"}, 283 | .{"sup3", "³"}, 284 | .{"Tab;", " "}, 285 | .{"Tau;", "Τ"}, 286 | .{"tau;", "τ"}, 287 | .{"Tcy;", "Т"}, 288 | .{"tcy;", "т"}, 289 | .{"Tfr;", "𝔗"}, 290 | .{"tfr;", "𝔱"}, 291 | .{"top;", "⊤"}, 292 | .{"Ucy;", "У"}, 293 | .{"ucy;", "у"}, 294 | .{"Ufr;", "𝔘"}, 295 | .{"ufr;", "𝔲"}, 296 | .{"uml;", "¨"}, 297 | .{"Uuml", "Ü"}, 298 | .{"uuml", "ü"}, 299 | .{"Vcy;", "В"}, 300 | .{"vcy;", "в"}, 301 | .{"Vee;", "⋁"}, 302 | .{"vee;", "∨"}, 303 | .{"Vfr;", "𝔙"}, 304 | .{"vfr;", "𝔳"}, 305 | .{"Wfr;", "𝔚"}, 306 | .{"wfr;", "𝔴"}, 307 | .{"Xfr;", "𝔛"}, 308 | .{"xfr;", "𝔵"}, 309 | .{"Ycy;", "Ы"}, 310 | .{"ycy;", "ы"}, 311 | .{"yen;", "¥"}, 312 | .{"Yfr;", "𝔜"}, 313 | .{"yfr;", "𝔶"}, 314 | .{"yuml", "ÿ"}, 315 | .{"Zcy;", "З"}, 316 | .{"zcy;", "з"}, 317 | .{"Zfr;", "ℨ"}, 318 | .{"zfr;", "𝔷"}, 319 | .{"zwj;", "‍"}, 320 | .{"Acirc", "Â"}, 321 | .{"acirc", "â"}, 322 | .{"acute", "´"}, 323 | .{"AElig", "Æ"}, 324 | .{"aelig", "æ"}, 325 | .{"andd;", "⩜"}, 326 | .{"andv;", "⩚"}, 327 | .{"ange;", "⦤"}, 328 | .{"Aopf;", "𝔸"}, 329 | .{"aopf;", "𝕒"}, 330 | .{"apid;", "≋"}, 331 | .{"apos;", "'"}, 332 | .{"Aring", "Å"}, 333 | .{"aring", "å"}, 334 | .{"Ascr;", "𝒜"}, 335 | .{"ascr;", "𝒶"}, 336 | .{"Auml;", "Ä"}, 337 | .{"auml;", "ä"}, 338 | .{"Barv;", "⫧"}, 339 | .{"bbrk;", "⎵"}, 340 | .{"Beta;", "Β"}, 341 | .{"beta;", "β"}, 342 | .{"beth;", "ℶ"}, 343 | .{"bNot;", "⫭"}, 344 | .{"bnot;", "⌐"}, 345 | .{"Bopf;", "𝔹"}, 346 | .{"bopf;", "𝕓"}, 347 | .{"boxH;", "═"}, 348 | .{"boxh;", "─"}, 349 | .{"boxV;", "║"}, 350 | .{"boxv;", "│"}, 351 | .{"Bscr;", "ℬ"}, 352 | .{"bscr;", "𝒷"}, 353 | .{"bsim;", "∽"}, 354 | .{"bsol;", "\\"}, 355 | .{"bull;", "•"}, 356 | .{"bump;", "≎"}, 357 | .{"caps;", "∩︀"}, 358 | .{"Cdot;", "Ċ"}, 359 | .{"cdot;", "ċ"}, 360 | .{"cedil", "¸"}, 361 | .{"cent;", "¢"}, 362 | .{"CHcy;", "Ч"}, 363 | .{"chcy;", "ч"}, 364 | .{"circ;", "ˆ"}, 365 | .{"cirE;", "⧃"}, 366 | .{"cire;", "≗"}, 367 | .{"comp;", "∁"}, 368 | .{"cong;", "≅"}, 369 | .{"Copf;", "ℂ"}, 370 | .{"copf;", "𝕔"}, 371 | .{"COPY;", "©"}, 372 | .{"copy;", "©"}, 373 | .{"Cscr;", "𝒞"}, 374 | .{"cscr;", "𝒸"}, 375 | .{"csub;", "⫏"}, 376 | .{"csup;", "⫐"}, 377 | .{"cups;", "∪︀"}, 378 | .{"Darr;", "↡"}, 379 | .{"dArr;", "⇓"}, 380 | .{"darr;", "↓"}, 381 | .{"dash;", "‐"}, 382 | .{"dHar;", "⥥"}, 383 | .{"diam;", "⋄"}, 384 | .{"DJcy;", "Ђ"}, 385 | .{"djcy;", "ђ"}, 386 | .{"Dopf;", "𝔻"}, 387 | .{"dopf;", "𝕕"}, 388 | .{"Dscr;", "𝒟"}, 389 | .{"dscr;", "𝒹"}, 390 | .{"DScy;", "Ѕ"}, 391 | .{"dscy;", "ѕ"}, 392 | .{"dsol;", "⧶"}, 393 | .{"dtri;", "▿"}, 394 | .{"DZcy;", "Џ"}, 395 | .{"dzcy;", "џ"}, 396 | .{"ecir;", "≖"}, 397 | .{"Ecirc", "Ê"}, 398 | .{"ecirc", "ê"}, 399 | .{"Edot;", "Ė"}, 400 | .{"eDot;", "≑"}, 401 | .{"edot;", "ė"}, 402 | .{"emsp;", " "}, 403 | .{"ensp;", " "}, 404 | .{"Eopf;", "𝔼"}, 405 | .{"eopf;", "𝕖"}, 406 | .{"epar;", "⋕"}, 407 | .{"epsi;", "ε"}, 408 | .{"Escr;", "ℰ"}, 409 | .{"escr;", "ℯ"}, 410 | .{"Esim;", "⩳"}, 411 | .{"esim;", "≂"}, 412 | .{"Euml;", "Ë"}, 413 | .{"euml;", "ë"}, 414 | .{"euro;", "€"}, 415 | .{"excl;", "!"}, 416 | .{"flat;", "♭"}, 417 | .{"fnof;", "ƒ"}, 418 | .{"Fopf;", "𝔽"}, 419 | .{"fopf;", "𝕗"}, 420 | .{"fork;", "⋔"}, 421 | .{"Fscr;", "ℱ"}, 422 | .{"fscr;", "𝒻"}, 423 | .{"Gdot;", "Ġ"}, 424 | .{"gdot;", "ġ"}, 425 | .{"geqq;", "≧"}, 426 | .{"gesl;", "⋛︀"}, 427 | .{"GJcy;", "Ѓ"}, 428 | .{"gjcy;", "ѓ"}, 429 | .{"gnap;", "⪊"}, 430 | .{"gneq;", "⪈"}, 431 | .{"Gopf;", "𝔾"}, 432 | .{"gopf;", "𝕘"}, 433 | .{"Gscr;", "𝒢"}, 434 | .{"gscr;", "ℊ"}, 435 | .{"gsim;", "≳"}, 436 | .{"gtcc;", "⪧"}, 437 | .{"gvnE;", "≩︀"}, 438 | .{"half;", "½"}, 439 | .{"hArr;", "⇔"}, 440 | .{"harr;", "↔"}, 441 | .{"hbar;", "ℏ"}, 442 | .{"Hopf;", "ℍ"}, 443 | .{"hopf;", "𝕙"}, 444 | .{"Hscr;", "ℋ"}, 445 | .{"hscr;", "𝒽"}, 446 | .{"Icirc", "Î"}, 447 | .{"icirc", "î"}, 448 | .{"Idot;", "İ"}, 449 | .{"IEcy;", "Е"}, 450 | .{"iecy;", "е"}, 451 | .{"iexcl", "¡"}, 452 | .{"imof;", "⊷"}, 453 | .{"IOcy;", "Ё"}, 454 | .{"iocy;", "ё"}, 455 | .{"Iopf;", "𝕀"}, 456 | .{"iopf;", "𝕚"}, 457 | .{"Iota;", "Ι"}, 458 | .{"iota;", "ι"}, 459 | .{"Iscr;", "ℐ"}, 460 | .{"iscr;", "𝒾"}, 461 | .{"isin;", "∈"}, 462 | .{"Iuml;", "Ï"}, 463 | .{"iuml;", "ï"}, 464 | .{"Jopf;", "𝕁"}, 465 | .{"jopf;", "𝕛"}, 466 | .{"Jscr;", "𝒥"}, 467 | .{"jscr;", "𝒿"}, 468 | .{"KHcy;", "Х"}, 469 | .{"khcy;", "х"}, 470 | .{"KJcy;", "Ќ"}, 471 | .{"kjcy;", "ќ"}, 472 | .{"Kopf;", "𝕂"}, 473 | .{"kopf;", "𝕜"}, 474 | .{"Kscr;", "𝒦"}, 475 | .{"kscr;", "𝓀"}, 476 | .{"Lang;", "⟪"}, 477 | .{"lang;", "⟨"}, 478 | .{"laquo", "«"}, 479 | .{"Larr;", "↞"}, 480 | .{"lArr;", "⇐"}, 481 | .{"larr;", "←"}, 482 | .{"late;", "⪭"}, 483 | .{"lcub;", "{"}, 484 | .{"ldca;", "⤶"}, 485 | .{"ldsh;", "↲"}, 486 | .{"leqq;", "≦"}, 487 | .{"lesg;", "⋚︀"}, 488 | .{"lHar;", "⥢"}, 489 | .{"LJcy;", "Љ"}, 490 | .{"ljcy;", "љ"}, 491 | .{"lnap;", "⪉"}, 492 | .{"lneq;", "⪇"}, 493 | .{"Lopf;", "𝕃"}, 494 | .{"lopf;", "𝕝"}, 495 | .{"lozf;", "⧫"}, 496 | .{"lpar;", "("}, 497 | .{"Lscr;", "ℒ"}, 498 | .{"lscr;", "𝓁"}, 499 | .{"lsim;", "≲"}, 500 | .{"lsqb;", "["}, 501 | .{"ltcc;", "⪦"}, 502 | .{"ltri;", "◃"}, 503 | .{"lvnE;", "≨︀"}, 504 | .{"macr;", "¯"}, 505 | .{"male;", "♂"}, 506 | .{"malt;", "✠"}, 507 | .{"micro", "µ"}, 508 | .{"mlcp;", "⫛"}, 509 | .{"mldr;", "…"}, 510 | .{"Mopf;", "𝕄"}, 511 | .{"mopf;", "𝕞"}, 512 | .{"Mscr;", "ℳ"}, 513 | .{"mscr;", "𝓂"}, 514 | .{"nang;", "∠⃒"}, 515 | .{"napE;", "⩰̸"}, 516 | .{"nbsp;", " "}, 517 | .{"ncap;", "⩃"}, 518 | .{"ncup;", "⩂"}, 519 | .{"ngeq;", "≱"}, 520 | .{"nges;", "⩾̸"}, 521 | .{"ngtr;", "≯"}, 522 | .{"nGtv;", "≫̸"}, 523 | .{"nisd;", "⋺"}, 524 | .{"NJcy;", "Њ"}, 525 | .{"njcy;", "њ"}, 526 | .{"nldr;", "‥"}, 527 | .{"nleq;", "≰"}, 528 | .{"nles;", "⩽̸"}, 529 | .{"nLtv;", "≪̸"}, 530 | .{"nmid;", "∤"}, 531 | .{"Nopf;", "ℕ"}, 532 | .{"nopf;", "𝕟"}, 533 | .{"npar;", "∦"}, 534 | .{"npre;", "⪯̸"}, 535 | .{"nsce;", "⪰̸"}, 536 | .{"Nscr;", "𝒩"}, 537 | .{"nscr;", "𝓃"}, 538 | .{"nsim;", "≁"}, 539 | .{"nsub;", "⊄"}, 540 | .{"nsup;", "⊅"}, 541 | .{"ntgl;", "≹"}, 542 | .{"ntlg;", "≸"}, 543 | .{"nvap;", "≍⃒"}, 544 | .{"nvge;", "≥⃒"}, 545 | .{"nvgt;", ">⃒"}, 546 | .{"nvle;", "≤⃒"}, 547 | .{"nvlt;", "<⃒"}, 548 | .{"oast;", "⊛"}, 549 | .{"ocir;", "⊚"}, 550 | .{"Ocirc", "Ô"}, 551 | .{"ocirc", "ô"}, 552 | .{"odiv;", "⨸"}, 553 | .{"odot;", "⊙"}, 554 | .{"ogon;", "˛"}, 555 | .{"oint;", "∮"}, 556 | .{"omid;", "⦶"}, 557 | .{"Oopf;", "𝕆"}, 558 | .{"oopf;", "𝕠"}, 559 | .{"opar;", "⦷"}, 560 | .{"ordf;", "ª"}, 561 | .{"ordm;", "º"}, 562 | .{"oror;", "⩖"}, 563 | .{"Oscr;", "𝒪"}, 564 | .{"oscr;", "ℴ"}, 565 | .{"osol;", "⊘"}, 566 | .{"Ouml;", "Ö"}, 567 | .{"ouml;", "ö"}, 568 | .{"para;", "¶"}, 569 | .{"part;", "∂"}, 570 | .{"perp;", "⊥"}, 571 | .{"phiv;", "ϕ"}, 572 | .{"plus;", "+"}, 573 | .{"Popf;", "ℙ"}, 574 | .{"popf;", "𝕡"}, 575 | .{"pound", "£"}, 576 | .{"prap;", "⪷"}, 577 | .{"prec;", "≺"}, 578 | .{"prnE;", "⪵"}, 579 | .{"prod;", "∏"}, 580 | .{"prop;", "∝"}, 581 | .{"Pscr;", "𝒫"}, 582 | .{"pscr;", "𝓅"}, 583 | .{"qint;", "⨌"}, 584 | .{"Qopf;", "ℚ"}, 585 | .{"qopf;", "𝕢"}, 586 | .{"Qscr;", "𝒬"}, 587 | .{"qscr;", "𝓆"}, 588 | .{"QUOT;", "\""}, 589 | .{"quot;", "\""}, 590 | .{"race;", "∽̱"}, 591 | .{"Rang;", "⟫"}, 592 | .{"rang;", "⟩"}, 593 | .{"raquo", "»"}, 594 | .{"Rarr;", "↠"}, 595 | .{"rArr;", "⇒"}, 596 | .{"rarr;", "→"}, 597 | .{"rcub;", "}"}, 598 | .{"rdca;", "⤷"}, 599 | .{"rdsh;", "↳"}, 600 | .{"real;", "ℜ"}, 601 | .{"rect;", "▭"}, 602 | .{"rHar;", "⥤"}, 603 | .{"rhov;", "ϱ"}, 604 | .{"ring;", "˚"}, 605 | .{"Ropf;", "ℝ"}, 606 | .{"ropf;", "𝕣"}, 607 | .{"rpar;", ")"}, 608 | .{"Rscr;", "ℛ"}, 609 | .{"rscr;", "𝓇"}, 610 | .{"rsqb;", "]"}, 611 | .{"rtri;", "▹"}, 612 | .{"scap;", "⪸"}, 613 | .{"scnE;", "⪶"}, 614 | .{"sdot;", "⋅"}, 615 | .{"sect;", "§"}, 616 | .{"semi;", ";"}, 617 | .{"sext;", "✶"}, 618 | .{"SHcy;", "Ш"}, 619 | .{"shcy;", "ш"}, 620 | .{"sime;", "≃"}, 621 | .{"simg;", "⪞"}, 622 | .{"siml;", "⪝"}, 623 | .{"smid;", "∣"}, 624 | .{"smte;", "⪬"}, 625 | .{"solb;", "⧄"}, 626 | .{"Sopf;", "𝕊"}, 627 | .{"sopf;", "𝕤"}, 628 | .{"spar;", "∥"}, 629 | .{"Sqrt;", "√"}, 630 | .{"squf;", "▪"}, 631 | .{"Sscr;", "𝒮"}, 632 | .{"sscr;", "𝓈"}, 633 | .{"Star;", "⋆"}, 634 | .{"star;", "☆"}, 635 | .{"subE;", "⫅"}, 636 | .{"sube;", "⊆"}, 637 | .{"succ;", "≻"}, 638 | .{"sung;", "♪"}, 639 | .{"sup1;", "¹"}, 640 | .{"sup2;", "²"}, 641 | .{"sup3;", "³"}, 642 | .{"supE;", "⫆"}, 643 | .{"supe;", "⊇"}, 644 | .{"szlig", "ß"}, 645 | .{"tbrk;", "⎴"}, 646 | .{"tdot;", "⃛"}, 647 | .{"THORN", "Þ"}, 648 | .{"thorn", "þ"}, 649 | .{"times", "×"}, 650 | .{"tint;", "∭"}, 651 | .{"toea;", "⤨"}, 652 | .{"Topf;", "𝕋"}, 653 | .{"topf;", "𝕥"}, 654 | .{"tosa;", "⤩"}, 655 | .{"trie;", "≜"}, 656 | .{"Tscr;", "𝒯"}, 657 | .{"tscr;", "𝓉"}, 658 | .{"TScy;", "Ц"}, 659 | .{"tscy;", "ц"}, 660 | .{"Uarr;", "↟"}, 661 | .{"uArr;", "⇑"}, 662 | .{"uarr;", "↑"}, 663 | .{"Ucirc", "Û"}, 664 | .{"ucirc", "û"}, 665 | .{"uHar;", "⥣"}, 666 | .{"Uopf;", "𝕌"}, 667 | .{"uopf;", "𝕦"}, 668 | .{"Upsi;", "ϒ"}, 669 | .{"upsi;", "υ"}, 670 | .{"Uscr;", "𝒰"}, 671 | .{"uscr;", "𝓊"}, 672 | .{"utri;", "▵"}, 673 | .{"Uuml;", "Ü"}, 674 | .{"uuml;", "ü"}, 675 | .{"vArr;", "⇕"}, 676 | .{"varr;", "↕"}, 677 | .{"Vbar;", "⫫"}, 678 | .{"vBar;", "⫨"}, 679 | .{"Vert;", "‖"}, 680 | .{"vert;", "|"}, 681 | .{"Vopf;", "𝕍"}, 682 | .{"vopf;", "𝕧"}, 683 | .{"Vscr;", "𝒱"}, 684 | .{"vscr;", "𝓋"}, 685 | .{"Wopf;", "𝕎"}, 686 | .{"wopf;", "𝕨"}, 687 | .{"Wscr;", "𝒲"}, 688 | .{"wscr;", "𝓌"}, 689 | .{"xcap;", "⋂"}, 690 | .{"xcup;", "⋃"}, 691 | .{"xmap;", "⟼"}, 692 | .{"xnis;", "⋻"}, 693 | .{"Xopf;", "𝕏"}, 694 | .{"xopf;", "𝕩"}, 695 | .{"Xscr;", "𝒳"}, 696 | .{"xscr;", "𝓍"}, 697 | .{"xvee;", "⋁"}, 698 | .{"YAcy;", "Я"}, 699 | .{"yacy;", "я"}, 700 | .{"YIcy;", "Ї"}, 701 | .{"yicy;", "ї"}, 702 | .{"Yopf;", "𝕐"}, 703 | .{"yopf;", "𝕪"}, 704 | .{"Yscr;", "𝒴"}, 705 | .{"yscr;", "𝓎"}, 706 | .{"YUcy;", "Ю"}, 707 | .{"yucy;", "ю"}, 708 | .{"Yuml;", "Ÿ"}, 709 | .{"yuml;", "ÿ"}, 710 | .{"Zdot;", "Ż"}, 711 | .{"zdot;", "ż"}, 712 | .{"Zeta;", "Ζ"}, 713 | .{"zeta;", "ζ"}, 714 | .{"ZHcy;", "Ж"}, 715 | .{"zhcy;", "ж"}, 716 | .{"Zopf;", "ℤ"}, 717 | .{"zopf;", "𝕫"}, 718 | .{"Zscr;", "𝒵"}, 719 | .{"zscr;", "𝓏"}, 720 | .{"zwnj;", "‌"}, 721 | .{"Aacute", "Á"}, 722 | .{"aacute", "á"}, 723 | .{"Acirc;", "Â"}, 724 | .{"acirc;", "â"}, 725 | .{"acute;", "´"}, 726 | .{"AElig;", "Æ"}, 727 | .{"aelig;", "æ"}, 728 | .{"Agrave", "À"}, 729 | .{"agrave", "à"}, 730 | .{"aleph;", "ℵ"}, 731 | .{"Alpha;", "Α"}, 732 | .{"alpha;", "α"}, 733 | .{"Amacr;", "Ā"}, 734 | .{"amacr;", "ā"}, 735 | .{"amalg;", "⨿"}, 736 | .{"angle;", "∠"}, 737 | .{"angrt;", "∟"}, 738 | .{"angst;", "Å"}, 739 | .{"Aogon;", "Ą"}, 740 | .{"aogon;", "ą"}, 741 | .{"Aring;", "Å"}, 742 | .{"aring;", "å"}, 743 | .{"asymp;", "≈"}, 744 | .{"Atilde", "Ã"}, 745 | .{"atilde", "ã"}, 746 | .{"awint;", "⨑"}, 747 | .{"bcong;", "≌"}, 748 | .{"bdquo;", "„"}, 749 | .{"bepsi;", "϶"}, 750 | .{"blank;", "␣"}, 751 | .{"blk12;", "▒"}, 752 | .{"blk14;", "░"}, 753 | .{"blk34;", "▓"}, 754 | .{"block;", "█"}, 755 | .{"boxDL;", "╗"}, 756 | .{"boxDl;", "╖"}, 757 | .{"boxdL;", "╕"}, 758 | .{"boxdl;", "┐"}, 759 | .{"boxDR;", "╔"}, 760 | .{"boxDr;", "╓"}, 761 | .{"boxdR;", "╒"}, 762 | .{"boxdr;", "┌"}, 763 | .{"boxHD;", "╦"}, 764 | .{"boxHd;", "╤"}, 765 | .{"boxhD;", "╥"}, 766 | .{"boxhd;", "┬"}, 767 | .{"boxHU;", "╩"}, 768 | .{"boxHu;", "╧"}, 769 | .{"boxhU;", "╨"}, 770 | .{"boxhu;", "┴"}, 771 | .{"boxUL;", "╝"}, 772 | .{"boxUl;", "╜"}, 773 | .{"boxuL;", "╛"}, 774 | .{"boxul;", "┘"}, 775 | .{"boxUR;", "╚"}, 776 | .{"boxUr;", "╙"}, 777 | .{"boxuR;", "╘"}, 778 | .{"boxur;", "└"}, 779 | .{"boxVH;", "╬"}, 780 | .{"boxVh;", "╫"}, 781 | .{"boxvH;", "╪"}, 782 | .{"boxvh;", "┼"}, 783 | .{"boxVL;", "╣"}, 784 | .{"boxVl;", "╢"}, 785 | .{"boxvL;", "╡"}, 786 | .{"boxvl;", "┤"}, 787 | .{"boxVR;", "╠"}, 788 | .{"boxVr;", "╟"}, 789 | .{"boxvR;", "╞"}, 790 | .{"boxvr;", "├"}, 791 | .{"Breve;", "˘"}, 792 | .{"breve;", "˘"}, 793 | .{"brvbar", "¦"}, 794 | .{"bsemi;", "⁏"}, 795 | .{"bsime;", "⋍"}, 796 | .{"bsolb;", "⧅"}, 797 | .{"bumpE;", "⪮"}, 798 | .{"bumpe;", "≏"}, 799 | .{"caret;", "⁁"}, 800 | .{"caron;", "ˇ"}, 801 | .{"ccaps;", "⩍"}, 802 | .{"Ccedil", "Ç"}, 803 | .{"ccedil", "ç"}, 804 | .{"Ccirc;", "Ĉ"}, 805 | .{"ccirc;", "ĉ"}, 806 | .{"ccups;", "⩌"}, 807 | .{"cedil;", "¸"}, 808 | .{"check;", "✓"}, 809 | .{"clubs;", "♣"}, 810 | .{"Colon;", "∷"}, 811 | .{"colon;", ":"}, 812 | .{"comma;", ","}, 813 | .{"crarr;", "↵"}, 814 | .{"Cross;", "⨯"}, 815 | .{"cross;", "✗"}, 816 | .{"csube;", "⫑"}, 817 | .{"csupe;", "⫒"}, 818 | .{"ctdot;", "⋯"}, 819 | .{"cuepr;", "⋞"}, 820 | .{"cuesc;", "⋟"}, 821 | .{"cupor;", "⩅"}, 822 | .{"curren", "¤"}, 823 | .{"cuvee;", "⋎"}, 824 | .{"cuwed;", "⋏"}, 825 | .{"cwint;", "∱"}, 826 | .{"Dashv;", "⫤"}, 827 | .{"dashv;", "⊣"}, 828 | .{"dblac;", "˝"}, 829 | .{"ddarr;", "⇊"}, 830 | .{"Delta;", "Δ"}, 831 | .{"delta;", "δ"}, 832 | .{"dharl;", "⇃"}, 833 | .{"dharr;", "⇂"}, 834 | .{"diams;", "♦"}, 835 | .{"disin;", "⋲"}, 836 | .{"divide", "÷"}, 837 | .{"doteq;", "≐"}, 838 | .{"dtdot;", "⋱"}, 839 | .{"dtrif;", "▾"}, 840 | .{"duarr;", "⇵"}, 841 | .{"duhar;", "⥯"}, 842 | .{"Eacute", "É"}, 843 | .{"eacute", "é"}, 844 | .{"Ecirc;", "Ê"}, 845 | .{"ecirc;", "ê"}, 846 | .{"eDDot;", "⩷"}, 847 | .{"efDot;", "≒"}, 848 | .{"Egrave", "È"}, 849 | .{"egrave", "è"}, 850 | .{"Emacr;", "Ē"}, 851 | .{"emacr;", "ē"}, 852 | .{"empty;", "∅"}, 853 | .{"Eogon;", "Ę"}, 854 | .{"eogon;", "ę"}, 855 | .{"eplus;", "⩱"}, 856 | .{"epsiv;", "ϵ"}, 857 | .{"eqsim;", "≂"}, 858 | .{"Equal;", "⩵"}, 859 | .{"equiv;", "≡"}, 860 | .{"erarr;", "⥱"}, 861 | .{"erDot;", "≓"}, 862 | .{"esdot;", "≐"}, 863 | .{"exist;", "∃"}, 864 | .{"fflig;", "ff"}, 865 | .{"filig;", "fi"}, 866 | .{"fjlig;", "fj"}, 867 | .{"fllig;", "fl"}, 868 | .{"fltns;", "▱"}, 869 | .{"forkv;", "⫙"}, 870 | .{"frac12", "½"}, 871 | .{"frac14", "¼"}, 872 | .{"frac34", "¾"}, 873 | .{"frasl;", "⁄"}, 874 | .{"frown;", "⌢"}, 875 | .{"Gamma;", "Γ"}, 876 | .{"gamma;", "γ"}, 877 | .{"Gcirc;", "Ĝ"}, 878 | .{"gcirc;", "ĝ"}, 879 | .{"gescc;", "⪩"}, 880 | .{"gimel;", "ℷ"}, 881 | .{"gneqq;", "≩"}, 882 | .{"gnsim;", "⋧"}, 883 | .{"grave;", "`"}, 884 | .{"gsime;", "⪎"}, 885 | .{"gsiml;", "⪐"}, 886 | .{"gtcir;", "⩺"}, 887 | .{"gtdot;", "⋗"}, 888 | .{"Hacek;", "ˇ"}, 889 | .{"harrw;", "↭"}, 890 | .{"Hcirc;", "Ĥ"}, 891 | .{"hcirc;", "ĥ"}, 892 | .{"hoarr;", "⇿"}, 893 | .{"Iacute", "Í"}, 894 | .{"iacute", "í"}, 895 | .{"Icirc;", "Î"}, 896 | .{"icirc;", "î"}, 897 | .{"iexcl;", "¡"}, 898 | .{"Igrave", "Ì"}, 899 | .{"igrave", "ì"}, 900 | .{"iiint;", "∭"}, 901 | .{"iiota;", "℩"}, 902 | .{"IJlig;", "IJ"}, 903 | .{"ijlig;", "ij"}, 904 | .{"Imacr;", "Ī"}, 905 | .{"imacr;", "ī"}, 906 | .{"image;", "ℑ"}, 907 | .{"imath;", "ı"}, 908 | .{"imped;", "Ƶ"}, 909 | .{"infin;", "∞"}, 910 | .{"Iogon;", "Į"}, 911 | .{"iogon;", "į"}, 912 | .{"iprod;", "⨼"}, 913 | .{"iquest", "¿"}, 914 | .{"isinE;", "⋹"}, 915 | .{"isins;", "⋴"}, 916 | .{"isinv;", "∈"}, 917 | .{"Iukcy;", "І"}, 918 | .{"iukcy;", "і"}, 919 | .{"Jcirc;", "Ĵ"}, 920 | .{"jcirc;", "ĵ"}, 921 | .{"jmath;", "ȷ"}, 922 | .{"Jukcy;", "Є"}, 923 | .{"jukcy;", "є"}, 924 | .{"Kappa;", "Κ"}, 925 | .{"kappa;", "κ"}, 926 | .{"lAarr;", "⇚"}, 927 | .{"langd;", "⦑"}, 928 | .{"laquo;", "«"}, 929 | .{"larrb;", "⇤"}, 930 | .{"lates;", "⪭︀"}, 931 | .{"lBarr;", "⤎"}, 932 | .{"lbarr;", "⤌"}, 933 | .{"lbbrk;", "❲"}, 934 | .{"lbrke;", "⦋"}, 935 | .{"lceil;", "⌈"}, 936 | .{"ldquo;", "“"}, 937 | .{"lescc;", "⪨"}, 938 | .{"lhard;", "↽"}, 939 | .{"lharu;", "↼"}, 940 | .{"lhblk;", "▄"}, 941 | .{"llarr;", "⇇"}, 942 | .{"lltri;", "◺"}, 943 | .{"lneqq;", "≨"}, 944 | .{"lnsim;", "⋦"}, 945 | .{"loang;", "⟬"}, 946 | .{"loarr;", "⇽"}, 947 | .{"lobrk;", "⟦"}, 948 | .{"lopar;", "⦅"}, 949 | .{"lrarr;", "⇆"}, 950 | .{"lrhar;", "⇋"}, 951 | .{"lrtri;", "⊿"}, 952 | .{"lsime;", "⪍"}, 953 | .{"lsimg;", "⪏"}, 954 | .{"lsquo;", "‘"}, 955 | .{"ltcir;", "⩹"}, 956 | .{"ltdot;", "⋖"}, 957 | .{"ltrie;", "⊴"}, 958 | .{"ltrif;", "◂"}, 959 | .{"mdash;", "—"}, 960 | .{"mDDot;", "∺"}, 961 | .{"micro;", "µ"}, 962 | .{"middot", "·"}, 963 | .{"minus;", "−"}, 964 | .{"mumap;", "⊸"}, 965 | .{"nabla;", "∇"}, 966 | .{"napid;", "≋̸"}, 967 | .{"napos;", "ʼn"}, 968 | .{"natur;", "♮"}, 969 | .{"nbump;", "≎̸"}, 970 | .{"ncong;", "≇"}, 971 | .{"ndash;", "–"}, 972 | .{"neArr;", "⇗"}, 973 | .{"nearr;", "↗"}, 974 | .{"nedot;", "≐̸"}, 975 | .{"nesim;", "≂̸"}, 976 | .{"ngeqq;", "≧̸"}, 977 | .{"ngsim;", "≵"}, 978 | .{"nhArr;", "⇎"}, 979 | .{"nharr;", "↮"}, 980 | .{"nhpar;", "⫲"}, 981 | .{"nlArr;", "⇍"}, 982 | .{"nlarr;", "↚"}, 983 | .{"nleqq;", "≦̸"}, 984 | .{"nless;", "≮"}, 985 | .{"nlsim;", "≴"}, 986 | .{"nltri;", "⋪"}, 987 | .{"notin;", "∉"}, 988 | .{"notni;", "∌"}, 989 | .{"npart;", "∂̸"}, 990 | .{"nprec;", "⊀"}, 991 | .{"nrArr;", "⇏"}, 992 | .{"nrarr;", "↛"}, 993 | .{"nrtri;", "⋫"}, 994 | .{"nsime;", "≄"}, 995 | .{"nsmid;", "∤"}, 996 | .{"nspar;", "∦"}, 997 | .{"nsubE;", "⫅̸"}, 998 | .{"nsube;", "⊈"}, 999 | .{"nsucc;", "⊁"}, 1000 | .{"nsupE;", "⫆̸"}, 1001 | .{"nsupe;", "⊉"}, 1002 | .{"Ntilde", "Ñ"}, 1003 | .{"ntilde", "ñ"}, 1004 | .{"numsp;", " "}, 1005 | .{"nvsim;", "∼⃒"}, 1006 | .{"nwArr;", "⇖"}, 1007 | .{"nwarr;", "↖"}, 1008 | .{"Oacute", "Ó"}, 1009 | .{"oacute", "ó"}, 1010 | .{"Ocirc;", "Ô"}, 1011 | .{"ocirc;", "ô"}, 1012 | .{"odash;", "⊝"}, 1013 | .{"OElig;", "Œ"}, 1014 | .{"oelig;", "œ"}, 1015 | .{"ofcir;", "⦿"}, 1016 | .{"Ograve", "Ò"}, 1017 | .{"ograve", "ò"}, 1018 | .{"ohbar;", "⦵"}, 1019 | .{"olarr;", "↺"}, 1020 | .{"olcir;", "⦾"}, 1021 | .{"oline;", "‾"}, 1022 | .{"Omacr;", "Ō"}, 1023 | .{"omacr;", "ō"}, 1024 | .{"Omega;", "Ω"}, 1025 | .{"omega;", "ω"}, 1026 | .{"operp;", "⦹"}, 1027 | .{"oplus;", "⊕"}, 1028 | .{"orarr;", "↻"}, 1029 | .{"order;", "ℴ"}, 1030 | .{"Oslash", "Ø"}, 1031 | .{"oslash", "ø"}, 1032 | .{"Otilde", "Õ"}, 1033 | .{"otilde", "õ"}, 1034 | .{"ovbar;", "⌽"}, 1035 | .{"parsl;", "⫽"}, 1036 | .{"phone;", "☎"}, 1037 | .{"plusb;", "⊞"}, 1038 | .{"pluse;", "⩲"}, 1039 | .{"plusmn", "±"}, 1040 | .{"pound;", "£"}, 1041 | .{"prcue;", "≼"}, 1042 | .{"Prime;", "″"}, 1043 | .{"prime;", "′"}, 1044 | .{"prnap;", "⪹"}, 1045 | .{"prsim;", "≾"}, 1046 | .{"quest;", "?"}, 1047 | .{"rAarr;", "⇛"}, 1048 | .{"radic;", "√"}, 1049 | .{"rangd;", "⦒"}, 1050 | .{"range;", "⦥"}, 1051 | .{"raquo;", "»"}, 1052 | .{"rarrb;", "⇥"}, 1053 | .{"rarrc;", "⤳"}, 1054 | .{"rarrw;", "↝"}, 1055 | .{"ratio;", "∶"}, 1056 | .{"RBarr;", "⤐"}, 1057 | .{"rBarr;", "⤏"}, 1058 | .{"rbarr;", "⤍"}, 1059 | .{"rbbrk;", "❳"}, 1060 | .{"rbrke;", "⦌"}, 1061 | .{"rceil;", "⌉"}, 1062 | .{"rdquo;", "”"}, 1063 | .{"reals;", "ℝ"}, 1064 | .{"rhard;", "⇁"}, 1065 | .{"rharu;", "⇀"}, 1066 | .{"rlarr;", "⇄"}, 1067 | .{"rlhar;", "⇌"}, 1068 | .{"rnmid;", "⫮"}, 1069 | .{"roang;", "⟭"}, 1070 | .{"roarr;", "⇾"}, 1071 | .{"robrk;", "⟧"}, 1072 | .{"ropar;", "⦆"}, 1073 | .{"rrarr;", "⇉"}, 1074 | .{"rsquo;", "’"}, 1075 | .{"rtrie;", "⊵"}, 1076 | .{"rtrif;", "▸"}, 1077 | .{"sbquo;", "‚"}, 1078 | .{"sccue;", "≽"}, 1079 | .{"Scirc;", "Ŝ"}, 1080 | .{"scirc;", "ŝ"}, 1081 | .{"scnap;", "⪺"}, 1082 | .{"scsim;", "≿"}, 1083 | .{"sdotb;", "⊡"}, 1084 | .{"sdote;", "⩦"}, 1085 | .{"seArr;", "⇘"}, 1086 | .{"searr;", "↘"}, 1087 | .{"setmn;", "∖"}, 1088 | .{"sharp;", "♯"}, 1089 | .{"Sigma;", "Σ"}, 1090 | .{"sigma;", "σ"}, 1091 | .{"simeq;", "≃"}, 1092 | .{"simgE;", "⪠"}, 1093 | .{"simlE;", "⪟"}, 1094 | .{"simne;", "≆"}, 1095 | .{"slarr;", "←"}, 1096 | .{"smile;", "⌣"}, 1097 | .{"smtes;", "⪬︀"}, 1098 | .{"sqcap;", "⊓"}, 1099 | .{"sqcup;", "⊔"}, 1100 | .{"sqsub;", "⊏"}, 1101 | .{"sqsup;", "⊐"}, 1102 | .{"srarr;", "→"}, 1103 | .{"starf;", "★"}, 1104 | .{"strns;", "¯"}, 1105 | .{"subnE;", "⫋"}, 1106 | .{"subne;", "⊊"}, 1107 | .{"supnE;", "⫌"}, 1108 | .{"supne;", "⊋"}, 1109 | .{"swArr;", "⇙"}, 1110 | .{"swarr;", "↙"}, 1111 | .{"szlig;", "ß"}, 1112 | .{"Theta;", "Θ"}, 1113 | .{"theta;", "θ"}, 1114 | .{"thkap;", "≈"}, 1115 | .{"THORN;", "Þ"}, 1116 | .{"thorn;", "þ"}, 1117 | .{"Tilde;", "∼"}, 1118 | .{"tilde;", "˜"}, 1119 | .{"times;", "×"}, 1120 | .{"TRADE;", "™"}, 1121 | .{"trade;", "™"}, 1122 | .{"trisb;", "⧍"}, 1123 | .{"TSHcy;", "Ћ"}, 1124 | .{"tshcy;", "ћ"}, 1125 | .{"twixt;", "≬"}, 1126 | .{"Uacute", "Ú"}, 1127 | .{"uacute", "ú"}, 1128 | .{"Ubrcy;", "Ў"}, 1129 | .{"ubrcy;", "ў"}, 1130 | .{"Ucirc;", "Û"}, 1131 | .{"ucirc;", "û"}, 1132 | .{"udarr;", "⇅"}, 1133 | .{"udhar;", "⥮"}, 1134 | .{"Ugrave", "Ù"}, 1135 | .{"ugrave", "ù"}, 1136 | .{"uharl;", "↿"}, 1137 | .{"uharr;", "↾"}, 1138 | .{"uhblk;", "▀"}, 1139 | .{"ultri;", "◸"}, 1140 | .{"Umacr;", "Ū"}, 1141 | .{"umacr;", "ū"}, 1142 | .{"Union;", "⋃"}, 1143 | .{"Uogon;", "Ų"}, 1144 | .{"uogon;", "ų"}, 1145 | .{"uplus;", "⊎"}, 1146 | .{"upsih;", "ϒ"}, 1147 | .{"UpTee;", "⊥"}, 1148 | .{"Uring;", "Ů"}, 1149 | .{"uring;", "ů"}, 1150 | .{"urtri;", "◹"}, 1151 | .{"utdot;", "⋰"}, 1152 | .{"utrif;", "▴"}, 1153 | .{"uuarr;", "⇈"}, 1154 | .{"varpi;", "ϖ"}, 1155 | .{"vBarv;", "⫩"}, 1156 | .{"VDash;", "⊫"}, 1157 | .{"Vdash;", "⊩"}, 1158 | .{"vDash;", "⊨"}, 1159 | .{"vdash;", "⊢"}, 1160 | .{"veeeq;", "≚"}, 1161 | .{"vltri;", "⊲"}, 1162 | .{"vnsub;", "⊂⃒"}, 1163 | .{"vnsup;", "⊃⃒"}, 1164 | .{"vprop;", "∝"}, 1165 | .{"vrtri;", "⊳"}, 1166 | .{"Wcirc;", "Ŵ"}, 1167 | .{"wcirc;", "ŵ"}, 1168 | .{"Wedge;", "⋀"}, 1169 | .{"wedge;", "∧"}, 1170 | .{"xcirc;", "◯"}, 1171 | .{"xdtri;", "▽"}, 1172 | .{"xhArr;", "⟺"}, 1173 | .{"xharr;", "⟷"}, 1174 | .{"xlArr;", "⟸"}, 1175 | .{"xlarr;", "⟵"}, 1176 | .{"xodot;", "⨀"}, 1177 | .{"xrArr;", "⟹"}, 1178 | .{"xrarr;", "⟶"}, 1179 | .{"xutri;", "△"}, 1180 | .{"Yacute", "Ý"}, 1181 | .{"yacute", "ý"}, 1182 | .{"Ycirc;", "Ŷ"}, 1183 | .{"ycirc;", "ŷ"}, 1184 | .{"Aacute;", "Á"}, 1185 | .{"aacute;", "á"}, 1186 | .{"Abreve;", "Ă"}, 1187 | .{"abreve;", "ă"}, 1188 | .{"Agrave;", "À"}, 1189 | .{"agrave;", "à"}, 1190 | .{"andand;", "⩕"}, 1191 | .{"angmsd;", "∡"}, 1192 | .{"angsph;", "∢"}, 1193 | .{"apacir;", "⩯"}, 1194 | .{"approx;", "≈"}, 1195 | .{"Assign;", "≔"}, 1196 | .{"Atilde;", "Ã"}, 1197 | .{"atilde;", "ã"}, 1198 | .{"barvee;", "⊽"}, 1199 | .{"Barwed;", "⌆"}, 1200 | .{"barwed;", "⌅"}, 1201 | .{"becaus;", "∵"}, 1202 | .{"bernou;", "ℬ"}, 1203 | .{"bigcap;", "⋂"}, 1204 | .{"bigcup;", "⋃"}, 1205 | .{"bigvee;", "⋁"}, 1206 | .{"bkarow;", "⤍"}, 1207 | .{"bottom;", "⊥"}, 1208 | .{"bowtie;", "⋈"}, 1209 | .{"boxbox;", "⧉"}, 1210 | .{"bprime;", "‵"}, 1211 | .{"brvbar;", "¦"}, 1212 | .{"bullet;", "•"}, 1213 | .{"Bumpeq;", "≎"}, 1214 | .{"bumpeq;", "≏"}, 1215 | .{"Cacute;", "Ć"}, 1216 | .{"cacute;", "ć"}, 1217 | .{"capand;", "⩄"}, 1218 | .{"capcap;", "⩋"}, 1219 | .{"capcup;", "⩇"}, 1220 | .{"capdot;", "⩀"}, 1221 | .{"Ccaron;", "Č"}, 1222 | .{"ccaron;", "č"}, 1223 | .{"Ccedil;", "Ç"}, 1224 | .{"ccedil;", "ç"}, 1225 | .{"circeq;", "≗"}, 1226 | .{"cirmid;", "⫯"}, 1227 | .{"Colone;", "⩴"}, 1228 | .{"colone;", "≔"}, 1229 | .{"commat;", "@"}, 1230 | .{"compfn;", "∘"}, 1231 | .{"Conint;", "∯"}, 1232 | .{"conint;", "∮"}, 1233 | .{"coprod;", "∐"}, 1234 | .{"copysr;", "℗"}, 1235 | .{"cularr;", "↶"}, 1236 | .{"CupCap;", "≍"}, 1237 | .{"cupcap;", "⩆"}, 1238 | .{"cupcup;", "⩊"}, 1239 | .{"cupdot;", "⊍"}, 1240 | .{"curarr;", "↷"}, 1241 | .{"curren;", "¤"}, 1242 | .{"cylcty;", "⌭"}, 1243 | .{"Dagger;", "‡"}, 1244 | .{"dagger;", "†"}, 1245 | .{"daleth;", "ℸ"}, 1246 | .{"Dcaron;", "Ď"}, 1247 | .{"dcaron;", "ď"}, 1248 | .{"dfisht;", "⥿"}, 1249 | .{"divide;", "÷"}, 1250 | .{"divonx;", "⋇"}, 1251 | .{"dlcorn;", "⌞"}, 1252 | .{"dlcrop;", "⌍"}, 1253 | .{"dollar;", "$"}, 1254 | .{"DotDot;", "⃜"}, 1255 | .{"drcorn;", "⌟"}, 1256 | .{"drcrop;", "⌌"}, 1257 | .{"Dstrok;", "Đ"}, 1258 | .{"dstrok;", "đ"}, 1259 | .{"Eacute;", "É"}, 1260 | .{"eacute;", "é"}, 1261 | .{"easter;", "⩮"}, 1262 | .{"Ecaron;", "Ě"}, 1263 | .{"ecaron;", "ě"}, 1264 | .{"ecolon;", "≕"}, 1265 | .{"Egrave;", "È"}, 1266 | .{"egrave;", "è"}, 1267 | .{"egsdot;", "⪘"}, 1268 | .{"elsdot;", "⪗"}, 1269 | .{"emptyv;", "∅"}, 1270 | .{"emsp13;", " "}, 1271 | .{"emsp14;", " "}, 1272 | .{"eparsl;", "⧣"}, 1273 | .{"eqcirc;", "≖"}, 1274 | .{"equals;", "="}, 1275 | .{"equest;", "≟"}, 1276 | .{"Exists;", "∃"}, 1277 | .{"female;", "♀"}, 1278 | .{"ffilig;", "ffi"}, 1279 | .{"ffllig;", "ffl"}, 1280 | .{"ForAll;", "∀"}, 1281 | .{"forall;", "∀"}, 1282 | .{"frac12;", "½"}, 1283 | .{"frac13;", "⅓"}, 1284 | .{"frac14;", "¼"}, 1285 | .{"frac15;", "⅕"}, 1286 | .{"frac16;", "⅙"}, 1287 | .{"frac18;", "⅛"}, 1288 | .{"frac23;", "⅔"}, 1289 | .{"frac25;", "⅖"}, 1290 | .{"frac34;", "¾"}, 1291 | .{"frac35;", "⅗"}, 1292 | .{"frac38;", "⅜"}, 1293 | .{"frac45;", "⅘"}, 1294 | .{"frac56;", "⅚"}, 1295 | .{"frac58;", "⅝"}, 1296 | .{"frac78;", "⅞"}, 1297 | .{"gacute;", "ǵ"}, 1298 | .{"Gammad;", "Ϝ"}, 1299 | .{"gammad;", "ϝ"}, 1300 | .{"Gbreve;", "Ğ"}, 1301 | .{"gbreve;", "ğ"}, 1302 | .{"Gcedil;", "Ģ"}, 1303 | .{"gesdot;", "⪀"}, 1304 | .{"gesles;", "⪔"}, 1305 | .{"gtlPar;", "⦕"}, 1306 | .{"gtrarr;", "⥸"}, 1307 | .{"gtrdot;", "⋗"}, 1308 | .{"gtrsim;", "≳"}, 1309 | .{"hairsp;", " "}, 1310 | .{"hamilt;", "ℋ"}, 1311 | .{"HARDcy;", "Ъ"}, 1312 | .{"hardcy;", "ъ"}, 1313 | .{"hearts;", "♥"}, 1314 | .{"hellip;", "…"}, 1315 | .{"hercon;", "⊹"}, 1316 | .{"homtht;", "∻"}, 1317 | .{"horbar;", "―"}, 1318 | .{"hslash;", "ℏ"}, 1319 | .{"Hstrok;", "Ħ"}, 1320 | .{"hstrok;", "ħ"}, 1321 | .{"hybull;", "⁃"}, 1322 | .{"hyphen;", "‐"}, 1323 | .{"Iacute;", "Í"}, 1324 | .{"iacute;", "í"}, 1325 | .{"Igrave;", "Ì"}, 1326 | .{"igrave;", "ì"}, 1327 | .{"iiiint;", "⨌"}, 1328 | .{"iinfin;", "⧜"}, 1329 | .{"incare;", "℅"}, 1330 | .{"inodot;", "ı"}, 1331 | .{"intcal;", "⊺"}, 1332 | .{"iquest;", "¿"}, 1333 | .{"isinsv;", "⋳"}, 1334 | .{"Itilde;", "Ĩ"}, 1335 | .{"itilde;", "ĩ"}, 1336 | .{"Jsercy;", "Ј"}, 1337 | .{"jsercy;", "ј"}, 1338 | .{"kappav;", "ϰ"}, 1339 | .{"Kcedil;", "Ķ"}, 1340 | .{"kcedil;", "ķ"}, 1341 | .{"kgreen;", "ĸ"}, 1342 | .{"Lacute;", "Ĺ"}, 1343 | .{"lacute;", "ĺ"}, 1344 | .{"lagran;", "ℒ"}, 1345 | .{"Lambda;", "Λ"}, 1346 | .{"lambda;", "λ"}, 1347 | .{"langle;", "⟨"}, 1348 | .{"larrfs;", "⤝"}, 1349 | .{"larrhk;", "↩"}, 1350 | .{"larrlp;", "↫"}, 1351 | .{"larrpl;", "⤹"}, 1352 | .{"larrtl;", "↢"}, 1353 | .{"lAtail;", "⤛"}, 1354 | .{"latail;", "⤙"}, 1355 | .{"lbrace;", "{"}, 1356 | .{"lbrack;", "["}, 1357 | .{"Lcaron;", "Ľ"}, 1358 | .{"lcaron;", "ľ"}, 1359 | .{"Lcedil;", "Ļ"}, 1360 | .{"lcedil;", "ļ"}, 1361 | .{"ldquor;", "„"}, 1362 | .{"lesdot;", "⩿"}, 1363 | .{"lesges;", "⪓"}, 1364 | .{"lfisht;", "⥼"}, 1365 | .{"lfloor;", "⌊"}, 1366 | .{"lharul;", "⥪"}, 1367 | .{"llhard;", "⥫"}, 1368 | .{"Lmidot;", "Ŀ"}, 1369 | .{"lmidot;", "ŀ"}, 1370 | .{"lmoust;", "⎰"}, 1371 | .{"loplus;", "⨭"}, 1372 | .{"lowast;", "∗"}, 1373 | .{"lowbar;", "_"}, 1374 | .{"lparlt;", "⦓"}, 1375 | .{"lrhard;", "⥭"}, 1376 | .{"lsaquo;", "‹"}, 1377 | .{"lsquor;", "‚"}, 1378 | .{"Lstrok;", "Ł"}, 1379 | .{"lstrok;", "ł"}, 1380 | .{"lthree;", "⋋"}, 1381 | .{"ltimes;", "⋉"}, 1382 | .{"ltlarr;", "⥶"}, 1383 | .{"ltrPar;", "⦖"}, 1384 | .{"mapsto;", "↦"}, 1385 | .{"marker;", "▮"}, 1386 | .{"mcomma;", "⨩"}, 1387 | .{"midast;", "*"}, 1388 | .{"midcir;", "⫰"}, 1389 | .{"middot;", "·"}, 1390 | .{"minusb;", "⊟"}, 1391 | .{"minusd;", "∸"}, 1392 | .{"mnplus;", "∓"}, 1393 | .{"models;", "⊧"}, 1394 | .{"mstpos;", "∾"}, 1395 | .{"Nacute;", "Ń"}, 1396 | .{"nacute;", "ń"}, 1397 | .{"nbumpe;", "≏̸"}, 1398 | .{"Ncaron;", "Ň"}, 1399 | .{"ncaron;", "ň"}, 1400 | .{"Ncedil;", "Ņ"}, 1401 | .{"ncedil;", "ņ"}, 1402 | .{"nearhk;", "⤤"}, 1403 | .{"nequiv;", "≢"}, 1404 | .{"nesear;", "⤨"}, 1405 | .{"nexist;", "∄"}, 1406 | .{"nltrie;", "⋬"}, 1407 | .{"notinE;", "⋹̸"}, 1408 | .{"nparsl;", "⫽⃥"}, 1409 | .{"nprcue;", "⋠"}, 1410 | .{"nrarrc;", "⤳̸"}, 1411 | .{"nrarrw;", "↝̸"}, 1412 | .{"nrtrie;", "⋭"}, 1413 | .{"nsccue;", "⋡"}, 1414 | .{"nsimeq;", "≄"}, 1415 | .{"Ntilde;", "Ñ"}, 1416 | .{"ntilde;", "ñ"}, 1417 | .{"numero;", "№"}, 1418 | .{"nVDash;", "⊯"}, 1419 | .{"nVdash;", "⊮"}, 1420 | .{"nvDash;", "⊭"}, 1421 | .{"nvdash;", "⊬"}, 1422 | .{"nvHarr;", "⤄"}, 1423 | .{"nvlArr;", "⤂"}, 1424 | .{"nvrArr;", "⤃"}, 1425 | .{"nwarhk;", "⤣"}, 1426 | .{"nwnear;", "⤧"}, 1427 | .{"Oacute;", "Ó"}, 1428 | .{"oacute;", "ó"}, 1429 | .{"Odblac;", "Ő"}, 1430 | .{"odblac;", "ő"}, 1431 | .{"odsold;", "⦼"}, 1432 | .{"Ograve;", "Ò"}, 1433 | .{"ograve;", "ò"}, 1434 | .{"ominus;", "⊖"}, 1435 | .{"origof;", "⊶"}, 1436 | .{"Oslash;", "Ø"}, 1437 | .{"oslash;", "ø"}, 1438 | .{"Otilde;", "Õ"}, 1439 | .{"otilde;", "õ"}, 1440 | .{"Otimes;", "⨷"}, 1441 | .{"otimes;", "⊗"}, 1442 | .{"parsim;", "⫳"}, 1443 | .{"percnt;", "%"}, 1444 | .{"period;", "."}, 1445 | .{"permil;", "‰"}, 1446 | .{"phmmat;", "ℳ"}, 1447 | .{"planck;", "ℏ"}, 1448 | .{"plankv;", "ℏ"}, 1449 | .{"plusdo;", "∔"}, 1450 | .{"plusdu;", "⨥"}, 1451 | .{"plusmn;", "±"}, 1452 | .{"preceq;", "⪯"}, 1453 | .{"primes;", "ℙ"}, 1454 | .{"prnsim;", "⋨"}, 1455 | .{"propto;", "∝"}, 1456 | .{"prurel;", "⊰"}, 1457 | .{"puncsp;", " "}, 1458 | .{"qprime;", "⁗"}, 1459 | .{"Racute;", "Ŕ"}, 1460 | .{"racute;", "ŕ"}, 1461 | .{"rangle;", "⟩"}, 1462 | .{"rarrap;", "⥵"}, 1463 | .{"rarrfs;", "⤞"}, 1464 | .{"rarrhk;", "↪"}, 1465 | .{"rarrlp;", "↬"}, 1466 | .{"rarrpl;", "⥅"}, 1467 | .{"Rarrtl;", "⤖"}, 1468 | .{"rarrtl;", "↣"}, 1469 | .{"rAtail;", "⤜"}, 1470 | .{"ratail;", "⤚"}, 1471 | .{"rbrace;", "}"}, 1472 | .{"rbrack;", "]"}, 1473 | .{"Rcaron;", "Ř"}, 1474 | .{"rcaron;", "ř"}, 1475 | .{"Rcedil;", "Ŗ"}, 1476 | .{"rcedil;", "ŗ"}, 1477 | .{"rdquor;", "”"}, 1478 | .{"rfisht;", "⥽"}, 1479 | .{"rfloor;", "⌋"}, 1480 | .{"rharul;", "⥬"}, 1481 | .{"rmoust;", "⎱"}, 1482 | .{"roplus;", "⨮"}, 1483 | .{"rpargt;", "⦔"}, 1484 | .{"rsaquo;", "›"}, 1485 | .{"rsquor;", "’"}, 1486 | .{"rthree;", "⋌"}, 1487 | .{"rtimes;", "⋊"}, 1488 | .{"Sacute;", "Ś"}, 1489 | .{"sacute;", "ś"}, 1490 | .{"Scaron;", "Š"}, 1491 | .{"scaron;", "š"}, 1492 | .{"Scedil;", "Ş"}, 1493 | .{"scedil;", "ş"}, 1494 | .{"scnsim;", "⋩"}, 1495 | .{"searhk;", "⤥"}, 1496 | .{"seswar;", "⤩"}, 1497 | .{"sfrown;", "⌢"}, 1498 | .{"SHCHcy;", "Щ"}, 1499 | .{"shchcy;", "щ"}, 1500 | .{"sigmaf;", "ς"}, 1501 | .{"sigmav;", "ς"}, 1502 | .{"simdot;", "⩪"}, 1503 | .{"smashp;", "⨳"}, 1504 | .{"SOFTcy;", "Ь"}, 1505 | .{"softcy;", "ь"}, 1506 | .{"solbar;", "⌿"}, 1507 | .{"spades;", "♠"}, 1508 | .{"sqcaps;", "⊓︀"}, 1509 | .{"sqcups;", "⊔︀"}, 1510 | .{"sqsube;", "⊑"}, 1511 | .{"sqsupe;", "⊒"}, 1512 | .{"Square;", "□"}, 1513 | .{"square;", "□"}, 1514 | .{"squarf;", "▪"}, 1515 | .{"ssetmn;", "∖"}, 1516 | .{"ssmile;", "⌣"}, 1517 | .{"sstarf;", "⋆"}, 1518 | .{"subdot;", "⪽"}, 1519 | .{"Subset;", "⋐"}, 1520 | .{"subset;", "⊂"}, 1521 | .{"subsim;", "⫇"}, 1522 | .{"subsub;", "⫕"}, 1523 | .{"subsup;", "⫓"}, 1524 | .{"succeq;", "⪰"}, 1525 | .{"supdot;", "⪾"}, 1526 | .{"Supset;", "⋑"}, 1527 | .{"supset;", "⊃"}, 1528 | .{"supsim;", "⫈"}, 1529 | .{"supsub;", "⫔"}, 1530 | .{"supsup;", "⫖"}, 1531 | .{"swarhk;", "⤦"}, 1532 | .{"swnwar;", "⤪"}, 1533 | .{"target;", "⌖"}, 1534 | .{"Tcaron;", "Ť"}, 1535 | .{"tcaron;", "ť"}, 1536 | .{"Tcedil;", "Ţ"}, 1537 | .{"tcedil;", "ţ"}, 1538 | .{"telrec;", "⌕"}, 1539 | .{"there4;", "∴"}, 1540 | .{"thetav;", "ϑ"}, 1541 | .{"thinsp;", " "}, 1542 | .{"thksim;", "∼"}, 1543 | .{"timesb;", "⊠"}, 1544 | .{"timesd;", "⨰"}, 1545 | .{"topbot;", "⌶"}, 1546 | .{"topcir;", "⫱"}, 1547 | .{"tprime;", "‴"}, 1548 | .{"tridot;", "◬"}, 1549 | .{"Tstrok;", "Ŧ"}, 1550 | .{"tstrok;", "ŧ"}, 1551 | .{"Uacute;", "Ú"}, 1552 | .{"uacute;", "ú"}, 1553 | .{"Ubreve;", "Ŭ"}, 1554 | .{"ubreve;", "ŭ"}, 1555 | .{"Udblac;", "Ű"}, 1556 | .{"udblac;", "ű"}, 1557 | .{"ufisht;", "⥾"}, 1558 | .{"Ugrave;", "Ù"}, 1559 | .{"ugrave;", "ù"}, 1560 | .{"ulcorn;", "⌜"}, 1561 | .{"ulcrop;", "⌏"}, 1562 | .{"urcorn;", "⌝"}, 1563 | .{"urcrop;", "⌎"}, 1564 | .{"Utilde;", "Ũ"}, 1565 | .{"utilde;", "ũ"}, 1566 | .{"vangrt;", "⦜"}, 1567 | .{"varphi;", "ϕ"}, 1568 | .{"varrho;", "ϱ"}, 1569 | .{"Vdashl;", "⫦"}, 1570 | .{"veebar;", "⊻"}, 1571 | .{"vellip;", "⋮"}, 1572 | .{"Verbar;", "‖"}, 1573 | .{"verbar;", "|"}, 1574 | .{"vsubnE;", "⫋︀"}, 1575 | .{"vsubne;", "⊊︀"}, 1576 | .{"vsupnE;", "⫌︀"}, 1577 | .{"vsupne;", "⊋︀"}, 1578 | .{"Vvdash;", "⊪"}, 1579 | .{"wedbar;", "⩟"}, 1580 | .{"wedgeq;", "≙"}, 1581 | .{"weierp;", "℘"}, 1582 | .{"wreath;", "≀"}, 1583 | .{"xoplus;", "⨁"}, 1584 | .{"xotime;", "⨂"}, 1585 | .{"xsqcup;", "⨆"}, 1586 | .{"xuplus;", "⨄"}, 1587 | .{"xwedge;", "⋀"}, 1588 | .{"Yacute;", "Ý"}, 1589 | .{"yacute;", "ý"}, 1590 | .{"Zacute;", "Ź"}, 1591 | .{"zacute;", "ź"}, 1592 | .{"Zcaron;", "Ž"}, 1593 | .{"zcaron;", "ž"}, 1594 | .{"zeetrf;", "ℨ"}, 1595 | .{"alefsym;", "ℵ"}, 1596 | .{"angrtvb;", "⊾"}, 1597 | .{"angzarr;", "⍼"}, 1598 | .{"asympeq;", "≍"}, 1599 | .{"backsim;", "∽"}, 1600 | .{"Because;", "∵"}, 1601 | .{"because;", "∵"}, 1602 | .{"bemptyv;", "⦰"}, 1603 | .{"between;", "≬"}, 1604 | .{"bigcirc;", "◯"}, 1605 | .{"bigodot;", "⨀"}, 1606 | .{"bigstar;", "★"}, 1607 | .{"bnequiv;", "≡⃥"}, 1608 | .{"boxplus;", "⊞"}, 1609 | .{"Cayleys;", "ℭ"}, 1610 | .{"Cconint;", "∰"}, 1611 | .{"ccupssm;", "⩐"}, 1612 | .{"Cedilla;", "¸"}, 1613 | .{"cemptyv;", "⦲"}, 1614 | .{"cirscir;", "⧂"}, 1615 | .{"coloneq;", "≔"}, 1616 | .{"congdot;", "⩭"}, 1617 | .{"cudarrl;", "⤸"}, 1618 | .{"cudarrr;", "⤵"}, 1619 | .{"cularrp;", "⤽"}, 1620 | .{"curarrm;", "⤼"}, 1621 | .{"dbkarow;", "⤏"}, 1622 | .{"ddagger;", "‡"}, 1623 | .{"ddotseq;", "⩷"}, 1624 | .{"demptyv;", "⦱"}, 1625 | .{"Diamond;", "⋄"}, 1626 | .{"diamond;", "⋄"}, 1627 | .{"digamma;", "ϝ"}, 1628 | .{"dotplus;", "∔"}, 1629 | .{"DownTee;", "⊤"}, 1630 | .{"dwangle;", "⦦"}, 1631 | .{"Element;", "∈"}, 1632 | .{"Epsilon;", "Ε"}, 1633 | .{"epsilon;", "ε"}, 1634 | .{"eqcolon;", "≕"}, 1635 | .{"equivDD;", "⩸"}, 1636 | .{"gesdoto;", "⪂"}, 1637 | .{"gtquest;", "⩼"}, 1638 | .{"gtrless;", "≷"}, 1639 | .{"harrcir;", "⥈"}, 1640 | .{"Implies;", "⇒"}, 1641 | .{"intprod;", "⨼"}, 1642 | .{"isindot;", "⋵"}, 1643 | .{"larrbfs;", "⤟"}, 1644 | .{"larrsim;", "⥳"}, 1645 | .{"lbrksld;", "⦏"}, 1646 | .{"lbrkslu;", "⦍"}, 1647 | .{"ldrdhar;", "⥧"}, 1648 | .{"LeftTee;", "⊣"}, 1649 | .{"lesdoto;", "⪁"}, 1650 | .{"lessdot;", "⋖"}, 1651 | .{"lessgtr;", "≶"}, 1652 | .{"lesssim;", "≲"}, 1653 | .{"lotimes;", "⨴"}, 1654 | .{"lozenge;", "◊"}, 1655 | .{"ltquest;", "⩻"}, 1656 | .{"luruhar;", "⥦"}, 1657 | .{"maltese;", "✠"}, 1658 | .{"minusdu;", "⨪"}, 1659 | .{"napprox;", "≉"}, 1660 | .{"natural;", "♮"}, 1661 | .{"nearrow;", "↗"}, 1662 | .{"NewLine;", " "}, 1663 | .{"nexists;", "∄"}, 1664 | .{"NoBreak;", "⁠"}, 1665 | .{"notinva;", "∉"}, 1666 | .{"notinvb;", "⋷"}, 1667 | .{"notinvc;", "⋶"}, 1668 | .{"NotLess;", "≮"}, 1669 | .{"notniva;", "∌"}, 1670 | .{"notnivb;", "⋾"}, 1671 | .{"notnivc;", "⋽"}, 1672 | .{"npolint;", "⨔"}, 1673 | .{"npreceq;", "⪯̸"}, 1674 | .{"nsqsube;", "⋢"}, 1675 | .{"nsqsupe;", "⋣"}, 1676 | .{"nsubset;", "⊂⃒"}, 1677 | .{"nsucceq;", "⪰̸"}, 1678 | .{"nsupset;", "⊃⃒"}, 1679 | .{"nvinfin;", "⧞"}, 1680 | .{"nvltrie;", "⊴⃒"}, 1681 | .{"nvrtrie;", "⊵⃒"}, 1682 | .{"nwarrow;", "↖"}, 1683 | .{"olcross;", "⦻"}, 1684 | .{"Omicron;", "Ο"}, 1685 | .{"omicron;", "ο"}, 1686 | .{"orderof;", "ℴ"}, 1687 | .{"orslope;", "⩗"}, 1688 | .{"OverBar;", "‾"}, 1689 | .{"pertenk;", "‱"}, 1690 | .{"planckh;", "ℎ"}, 1691 | .{"pluscir;", "⨢"}, 1692 | .{"plussim;", "⨦"}, 1693 | .{"plustwo;", "⨧"}, 1694 | .{"precsim;", "≾"}, 1695 | .{"Product;", "∏"}, 1696 | .{"quatint;", "⨖"}, 1697 | .{"questeq;", "≟"}, 1698 | .{"rarrbfs;", "⤠"}, 1699 | .{"rarrsim;", "⥴"}, 1700 | .{"rbrksld;", "⦎"}, 1701 | .{"rbrkslu;", "⦐"}, 1702 | .{"rdldhar;", "⥩"}, 1703 | .{"realine;", "ℛ"}, 1704 | .{"rotimes;", "⨵"}, 1705 | .{"ruluhar;", "⥨"}, 1706 | .{"searrow;", "↘"}, 1707 | .{"simplus;", "⨤"}, 1708 | .{"simrarr;", "⥲"}, 1709 | .{"subedot;", "⫃"}, 1710 | .{"submult;", "⫁"}, 1711 | .{"subplus;", "⪿"}, 1712 | .{"subrarr;", "⥹"}, 1713 | .{"succsim;", "≿"}, 1714 | .{"supdsub;", "⫘"}, 1715 | .{"supedot;", "⫄"}, 1716 | .{"suphsol;", "⟉"}, 1717 | .{"suphsub;", "⫗"}, 1718 | .{"suplarr;", "⥻"}, 1719 | .{"supmult;", "⫂"}, 1720 | .{"supplus;", "⫀"}, 1721 | .{"swarrow;", "↙"}, 1722 | .{"topfork;", "⫚"}, 1723 | .{"triplus;", "⨹"}, 1724 | .{"tritime;", "⨻"}, 1725 | .{"UpArrow;", "↑"}, 1726 | .{"Uparrow;", "⇑"}, 1727 | .{"uparrow;", "↑"}, 1728 | .{"Upsilon;", "Υ"}, 1729 | .{"upsilon;", "υ"}, 1730 | .{"uwangle;", "⦧"}, 1731 | .{"vzigzag;", "⦚"}, 1732 | .{"zigrarr;", "⇝"}, 1733 | .{"andslope;", "⩘"}, 1734 | .{"angmsdaa;", "⦨"}, 1735 | .{"angmsdab;", "⦩"}, 1736 | .{"angmsdac;", "⦪"}, 1737 | .{"angmsdad;", "⦫"}, 1738 | .{"angmsdae;", "⦬"}, 1739 | .{"angmsdaf;", "⦭"}, 1740 | .{"angmsdag;", "⦮"}, 1741 | .{"angmsdah;", "⦯"}, 1742 | .{"angrtvbd;", "⦝"}, 1743 | .{"approxeq;", "≊"}, 1744 | .{"awconint;", "∳"}, 1745 | .{"backcong;", "≌"}, 1746 | .{"barwedge;", "⌅"}, 1747 | .{"bbrktbrk;", "⎶"}, 1748 | .{"bigoplus;", "⨁"}, 1749 | .{"bigsqcup;", "⨆"}, 1750 | .{"biguplus;", "⨄"}, 1751 | .{"bigwedge;", "⋀"}, 1752 | .{"boxminus;", "⊟"}, 1753 | .{"boxtimes;", "⊠"}, 1754 | .{"bsolhsub;", "⟈"}, 1755 | .{"capbrcup;", "⩉"}, 1756 | .{"circledR;", "®"}, 1757 | .{"circledS;", "Ⓢ"}, 1758 | .{"cirfnint;", "⨐"}, 1759 | .{"clubsuit;", "♣"}, 1760 | .{"cupbrcap;", "⩈"}, 1761 | .{"curlyvee;", "⋎"}, 1762 | .{"cwconint;", "∲"}, 1763 | .{"DDotrahd;", "⤑"}, 1764 | .{"doteqdot;", "≑"}, 1765 | .{"DotEqual;", "≐"}, 1766 | .{"dotminus;", "∸"}, 1767 | .{"drbkarow;", "⤐"}, 1768 | .{"dzigrarr;", "⟿"}, 1769 | .{"elinters;", "⏧"}, 1770 | .{"emptyset;", "∅"}, 1771 | .{"eqvparsl;", "⧥"}, 1772 | .{"fpartint;", "⨍"}, 1773 | .{"geqslant;", "⩾"}, 1774 | .{"gesdotol;", "⪄"}, 1775 | .{"gnapprox;", "⪊"}, 1776 | .{"hksearow;", "⤥"}, 1777 | .{"hkswarow;", "⤦"}, 1778 | .{"imagline;", "ℐ"}, 1779 | .{"imagpart;", "ℑ"}, 1780 | .{"infintie;", "⧝"}, 1781 | .{"integers;", "ℤ"}, 1782 | .{"Integral;", "∫"}, 1783 | .{"intercal;", "⊺"}, 1784 | .{"intlarhk;", "⨗"}, 1785 | .{"laemptyv;", "⦴"}, 1786 | .{"ldrushar;", "⥋"}, 1787 | .{"leqslant;", "⩽"}, 1788 | .{"lesdotor;", "⪃"}, 1789 | .{"LessLess;", "⪡"}, 1790 | .{"llcorner;", "⌞"}, 1791 | .{"lnapprox;", "⪉"}, 1792 | .{"lrcorner;", "⌟"}, 1793 | .{"lurdshar;", "⥊"}, 1794 | .{"mapstoup;", "↥"}, 1795 | .{"multimap;", "⊸"}, 1796 | .{"naturals;", "ℕ"}, 1797 | .{"ncongdot;", "⩭̸"}, 1798 | .{"NotEqual;", "≠"}, 1799 | .{"notindot;", "⋵̸"}, 1800 | .{"NotTilde;", "≁"}, 1801 | .{"otimesas;", "⨶"}, 1802 | .{"parallel;", "∥"}, 1803 | .{"PartialD;", "∂"}, 1804 | .{"plusacir;", "⨣"}, 1805 | .{"pointint;", "⨕"}, 1806 | .{"Precedes;", "≺"}, 1807 | .{"precneqq;", "⪵"}, 1808 | .{"precnsim;", "⋨"}, 1809 | .{"profalar;", "⌮"}, 1810 | .{"profline;", "⌒"}, 1811 | .{"profsurf;", "⌓"}, 1812 | .{"raemptyv;", "⦳"}, 1813 | .{"realpart;", "ℜ"}, 1814 | .{"RightTee;", "⊢"}, 1815 | .{"rppolint;", "⨒"}, 1816 | .{"rtriltri;", "⧎"}, 1817 | .{"scpolint;", "⨓"}, 1818 | .{"setminus;", "∖"}, 1819 | .{"shortmid;", "∣"}, 1820 | .{"smeparsl;", "⧤"}, 1821 | .{"sqsubset;", "⊏"}, 1822 | .{"sqsupset;", "⊐"}, 1823 | .{"subseteq;", "⊆"}, 1824 | .{"Succeeds;", "≻"}, 1825 | .{"succneqq;", "⪶"}, 1826 | .{"succnsim;", "⋩"}, 1827 | .{"SuchThat;", "∋"}, 1828 | .{"Superset;", "⊃"}, 1829 | .{"supseteq;", "⊇"}, 1830 | .{"thetasym;", "ϑ"}, 1831 | .{"thicksim;", "∼"}, 1832 | .{"timesbar;", "⨱"}, 1833 | .{"triangle;", "▵"}, 1834 | .{"triminus;", "⨺"}, 1835 | .{"trpezium;", "⏢"}, 1836 | .{"Uarrocir;", "⥉"}, 1837 | .{"ulcorner;", "⌜"}, 1838 | .{"UnderBar;", "_"}, 1839 | .{"urcorner;", "⌝"}, 1840 | .{"varkappa;", "ϰ"}, 1841 | .{"varsigma;", "ς"}, 1842 | .{"vartheta;", "ϑ"}, 1843 | .{"backprime;", "‵"}, 1844 | .{"backsimeq;", "⋍"}, 1845 | .{"Backslash;", "∖"}, 1846 | .{"bigotimes;", "⨂"}, 1847 | .{"CenterDot;", "·"}, 1848 | .{"centerdot;", "·"}, 1849 | .{"checkmark;", "✓"}, 1850 | .{"CircleDot;", "⊙"}, 1851 | .{"complexes;", "ℂ"}, 1852 | .{"Congruent;", "≡"}, 1853 | .{"Coproduct;", "∐"}, 1854 | .{"dotsquare;", "⊡"}, 1855 | .{"DoubleDot;", "¨"}, 1856 | .{"DownArrow;", "↓"}, 1857 | .{"Downarrow;", "⇓"}, 1858 | .{"downarrow;", "↓"}, 1859 | .{"DownBreve;", "̑"}, 1860 | .{"gtrapprox;", "⪆"}, 1861 | .{"gtreqless;", "⋛"}, 1862 | .{"gvertneqq;", "≩︀"}, 1863 | .{"heartsuit;", "♥"}, 1864 | .{"HumpEqual;", "≏"}, 1865 | .{"LeftArrow;", "←"}, 1866 | .{"Leftarrow;", "⇐"}, 1867 | .{"leftarrow;", "←"}, 1868 | .{"LeftFloor;", "⌊"}, 1869 | .{"lesseqgtr;", "⋚"}, 1870 | .{"LessTilde;", "≲"}, 1871 | .{"lvertneqq;", "≨︀"}, 1872 | .{"Mellintrf;", "ℳ"}, 1873 | .{"MinusPlus;", "∓"}, 1874 | .{"ngeqslant;", "⩾̸"}, 1875 | .{"nleqslant;", "⩽̸"}, 1876 | .{"NotCupCap;", "≭"}, 1877 | .{"NotExists;", "∄"}, 1878 | .{"NotSubset;", "⊂⃒"}, 1879 | .{"nparallel;", "∦"}, 1880 | .{"nshortmid;", "∤"}, 1881 | .{"nsubseteq;", "⊈"}, 1882 | .{"nsupseteq;", "⊉"}, 1883 | .{"OverBrace;", "⏞"}, 1884 | .{"pitchfork;", "⋔"}, 1885 | .{"PlusMinus;", "±"}, 1886 | .{"rationals;", "ℚ"}, 1887 | .{"spadesuit;", "♠"}, 1888 | .{"subseteqq;", "⫅"}, 1889 | .{"subsetneq;", "⊊"}, 1890 | .{"supseteqq;", "⫆"}, 1891 | .{"supsetneq;", "⊋"}, 1892 | .{"Therefore;", "∴"}, 1893 | .{"therefore;", "∴"}, 1894 | .{"ThinSpace;", " "}, 1895 | .{"triangleq;", "≜"}, 1896 | .{"TripleDot;", "⃛"}, 1897 | .{"UnionPlus;", "⊎"}, 1898 | .{"varpropto;", "∝"}, 1899 | .{"Bernoullis;", "ℬ"}, 1900 | .{"circledast;", "⊛"}, 1901 | .{"CirclePlus;", "⊕"}, 1902 | .{"complement;", "∁"}, 1903 | .{"curlywedge;", "⋏"}, 1904 | .{"eqslantgtr;", "⪖"}, 1905 | .{"EqualTilde;", "≂"}, 1906 | .{"Fouriertrf;", "ℱ"}, 1907 | .{"gtreqqless;", "⪌"}, 1908 | .{"ImaginaryI;", "ⅈ"}, 1909 | .{"Laplacetrf;", "ℒ"}, 1910 | .{"LeftVector;", "↼"}, 1911 | .{"lessapprox;", "⪅"}, 1912 | .{"lesseqqgtr;", "⪋"}, 1913 | .{"Lleftarrow;", "⇚"}, 1914 | .{"lmoustache;", "⎰"}, 1915 | .{"longmapsto;", "⟼"}, 1916 | .{"mapstodown;", "↧"}, 1917 | .{"mapstoleft;", "↤"}, 1918 | .{"nLeftarrow;", "⇍"}, 1919 | .{"nleftarrow;", "↚"}, 1920 | .{"NotElement;", "∉"}, 1921 | .{"NotGreater;", "≯"}, 1922 | .{"nsubseteqq;", "⫅̸"}, 1923 | .{"nsupseteqq;", "⫆̸"}, 1924 | .{"precapprox;", "⪷"}, 1925 | .{"Proportion;", "∷"}, 1926 | .{"RightArrow;", "→"}, 1927 | .{"Rightarrow;", "⇒"}, 1928 | .{"rightarrow;", "→"}, 1929 | .{"RightFloor;", "⌋"}, 1930 | .{"rmoustache;", "⎱"}, 1931 | .{"sqsubseteq;", "⊑"}, 1932 | .{"sqsupseteq;", "⊒"}, 1933 | .{"subsetneqq;", "⫋"}, 1934 | .{"succapprox;", "⪸"}, 1935 | .{"supsetneqq;", "⫌"}, 1936 | .{"ThickSpace;", "  "}, 1937 | .{"TildeEqual;", "≃"}, 1938 | .{"TildeTilde;", "≈"}, 1939 | .{"UnderBrace;", "⏟"}, 1940 | .{"UpArrowBar;", "⤒"}, 1941 | .{"UpTeeArrow;", "↥"}, 1942 | .{"upuparrows;", "⇈"}, 1943 | .{"varepsilon;", "ϵ"}, 1944 | .{"varnothing;", "∅"}, 1945 | .{"backepsilon;", "϶"}, 1946 | .{"blacksquare;", "▪"}, 1947 | .{"circledcirc;", "⊚"}, 1948 | .{"circleddash;", "⊝"}, 1949 | .{"CircleMinus;", "⊖"}, 1950 | .{"CircleTimes;", "⊗"}, 1951 | .{"curlyeqprec;", "⋞"}, 1952 | .{"curlyeqsucc;", "⋟"}, 1953 | .{"diamondsuit;", "♦"}, 1954 | .{"eqslantless;", "⪕"}, 1955 | .{"Equilibrium;", "⇌"}, 1956 | .{"expectation;", "ℰ"}, 1957 | .{"GreaterLess;", "≷"}, 1958 | .{"LeftCeiling;", "⌈"}, 1959 | .{"LessGreater;", "≶"}, 1960 | .{"MediumSpace;", " "}, 1961 | .{"NotLessLess;", "≪̸"}, 1962 | .{"NotPrecedes;", "⊀"}, 1963 | .{"NotSucceeds;", "⊁"}, 1964 | .{"NotSuperset;", "⊃⃒"}, 1965 | .{"nRightarrow;", "⇏"}, 1966 | .{"nrightarrow;", "↛"}, 1967 | .{"OverBracket;", "⎴"}, 1968 | .{"preccurlyeq;", "≼"}, 1969 | .{"precnapprox;", "⪹"}, 1970 | .{"quaternions;", "ℍ"}, 1971 | .{"RightVector;", "⇀"}, 1972 | .{"Rrightarrow;", "⇛"}, 1973 | .{"RuleDelayed;", "⧴"}, 1974 | .{"SmallCircle;", "∘"}, 1975 | .{"SquareUnion;", "⊔"}, 1976 | .{"straightphi;", "ϕ"}, 1977 | .{"SubsetEqual;", "⊆"}, 1978 | .{"succcurlyeq;", "≽"}, 1979 | .{"succnapprox;", "⪺"}, 1980 | .{"thickapprox;", "≈"}, 1981 | .{"UpDownArrow;", "↕"}, 1982 | .{"Updownarrow;", "⇕"}, 1983 | .{"updownarrow;", "↕"}, 1984 | .{"VerticalBar;", "∣"}, 1985 | .{"blacklozenge;", "⧫"}, 1986 | .{"DownArrowBar;", "⤓"}, 1987 | .{"DownTeeArrow;", "↧"}, 1988 | .{"ExponentialE;", "ⅇ"}, 1989 | .{"exponentiale;", "ⅇ"}, 1990 | .{"GreaterEqual;", "≥"}, 1991 | .{"GreaterTilde;", "≳"}, 1992 | .{"HilbertSpace;", "ℋ"}, 1993 | .{"HumpDownHump;", "≎"}, 1994 | .{"Intersection;", "⋂"}, 1995 | .{"LeftArrowBar;", "⇤"}, 1996 | .{"LeftTeeArrow;", "↤"}, 1997 | .{"LeftTriangle;", "⊲"}, 1998 | .{"LeftUpVector;", "↿"}, 1999 | .{"NotCongruent;", "≢"}, 2000 | .{"NotHumpEqual;", "≏̸"}, 2001 | .{"NotLessEqual;", "≰"}, 2002 | .{"NotLessTilde;", "≴"}, 2003 | .{"Proportional;", "∝"}, 2004 | .{"RightCeiling;", "⌉"}, 2005 | .{"risingdotseq;", "≓"}, 2006 | .{"RoundImplies;", "⥰"}, 2007 | .{"ShortUpArrow;", "↑"}, 2008 | .{"SquareSubset;", "⊏"}, 2009 | .{"triangledown;", "▿"}, 2010 | .{"triangleleft;", "◃"}, 2011 | .{"UnderBracket;", "⎵"}, 2012 | .{"varsubsetneq;", "⊊︀"}, 2013 | .{"varsupsetneq;", "⊋︀"}, 2014 | .{"VerticalLine;", "|"}, 2015 | .{"ApplyFunction;", "⁡"}, 2016 | .{"bigtriangleup;", "△"}, 2017 | .{"blacktriangle;", "▴"}, 2018 | .{"DifferentialD;", "ⅆ"}, 2019 | .{"divideontimes;", "⋇"}, 2020 | .{"DoubleLeftTee;", "⫤"}, 2021 | .{"DoubleUpArrow;", "⇑"}, 2022 | .{"fallingdotseq;", "≒"}, 2023 | .{"hookleftarrow;", "↩"}, 2024 | .{"leftarrowtail;", "↢"}, 2025 | .{"leftharpoonup;", "↼"}, 2026 | .{"LeftTeeVector;", "⥚"}, 2027 | .{"LeftVectorBar;", "⥒"}, 2028 | .{"LessFullEqual;", "≦"}, 2029 | .{"LongLeftArrow;", "⟵"}, 2030 | .{"Longleftarrow;", "⟸"}, 2031 | .{"longleftarrow;", "⟵"}, 2032 | .{"looparrowleft;", "↫"}, 2033 | .{"measuredangle;", "∡"}, 2034 | .{"NotEqualTilde;", "≂̸"}, 2035 | .{"NotTildeEqual;", "≄"}, 2036 | .{"NotTildeTilde;", "≉"}, 2037 | .{"ntriangleleft;", "⋪"}, 2038 | .{"Poincareplane;", "ℌ"}, 2039 | .{"PrecedesEqual;", "⪯"}, 2040 | .{"PrecedesTilde;", "≾"}, 2041 | .{"RightArrowBar;", "⇥"}, 2042 | .{"RightTeeArrow;", "↦"}, 2043 | .{"RightTriangle;", "⊳"}, 2044 | .{"RightUpVector;", "↾"}, 2045 | .{"shortparallel;", "∥"}, 2046 | .{"smallsetminus;", "∖"}, 2047 | .{"SucceedsEqual;", "⪰"}, 2048 | .{"SucceedsTilde;", "≿"}, 2049 | .{"SupersetEqual;", "⊇"}, 2050 | .{"triangleright;", "▹"}, 2051 | .{"UpEquilibrium;", "⥮"}, 2052 | .{"upharpoonleft;", "↿"}, 2053 | .{"varsubsetneqq;", "⫋︀"}, 2054 | .{"varsupsetneqq;", "⫌︀"}, 2055 | .{"VerticalTilde;", "≀"}, 2056 | .{"VeryThinSpace;", " "}, 2057 | .{"curvearrowleft;", "↶"}, 2058 | .{"DiacriticalDot;", "˙"}, 2059 | .{"doublebarwedge;", "⌆"}, 2060 | .{"DoubleRightTee;", "⊨"}, 2061 | .{"downdownarrows;", "⇊"}, 2062 | .{"DownLeftVector;", "↽"}, 2063 | .{"GreaterGreater;", "⪢"}, 2064 | .{"hookrightarrow;", "↪"}, 2065 | .{"HorizontalLine;", "─"}, 2066 | .{"InvisibleComma;", "⁣"}, 2067 | .{"InvisibleTimes;", "⁢"}, 2068 | .{"LeftDownVector;", "⇃"}, 2069 | .{"leftleftarrows;", "⇇"}, 2070 | .{"LeftRightArrow;", "↔"}, 2071 | .{"Leftrightarrow;", "⇔"}, 2072 | .{"leftrightarrow;", "↔"}, 2073 | .{"leftthreetimes;", "⋋"}, 2074 | .{"LessSlantEqual;", "⩽"}, 2075 | .{"LongRightArrow;", "⟶"}, 2076 | .{"Longrightarrow;", "⟹"}, 2077 | .{"longrightarrow;", "⟶"}, 2078 | .{"looparrowright;", "↬"}, 2079 | .{"LowerLeftArrow;", "↙"}, 2080 | .{"NestedLessLess;", "≪"}, 2081 | .{"NotGreaterLess;", "≹"}, 2082 | .{"NotLessGreater;", "≸"}, 2083 | .{"NotSubsetEqual;", "⊈"}, 2084 | .{"NotVerticalBar;", "∤"}, 2085 | .{"nshortparallel;", "∦"}, 2086 | .{"ntriangleright;", "⋫"}, 2087 | .{"OpenCurlyQuote;", "‘"}, 2088 | .{"ReverseElement;", "∋"}, 2089 | .{"rightarrowtail;", "↣"}, 2090 | .{"rightharpoonup;", "⇀"}, 2091 | .{"RightTeeVector;", "⥛"}, 2092 | .{"RightVectorBar;", "⥓"}, 2093 | .{"ShortDownArrow;", "↓"}, 2094 | .{"ShortLeftArrow;", "←"}, 2095 | .{"SquareSuperset;", "⊐"}, 2096 | .{"TildeFullEqual;", "≅"}, 2097 | .{"trianglelefteq;", "⊴"}, 2098 | .{"upharpoonright;", "↾"}, 2099 | .{"UpperLeftArrow;", "↖"}, 2100 | .{"ZeroWidthSpace;", "​"}, 2101 | .{"bigtriangledown;", "▽"}, 2102 | .{"circlearrowleft;", "↺"}, 2103 | .{"CloseCurlyQuote;", "’"}, 2104 | .{"ContourIntegral;", "∮"}, 2105 | .{"curvearrowright;", "↷"}, 2106 | .{"DoubleDownArrow;", "⇓"}, 2107 | .{"DoubleLeftArrow;", "⇐"}, 2108 | .{"downharpoonleft;", "⇃"}, 2109 | .{"DownRightVector;", "⇁"}, 2110 | .{"leftharpoondown;", "↽"}, 2111 | .{"leftrightarrows;", "⇆"}, 2112 | .{"LeftRightVector;", "⥎"}, 2113 | .{"LeftTriangleBar;", "⧏"}, 2114 | .{"LeftUpTeeVector;", "⥠"}, 2115 | .{"LeftUpVectorBar;", "⥘"}, 2116 | .{"LowerRightArrow;", "↘"}, 2117 | .{"nLeftrightarrow;", "⇎"}, 2118 | .{"nleftrightarrow;", "↮"}, 2119 | .{"NotGreaterEqual;", "≱"}, 2120 | .{"NotGreaterTilde;", "≵"}, 2121 | .{"NotHumpDownHump;", "≎̸"}, 2122 | .{"NotLeftTriangle;", "⋪"}, 2123 | .{"NotSquareSubset;", "⊏̸"}, 2124 | .{"ntrianglelefteq;", "⋬"}, 2125 | .{"OverParenthesis;", "⏜"}, 2126 | .{"RightDownVector;", "⇂"}, 2127 | .{"rightleftarrows;", "⇄"}, 2128 | .{"rightsquigarrow;", "↝"}, 2129 | .{"rightthreetimes;", "⋌"}, 2130 | .{"ShortRightArrow;", "→"}, 2131 | .{"straightepsilon;", "ϵ"}, 2132 | .{"trianglerighteq;", "⊵"}, 2133 | .{"UpperRightArrow;", "↗"}, 2134 | .{"vartriangleleft;", "⊲"}, 2135 | .{"circlearrowright;", "↻"}, 2136 | .{"DiacriticalAcute;", "´"}, 2137 | .{"DiacriticalGrave;", "`"}, 2138 | .{"DiacriticalTilde;", "˜"}, 2139 | .{"DoubleRightArrow;", "⇒"}, 2140 | .{"DownArrowUpArrow;", "⇵"}, 2141 | .{"downharpoonright;", "⇂"}, 2142 | .{"EmptySmallSquare;", "◻"}, 2143 | .{"GreaterEqualLess;", "⋛"}, 2144 | .{"GreaterFullEqual;", "≧"}, 2145 | .{"LeftAngleBracket;", "⟨"}, 2146 | .{"LeftUpDownVector;", "⥑"}, 2147 | .{"LessEqualGreater;", "⋚"}, 2148 | .{"NonBreakingSpace;", " "}, 2149 | .{"NotPrecedesEqual;", "⪯̸"}, 2150 | .{"NotRightTriangle;", "⋫"}, 2151 | .{"NotSucceedsEqual;", "⪰̸"}, 2152 | .{"NotSucceedsTilde;", "≿̸"}, 2153 | .{"NotSupersetEqual;", "⊉"}, 2154 | .{"ntrianglerighteq;", "⋭"}, 2155 | .{"rightharpoondown;", "⇁"}, 2156 | .{"rightrightarrows;", "⇉"}, 2157 | .{"RightTriangleBar;", "⧐"}, 2158 | .{"RightUpTeeVector;", "⥜"}, 2159 | .{"RightUpVectorBar;", "⥔"}, 2160 | .{"twoheadleftarrow;", "↞"}, 2161 | .{"UnderParenthesis;", "⏝"}, 2162 | .{"UpArrowDownArrow;", "⇅"}, 2163 | .{"vartriangleright;", "⊳"}, 2164 | .{"blacktriangledown;", "▾"}, 2165 | .{"blacktriangleleft;", "◂"}, 2166 | .{"DoubleUpDownArrow;", "⇕"}, 2167 | .{"DoubleVerticalBar;", "∥"}, 2168 | .{"DownLeftTeeVector;", "⥞"}, 2169 | .{"DownLeftVectorBar;", "⥖"}, 2170 | .{"FilledSmallSquare;", "◼"}, 2171 | .{"GreaterSlantEqual;", "⩾"}, 2172 | .{"LeftDoubleBracket;", "⟦"}, 2173 | .{"LeftDownTeeVector;", "⥡"}, 2174 | .{"LeftDownVectorBar;", "⥙"}, 2175 | .{"leftrightharpoons;", "⇋"}, 2176 | .{"LeftTriangleEqual;", "⊴"}, 2177 | .{"NegativeThinSpace;", "​"}, 2178 | .{"NotGreaterGreater;", "≫̸"}, 2179 | .{"NotLessSlantEqual;", "⩽̸"}, 2180 | .{"NotNestedLessLess;", "⪡̸"}, 2181 | .{"NotReverseElement;", "∌"}, 2182 | .{"NotSquareSuperset;", "⊐̸"}, 2183 | .{"NotTildeFullEqual;", "≇"}, 2184 | .{"RightAngleBracket;", "⟩"}, 2185 | .{"rightleftharpoons;", "⇌"}, 2186 | .{"RightUpDownVector;", "⥏"}, 2187 | .{"SquareSubsetEqual;", "⊑"}, 2188 | .{"twoheadrightarrow;", "↠"}, 2189 | .{"VerticalSeparator;", "❘"}, 2190 | .{"blacktriangleright;", "▸"}, 2191 | .{"DownRightTeeVector;", "⥟"}, 2192 | .{"DownRightVectorBar;", "⥗"}, 2193 | .{"LongLeftRightArrow;", "⟷"}, 2194 | .{"Longleftrightarrow;", "⟺"}, 2195 | .{"longleftrightarrow;", "⟷"}, 2196 | .{"NegativeThickSpace;", "​"}, 2197 | .{"NotLeftTriangleBar;", "⧏̸"}, 2198 | .{"PrecedesSlantEqual;", "≼"}, 2199 | .{"ReverseEquilibrium;", "⇋"}, 2200 | .{"RightDoubleBracket;", "⟧"}, 2201 | .{"RightDownTeeVector;", "⥝"}, 2202 | .{"RightDownVectorBar;", "⥕"}, 2203 | .{"RightTriangleEqual;", "⊵"}, 2204 | .{"SquareIntersection;", "⊓"}, 2205 | .{"SucceedsSlantEqual;", "≽"}, 2206 | .{"DoubleLongLeftArrow;", "⟸"}, 2207 | .{"DownLeftRightVector;", "⥐"}, 2208 | .{"LeftArrowRightArrow;", "⇆"}, 2209 | .{"leftrightsquigarrow;", "↭"}, 2210 | .{"NegativeMediumSpace;", "​"}, 2211 | .{"NotGreaterFullEqual;", "≧̸"}, 2212 | .{"NotRightTriangleBar;", "⧐̸"}, 2213 | .{"RightArrowLeftArrow;", "⇄"}, 2214 | .{"SquareSupersetEqual;", "⊒"}, 2215 | .{"CapitalDifferentialD;", "ⅅ"}, 2216 | .{"DoubleLeftRightArrow;", "⇔"}, 2217 | .{"DoubleLongRightArrow;", "⟹"}, 2218 | .{"EmptyVerySmallSquare;", "▫"}, 2219 | .{"NestedGreaterGreater;", "≫"}, 2220 | .{"NotDoubleVerticalBar;", "∦"}, 2221 | .{"NotGreaterSlantEqual;", "⩾̸"}, 2222 | .{"NotLeftTriangleEqual;", "⋬"}, 2223 | .{"NotSquareSubsetEqual;", "⋢"}, 2224 | .{"OpenCurlyDoubleQuote;", "“"}, 2225 | .{"ReverseUpEquilibrium;", "⥯"}, 2226 | .{"CloseCurlyDoubleQuote;", "”"}, 2227 | .{"DoubleContourIntegral;", "∯"}, 2228 | .{"FilledVerySmallSquare;", "▪"}, 2229 | .{"NegativeVeryThinSpace;", "​"}, 2230 | .{"NotPrecedesSlantEqual;", "⋠"}, 2231 | .{"NotRightTriangleEqual;", "⋭"}, 2232 | .{"NotSucceedsSlantEqual;", "⋡"}, 2233 | .{"DiacriticalDoubleAcute;", "˝"}, 2234 | .{"NotSquareSupersetEqual;", "⋣"}, 2235 | .{"NotNestedGreaterGreater;", "⪢̸"}, 2236 | .{"ClockwiseContourIntegral;", "∲"}, 2237 | .{"DoubleLongLeftRightArrow;", "⟺"}, 2238 | .{"CounterClockwiseContourIntegral;", "∳"} 2239 | }; 2240 | 2241 | var hashmap = StringHashMap([]const u8).init(allocator.*); 2242 | 2243 | inline for (pairs) |pair| { 2244 | _ = hashmap.put(pair.@"0", pair.@"1") catch unreachable; 2245 | } 2246 | 2247 | return hashmap; 2248 | } 2249 | -------------------------------------------------------------------------------- /src/node.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const Token = @import("token.zig").Token; 3 | const ArrayList = std.ArrayList; 4 | const StringHashMap = std.hash_map.StringHashMap; 5 | const ParseError = @import("parse_error.zig").ParseError; 6 | 7 | pub const Node = union(enum) { 8 | Document: Document, 9 | DocumentType: DocumentType, 10 | DocumentFragment: DocumentFragment, 11 | Element: Element, 12 | Text: Text, 13 | ProcessingInstruction: ProcessingInstruction, 14 | Comment: Comment, 15 | }; 16 | 17 | pub const Document = struct { 18 | const Self = @This(); 19 | 20 | allocator: *std.mem.Allocator, 21 | title: ?[]const u8 = null, 22 | dir: ?[]const u8 = null, 23 | quirksMode: bool = false, 24 | limitedQuirksMode: bool = false, 25 | doctype: ?DocumentType = null, 26 | body: ?Element = null, 27 | head: ?Element = null, 28 | images: ArrayList(Element), 29 | embeds: ArrayList(Element), 30 | plugins: ArrayList(Element), 31 | links: ArrayList(Element), 32 | forms: ArrayList(Element), 33 | scripts: ArrayList(Element), 34 | parseErrors: ArrayList(ParseError), 35 | currentScript: ?Element = null, 36 | children: ArrayList(Node), 37 | throwOnDynamicMarkupInsertionCounter: usize = 0, 38 | 39 | pub fn init(allocator: *std.mem.Allocator) Document { 40 | return Document{ 41 | .allocator = allocator, 42 | .images = ArrayList(Element).init(allocator), 43 | .embeds = ArrayList(Element).init(allocator), 44 | .plugins = ArrayList(Element).init(allocator), 45 | .links = ArrayList(Element).init(allocator), 46 | .forms = ArrayList(Element).init(allocator), 47 | .scripts = ArrayList(Element).init(allocator), 48 | .children = ArrayList(Node).init(allocator), 49 | .parseErrors = ArrayList(ParseError).init(allocator), 50 | }; 51 | } 52 | 53 | pub fn appendNode(self: *Self, node: Node) void { 54 | self.children.append(node) catch unreachable; 55 | } 56 | 57 | pub fn nodeCount(self: Self) usize { 58 | return self.children.items.len; 59 | } 60 | 61 | pub fn popNode(self: *Self) ?Node { 62 | return self.children.popOrNull(); 63 | } 64 | }; 65 | 66 | pub const DocumentType = struct { 67 | const Self = @This(); 68 | 69 | name: []const u8, 70 | publicId: []const u8, 71 | systemId: []const u8, 72 | }; 73 | 74 | pub const DocumentFragment = struct { 75 | const Self = @This(); 76 | }; 77 | 78 | pub const Element = struct { 79 | const Self = @This(); 80 | 81 | const Namespace = enum { 82 | HTML, 83 | MathML, 84 | SVG, 85 | XLink, 86 | XML, 87 | XMLNS, 88 | 89 | pub fn toUri(self: Namespace) []const u8 { 90 | return switch (self) { 91 | .HTML => "http://www.w3.org/1999/xhtml", 92 | .MathML => "http://www.w3.org/1998/Math/MathML", 93 | .SVG => "http://www.w3.org/2000/svg", 94 | .XLink => "http://www.w3.org/1999/xlink", 95 | .XML => "http://www.w3.org/XML/1998/namespace", 96 | .XMLNS => "http://www.w3.org/2000/xmlns/", 97 | }; 98 | } 99 | }; 100 | 101 | namespace: Namespace, 102 | prefix: ?[]const u8, 103 | localName: []const u8, 104 | tagName: []const u8, 105 | 106 | id: []const u8, 107 | className: []const u8, 108 | classList: ArrayList([]const u8), 109 | slot: []const u8, 110 | 111 | document: Document, 112 | attributes: StringHashMap([]const u8), 113 | 114 | pub fn init(local_name: []const u8, document: Document, namespace: Namespace, token: ?Token) Element { 115 | var definition: ?Element = null; // TODO: Look up custom element definition 116 | 117 | return Element{ 118 | .name = local_name, 119 | .document = document, 120 | .namespace = namespace, 121 | .attributes = attributes, 122 | .prefix = null, 123 | .is = null, 124 | .synchronousCustomElements = false, 125 | }; 126 | } 127 | 128 | pub fn namespaceUri(self: Self) []const u8 { 129 | return self.namespace.toUri(); 130 | } 131 | 132 | pub fn hasAttributes(self: Self) bool { 133 | return self.attributes.items().len > 0; 134 | } 135 | 136 | pub fn getAttributeNames(self: Self) [][]const u8 {} 137 | 138 | pub fn isInNamespace(self: Self, namespace: Namespace) bool { 139 | return self.namespace == namespace; 140 | } 141 | 142 | pub fn isHTMLIntegrationPoint(self: Self) bool { 143 | return false; 144 | } 145 | 146 | pub fn isMathMLTextIntegrationPoint(self: Self) bool { 147 | return false; 148 | } 149 | }; 150 | 151 | pub const Text = struct { 152 | const Self = @This(); 153 | }; 154 | 155 | pub const ProcessingInstruction = struct { 156 | const Self = @This(); 157 | }; 158 | 159 | pub const Comment = struct { 160 | const Self = @This(); 161 | 162 | data: []const u8 163 | }; 164 | -------------------------------------------------------------------------------- /src/parse_error.zig: -------------------------------------------------------------------------------- 1 | pub const ParseError = error { 2 | Default, 3 | AbruptClosingOfEmptyComment, 4 | AbruptDoctypePublicIdentifier, 5 | AbruptDoctypeSystemIdentifier, 6 | AbsenceOfDigitsInNumericCharacterReference, 7 | CDATAInHtmlContent, 8 | CharacterReferenceOutsideUnicodeRange, 9 | ControlCharacterInInputStream, 10 | ControlCharacterReference, 11 | EndTagWithAttributes, 12 | DuplicateAttribute, 13 | EndTagWithTrailingSolidus, 14 | EofBeforeTagName, 15 | EofInCDATA, 16 | EofInComment, 17 | EofInDOCTYPE, 18 | EofInScriptHTMLCommentLikeText, 19 | EofInTag, 20 | IncorrectlyClosedComment, 21 | IncorrectlyOpenedComment, 22 | InvalidCharacterSequenceAfterDoctypeName, 23 | InvalidFirstCharacterOfTagName, 24 | MissingAttributeValue, 25 | MissingDoctypeName, 26 | MissingDoctypePublicIdentifier, 27 | MissingDoctypeSystemIdentifier, 28 | MissingEndTagName, 29 | MissingQuoteBeforeDoctypePublicIdentifier, 30 | MissingQuoteBeforeDoctypeSystemIdentifier, 31 | MissingSemicolonAfterCharacterReference, 32 | MissingWhitespaceAfterDoctypePublicKeyword, 33 | MissingWhitespaceAfterDoctypeSystemKeyword, 34 | MissingWhitespaceBeforeDoctypeName, 35 | MissingWhitespaceBetweenAttributes, 36 | MissingWhitespaceBetweenDoctypePublicAndSystemIdentifiers, 37 | NestedComment, 38 | NoncharacterCharacterReference, 39 | NoncharacterInInputStream, 40 | NonVoidHTMLElementStartTagWithTrailingSolidus, 41 | NullCharacterReference, 42 | SurrogateCharacterReference, 43 | SurrogateInInputStream, 44 | UnexpectedCharacterAfterDoctypeSystemIdentifier, 45 | UnexpectedCharacterInAttributeName, 46 | UnexpectedCharacterInUnquotedAttributeValue, 47 | UnexpectedEqualsSignBeforeAttributeName, 48 | UnexpectedNullCharacter, 49 | UnexpectedQuestionMarkInsteadOfTagName, 50 | UnexpectedSolidusInTag, 51 | UnknownNamedCharacterReference, 52 | }; -------------------------------------------------------------------------------- /src/parser.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const mem = std.mem; 3 | const ArrayList = std.ArrayList; 4 | const node = @import("node.zig"); 5 | 6 | const Document = node.Document; 7 | const Element = node.Element; 8 | 9 | const Token = @import("token.zig").Token; 10 | const Tokenizer = @import("tokenizer.zig").Tokenizer; 11 | const ParseError = @import("parse_error.zig").ParseError; 12 | 13 | pub const Parser = struct { 14 | const Self = @This(); 15 | 16 | /// The insertion mode is a state variable that controls the primary operation of the tree construction stage. 17 | /// https://html.spec.whatwg.org/multipage/parsing.html#the-insertion-mode 18 | pub const InsertionMode = enum { 19 | Initial, 20 | BeforeHtml, 21 | BeforeHead, 22 | InHead, 23 | InHeadNoscript, 24 | AfterHead, 25 | InBody, 26 | Text, 27 | InTable, 28 | InTableText, 29 | InCaption, 30 | InColumnGroup, 31 | InTableBody, 32 | InRow, 33 | InCell, 34 | InSelect, 35 | InSelectInTable, 36 | InTemplate, 37 | AfterBody, 38 | InFrameset, 39 | AfterFrameset, 40 | AfterAfterBody, 41 | AfterAfterFrameset, 42 | }; 43 | 44 | allocator: *mem.Allocator, 45 | tokenizer: *Tokenizer, 46 | stackOfOpenElements: ArrayList(Element), 47 | insertionMode: InsertionMode, 48 | reprocess: bool = false, 49 | lastToken: Token = undefined, 50 | context: ?Element = null, 51 | 52 | pub fn init(allocator: *mem.Allocator, tokenizer: *Tokenizer) Parser { 53 | var stackOfOpenElements = ArrayList(Element).init(allocator); 54 | return Parser { 55 | .allocator = allocator, 56 | .tokenizer = tokenizer, 57 | .stackOfOpenElements = stackOfOpenElements, 58 | .insertionMode = .Initial, 59 | }; 60 | } 61 | 62 | pub fn adjustedCurrentNode(self: *Self) Element { 63 | // The adjusted current node is the context element if the parser was created as part of the HTML fragment 64 | // parsing algorithm and the stack of open elements has only one element in it (fragment case); otherwise, 65 | // the adjusted current node is the current node. 66 | 67 | if (self.context) |ctx| { 68 | if (self.stackOfOpenElements.items.len == 1) { 69 | return ctx; 70 | } 71 | } 72 | 73 | var elementStack = self.stackOfOpenElements.items; 74 | return elementStack[elementStack.len - 1]; 75 | } 76 | 77 | pub fn parse(self: *Self) !Document { 78 | var document = Document.init(self.allocator); 79 | while (true) { 80 | var token: ?Token = null; 81 | if (self.reprocess) { 82 | token = self.lastToken; 83 | } else { 84 | token = self.tokenizer.nextToken() catch |err| { 85 | document.parseErrors.append(err) catch unreachable; 86 | continue; 87 | }; 88 | } 89 | 90 | if (token) |tok| { 91 | self.lastToken = tok; 92 | 93 | if (// If the stack of open elements is empty 94 | (self.stackOfOpenElements.items.len == 0) or 95 | 96 | // If the adjusted current node is an element in the HTML namespace 97 | (self.adjustedCurrentNode().isInNamespace(.HTML)) or 98 | 99 | // If the adjusted current node is a MathML text integration point and the token is a start tag 100 | // whose tag name is neither "mglyph" nor "malignmark" 101 | (self.adjustedCurrentNode().isMathMLTextIntegrationPoint() and 102 | tok == Token.StartTag and 103 | (mem.eql(u8, tok.StartTag.name.?, "mglyph") 104 | or (mem.eql(u8, tok.StartTag.name.?, "malignmark")))) or 105 | 106 | // If the adjusted current node is a MathML text integration point and the token is a character token 107 | (self.adjustedCurrentNode().isMathMLTextIntegrationPoint() and 108 | tok == Token.Character) or 109 | 110 | // If the adjusted current node is a MathML annotation-xml element and the token is a start tag whose tag name is "svg" 111 | (mem.eql(u8, self.adjustedCurrentNode().name, "annotation-xml") and 112 | tok == Token.StartTag and 113 | mem.eql(u8, tok.StartTag.name.?, "svg")) or 114 | 115 | // If the adjusted current node is an HTML integration point and the token is a start tag 116 | (self.adjustedCurrentNode().isHTMLIntegrationPoint() and tok == Token.StartTag) or 117 | 118 | // If the adjusted current node is an HTML integration point and the token is a character token 119 | (self.adjustedCurrentNode().isHTMLIntegrationPoint() and tok == Token.Character) or 120 | 121 | // If the token is an end-of-file token 122 | (tok == Token.EndOfFile)) { 123 | switch (self.insertionMode) { 124 | .Initial => { 125 | self.handleInitialInsertionMode(&document, tok); 126 | }, 127 | .BeforeHtml => { 128 | self.handleBeforeHtmlInsertionMode(&document, tok); 129 | }, 130 | else => { 131 | std.debug.warn("{}\n", .{ self.insertionMode }); 132 | break; 133 | } 134 | } 135 | } else { 136 | // TODO: Process the token according to the rules given in the section for parsing tokens in foreign content. 137 | unreachable; 138 | } 139 | } 140 | } 141 | return document; 142 | } 143 | 144 | // pub fn parseFragment(self: *Self, input: []const u8) !Document { } 145 | 146 | fn handleInitialInsertionMode(self: *Self, document: *Document, token: Token) void { 147 | switch (token) { 148 | Token.Character => |tok| { 149 | if (tok.data == '\t' or tok.data == ' ' or tok.data == 0x000A or 150 | tok.data == 0x000C or tok.data == 0x000D) { 151 | // Ignore and do nothing 152 | return; 153 | } 154 | }, 155 | Token.Comment => |tok| { 156 | document.appendNode(node.Node { .Comment = .{ .data = tok.data.? } }); 157 | return; 158 | }, 159 | Token.DOCTYPE => |tok| { 160 | if ((tok.name != null and !mem.eql(u8, tok.name.?, "html")) or 161 | (tok.publicIdentifier != null and tok.publicIdentifier.?.len != 0) or 162 | (tok.systemIdentifier != null and !mem.eql(u8, tok.systemIdentifier.?, "about:legacy-compat"))) { 163 | document.parseErrors.append(ParseError.Default) catch unreachable; 164 | } 165 | 166 | var doctype = node.DocumentType { 167 | .name = if (tok.name == null) "" else tok.name.?, 168 | .publicId = if (tok.publicIdentifier == null) "" else tok.publicIdentifier.?, 169 | .systemId = if (tok.systemIdentifier == null) "" else tok.systemIdentifier.?, 170 | }; 171 | 172 | document.appendNode(node.Node { .DocumentType = doctype }); 173 | document.doctype = doctype; 174 | 175 | if (tok.forceQuirks or 176 | mem.eql(u8, doctype.publicId, "-//W3O//DTD W3 HTML Strict 3.0//EN//") or 177 | mem.eql(u8, doctype.publicId, "-/W3C/DTD HTML 4.0 Transitional/EN") or 178 | mem.eql(u8, doctype.publicId, "HTML") or 179 | mem.eql(u8, doctype.systemId, "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd") or 180 | mem.startsWith(u8, doctype.publicId, "+//Silmaril//dtd html Pro v0r11 19970101//") or 181 | mem.startsWith(u8, doctype.publicId, "-//AS//DTD HTML 3.0 asWedit + extensions//") or 182 | mem.startsWith(u8, doctype.publicId, "-//AdvaSoft Ltd//DTD HTML 3.0 asWedit + extensions//") or 183 | mem.startsWith(u8, doctype.publicId, "-//IETF//DTD HTML 2.0 Level 1//") or 184 | mem.startsWith(u8, doctype.publicId, "-//IETF//DTD HTML 2.0 Level 2//") or 185 | mem.startsWith(u8, doctype.publicId, "-//IETF//DTD HTML 2.0 Strict Level 1//") or 186 | mem.startsWith(u8, doctype.publicId, "-//IETF//DTD HTML 2.0 Strict Level 2//") or 187 | mem.startsWith(u8, doctype.publicId, "-//IETF//DTD HTML 2.0 Strict//") or 188 | mem.startsWith(u8, doctype.publicId, "-//IETF//DTD HTML 2.0//") or 189 | mem.startsWith(u8, doctype.publicId, "-//IETF//DTD HTML 2.1E//") or 190 | mem.startsWith(u8, doctype.publicId, "-//IETF//DTD HTML 3.0//") or 191 | mem.startsWith(u8, doctype.publicId, "-//IETF//DTD HTML 3.2 Final//") or 192 | mem.startsWith(u8, doctype.publicId, "-//IETF//DTD HTML 3.2//") or 193 | mem.startsWith(u8, doctype.publicId, "-//IETF//DTD HTML 3//") or 194 | mem.startsWith(u8, doctype.publicId, "-//IETF//DTD HTML Level 0//") or 195 | mem.startsWith(u8, doctype.publicId, "-//IETF//DTD HTML Level 1//") or 196 | mem.startsWith(u8, doctype.publicId, "-//IETF//DTD HTML Level 2//") or 197 | mem.startsWith(u8, doctype.publicId, "-//IETF//DTD HTML Level 3//") or 198 | mem.startsWith(u8, doctype.publicId, "-//IETF//DTD HTML Strict Level 0//") or 199 | mem.startsWith(u8, doctype.publicId, "-//IETF//DTD HTML Strict Level 1//") or 200 | mem.startsWith(u8, doctype.publicId, "-//IETF//DTD HTML Strict Level 2//") or 201 | mem.startsWith(u8, doctype.publicId, "-//IETF//DTD HTML Strict Level 3//") or 202 | mem.startsWith(u8, doctype.publicId, "-//IETF//DTD HTML Strict//") or 203 | mem.startsWith(u8, doctype.publicId, "-//IETF//DTD HTML//") or 204 | mem.startsWith(u8, doctype.publicId, "-//Metrius//DTD Metrius Presentational//") or 205 | mem.startsWith(u8, doctype.publicId, "-//Microsoft//DTD Internet Explorer 2.0 HTML Strict//") or 206 | mem.startsWith(u8, doctype.publicId, "-//Microsoft//DTD Internet Explorer 2.0 HTML//") or 207 | mem.startsWith(u8, doctype.publicId, "-//Microsoft//DTD Internet Explorer 2.0 Tables//") or 208 | mem.startsWith(u8, doctype.publicId, "-//Microsoft//DTD Internet Explorer 3.0 HTML Strict//") or 209 | mem.startsWith(u8, doctype.publicId, "-//Microsoft//DTD Internet Explorer 3.0 HTML//") or 210 | mem.startsWith(u8, doctype.publicId, "-//Microsoft//DTD Internet Explorer 3.0 Tables//") or 211 | mem.startsWith(u8, doctype.publicId, "-//Netscape Comm. Corp.//DTD HTML//") or 212 | mem.startsWith(u8, doctype.publicId, "-//Netscape Comm. Corp.//DTD Strict HTML//") or 213 | mem.startsWith(u8, doctype.publicId, "-//O'Reilly and Associates//DTD HTML 2.0//") or 214 | mem.startsWith(u8, doctype.publicId, "-//O'Reilly and Associates//DTD HTML Extended 1.0//") or 215 | mem.startsWith(u8, doctype.publicId, "-//O'Reilly and Associates//DTD HTML Extended Relaxed 1.0//") or 216 | mem.startsWith(u8, doctype.publicId, "-//SQ//DTD HTML 2.0 HoTMetaL + extensions//") or 217 | mem.startsWith(u8, doctype.publicId, "-//SoftQuad Software//DTD HoTMetaL PRO 6.0::19990601::extensions to HTML 4.0//") or 218 | mem.startsWith(u8, doctype.publicId, "-//SoftQuad//DTD HoTMetaL PRO 4.0::19971010::extensions to HTML 4.0//") or 219 | mem.startsWith(u8, doctype.publicId, "-//Spyglass//DTD HTML 2.0 Extended//") or 220 | mem.startsWith(u8, doctype.publicId, "-//Sun Microsystems Corp.//DTD HotJava HTML//") or 221 | mem.startsWith(u8, doctype.publicId, "-//Sun Microsystems Corp.//DTD HotJava Strict HTML//") or 222 | mem.startsWith(u8, doctype.publicId, "-//W3C//DTD HTML 3 1995-03-24//") or 223 | mem.startsWith(u8, doctype.publicId, "-//W3C//DTD HTML 3.2 Draft//") or 224 | mem.startsWith(u8, doctype.publicId, "-//W3C//DTD HTML 3.2 Final//") or 225 | mem.startsWith(u8, doctype.publicId, "-//W3C//DTD HTML 3.2//") or 226 | mem.startsWith(u8, doctype.publicId, "-//W3C//DTD HTML 3.2S Draft//") or 227 | mem.startsWith(u8, doctype.publicId, "-//W3C//DTD HTML 4.0 Frameset//") or 228 | mem.startsWith(u8, doctype.publicId, "-//W3C//DTD HTML 4.0 Transitional//") or 229 | mem.startsWith(u8, doctype.publicId, "-//W3C//DTD HTML Experimental 19960712//") or 230 | mem.startsWith(u8, doctype.publicId, "-//W3C//DTD HTML Experimental 970421//") or 231 | mem.startsWith(u8, doctype.publicId, "-//W3C//DTD W3 HTML//") or 232 | mem.startsWith(u8, doctype.publicId, "-//W3O//DTD W3 HTML 3.0//") or 233 | mem.startsWith(u8, doctype.publicId, "-//WebTechs//DTD Mozilla HTML 2.0//") or 234 | mem.startsWith(u8, doctype.publicId, "-//WebTechs//DTD Mozilla HTML//") or 235 | mem.startsWith(u8, doctype.systemId, "-//W3C//DTD HTML 4.01 Frameset//") or 236 | mem.startsWith(u8, doctype.systemId, "-//W3C//DTD HTML 4.01 Transitional//")) { 237 | document.quirksMode = true; 238 | return; 239 | } else if (mem.startsWith(u8, doctype.publicId, "-//W3C//DTD XHTML 1.0 Frameset//") or 240 | mem.startsWith(u8, doctype.publicId, "-//W3C//DTD XHTML 1.0 Transitional//") or 241 | (doctype.systemId.len != 0 and mem.startsWith(u8, doctype.systemId, "-//W3C//DTD HTML 4.01 Frameset//")) or 242 | (doctype.systemId.len != 0 and mem.startsWith(u8, doctype.systemId, "-//W3C//DTD HTML 4.01 Transitional//"))) { 243 | self.insertionMode = .BeforeHtml; 244 | return; 245 | } 246 | }, 247 | else => {} 248 | } 249 | 250 | self.reprocess = true; 251 | self.insertionMode = .BeforeHtml; 252 | document.quirksMode = true; 253 | document.parseErrors.append(ParseError.Default) catch unreachable; 254 | } 255 | 256 | fn handleBeforeHtmlInsertionMode(self: *Self, document: *Document, token: Token) void { 257 | switch (token) { 258 | Token.DOCTYPE => { 259 | document.parseErrors.append(ParseError.Default) catch unreachable; 260 | return; 261 | }, 262 | Token.Comment => |tok| { 263 | document.appendNode(node.Node { .Comment = .{ .data = tok.data.? } }); 264 | return; 265 | }, 266 | Token.Character => |tok| { 267 | if (tok.data == '\t' or tok.data == ' ' or tok.data == 0x000A or 268 | tok.data == 0x000C or tok.data == 0x000D) { 269 | // Ignore and do nothing 270 | return; 271 | } 272 | }, 273 | Token.StartTag => |tok| { 274 | if (mem.eql(u8, tok.name.?, "html")) { 275 | var element = self.createElementForToken(document, token); 276 | } 277 | }, 278 | else => {} 279 | } 280 | } 281 | 282 | fn createElementForToken(self: Self, document: *Document, token: Token) Element { 283 | var local_name = token.StartTag.name.?; 284 | var is = token.StartTag.attributes.get("is"); 285 | var definition: ?Element = null; // TODO: Look up custom element definition 286 | 287 | var will_execute_script = definition != null and self.context == null; 288 | if (will_execute_script) { 289 | // will execute script 290 | document.throwOnDynamicMarkupInsertionCounter += 1; 291 | // TODO: If the JavaScript execution context stack is empty, then perform a microtask checkpoint. 292 | // TODO: Push a new element queue onto document's relevant agent's custom element reactions stack. 293 | } 294 | 295 | var element = Element.init(); 296 | } 297 | }; -------------------------------------------------------------------------------- /src/token.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const mem = std.mem; 3 | const StringHashMap = std.hash_map.StringHashMap; 4 | const ArrayList = std.ArrayList; 5 | 6 | /// Represents a token to be emitted by the {{Tokenizer}}. 7 | pub const Token = union(enum) { 8 | DOCTYPE: struct { 9 | name: ?[]const u8 = null, 10 | publicIdentifier: ?[]const u8 = null, 11 | systemIdentifier: ?[]const u8 = null, 12 | forceQuirks: bool = false, 13 | }, 14 | StartTag: struct { 15 | name: ?[]const u8 = null, 16 | selfClosing: bool = false, 17 | attributes: StringHashMap([]const u8), 18 | 19 | pub fn format(value: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { 20 | try writer.writeAll("{ "); 21 | try writer.print(".name = {any}, .selfClosing = {any}", .{ value.name, value.selfClosing }); 22 | var it = value.attributes.iterator(); 23 | if (value.attributes.count() > 0) { 24 | try writer.writeAll(", attributes = .{ "); 25 | var i: u32 = 0; 26 | while (it.next()) |entry| { 27 | try writer.print("{s}: \"{s}\"", .{ entry.key_ptr.*, entry.value_ptr.* }); 28 | if (i + 1 < value.attributes.count()) 29 | try writer.writeAll(", "); 30 | } 31 | try writer.writeAll(" }"); 32 | i += 1; 33 | } 34 | try writer.writeAll(" }"); 35 | } 36 | }, 37 | EndTag: struct { 38 | name: ?[]const u8 = null, 39 | /// Ignored past tokenization, only used for errors 40 | selfClosing: bool = false, 41 | /// Ignored past tokenization, only used for errors 42 | attributes: StringHashMap([]const u8), 43 | 44 | pub fn format(value: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { 45 | try writer.writeAll("{ "); 46 | try writer.print(".name = {any}, .selfClosing = {any}", .{ value.name, value.selfClosing }); 47 | try writer.writeAll(" }"); 48 | } 49 | }, 50 | Comment: struct { 51 | data: ?[]const u8 = null, 52 | }, 53 | Character: struct { 54 | data: u21, 55 | 56 | pub fn format(value: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { 57 | var char: [4]u8 = undefined; 58 | var len = std.unicode.utf8Encode(value.data, char[0..]) catch unreachable; 59 | if (char[0] == '\n') { 60 | len = 2; 61 | std.mem.copy(u8, char[0..2], "\\n"); 62 | } 63 | try writer.print("\"{s}\"", .{ char[0..len] }); 64 | } 65 | }, 66 | EndOfFile, 67 | }; 68 | -------------------------------------------------------------------------------- /test/tokenizer-html5lib.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const testing = std.testing; 3 | const Token = @import("zhtml/token").Token; 4 | const Tokenizer = @import("zhtml/tokenizer").Tokenizer; 5 | const ParseError = @import("zhtml/parse_error").ParseError; 6 | 7 | // FIXME: This whole file is rather sloppy with memory 8 | // TODO: Preprocessing the input stream (spec 12.2.3.5) 9 | // TODO: test.doubleEscaped 10 | // TODO: test.lastStartTag 11 | // TODO: If test.doubleEscaped is present and true, then every string within test.output must 12 | // be further unescaped (as described above) before comparing with the tokenizer's output. 13 | // TODO: Run more .test files once the relevant above TODOs are addressed and the tokenizer progresses 14 | 15 | const ignored_tests = [_][]const u8{ 16 | "Unfinished entity", 17 | "Unfinished numeric entity", 18 | "Entity with trailing semicolon (1)", 19 | "Entity with trailing semicolon (2)", 20 | "Entity without trailing semicolon (1)", 21 | "Entity without trailing semicolon (2)", 22 | "Partial entity match at end of file", 23 | "Non-ASCII character reference name", 24 | "Entity + newline", 25 | ";\\uDBC0\\uDC00", 26 | "Empty hex numeric entities", 27 | "Invalid digit in hex numeric entity", 28 | "Empty decimal numeric entities", 29 | "Invalid digit in decimal numeric entity", 30 | "Ampersand, number sign", 31 | "