1/** All valid namespaces in HTML. */ 2export enum NS { 3 HTML = 'http://www.w3.org/1999/xhtml', 4 MATHML = 'http://www.w3.org/1998/Math/MathML', 5 SVG = 'http://www.w3.org/2000/svg', 6 XLINK = 'http://www.w3.org/1999/xlink', 7 XML = 'http://www.w3.org/XML/1998/namespace', 8 XMLNS = 'http://www.w3.org/2000/xmlns/', 9} 10 11export enum ATTRS { 12 TYPE = 'type', 13 ACTION = 'action', 14 ENCODING = 'encoding', 15 PROMPT = 'prompt', 16 NAME = 'name', 17 COLOR = 'color', 18 FACE = 'face', 19 SIZE = 'size', 20} 21 22/** 23 * The mode of the document. 24 * 25 * @see {@link https://dom.spec.whatwg.org/#concept-document-limited-quirks} 26 */ 27export enum DOCUMENT_MODE { 28 NO_QUIRKS = 'no-quirks', 29 QUIRKS = 'quirks', 30 LIMITED_QUIRKS = 'limited-quirks', 31} 32 33export enum TAG_NAMES { 34 A = 'a', 35 ADDRESS = 'address', 36 ANNOTATION_XML = 'annotation-xml', 37 APPLET = 'applet', 38 AREA = 'area', 39 ARTICLE = 'article', 40 ASIDE = 'aside', 41 42 B = 'b', 43 BASE = 'base', 44 BASEFONT = 'basefont', 45 BGSOUND = 'bgsound', 46 BIG = 'big', 47 BLOCKQUOTE = 'blockquote', 48 BODY = 'body', 49 BR = 'br', 50 BUTTON = 'button', 51 52 CAPTION = 'caption', 53 CENTER = 'center', 54 CODE = 'code', 55 COL = 'col', 56 COLGROUP = 'colgroup', 57 58 DD = 'dd', 59 DESC = 'desc', 60 DETAILS = 'details', 61 DIALOG = 'dialog', 62 DIR = 'dir', 63 DIV = 'div', 64 DL = 'dl', 65 DT = 'dt', 66 67 EM = 'em', 68 EMBED = 'embed', 69 70 FIELDSET = 'fieldset', 71 FIGCAPTION = 'figcaption', 72 FIGURE = 'figure', 73 FONT = 'font', 74 FOOTER = 'footer', 75 FOREIGN_OBJECT = 'foreignObject', 76 FORM = 'form', 77 FRAME = 'frame', 78 FRAMESET = 'frameset', 79 80 H1 = 'h1', 81 H2 = 'h2', 82 H3 = 'h3', 83 H4 = 'h4', 84 H5 = 'h5', 85 H6 = 'h6', 86 HEAD = 'head', 87 HEADER = 'header', 88 HGROUP = 'hgroup', 89 HR = 'hr', 90 HTML = 'html', 91 92 I = 'i', 93 IMG = 'img', 94 IMAGE = 'image', 95 INPUT = 'input', 96 IFRAME = 'iframe', 97 98 KEYGEN = 'keygen', 99 100 LABEL = 'label', 101 LI = 'li', 102 LINK = 'link', 103 LISTING = 'listing', 104 105 MAIN = 'main', 106 MALIGNMARK = 'malignmark', 107 MARQUEE = 'marquee', 108 MATH = 'math', 109 MENU = 'menu', 110 META = 'meta', 111 MGLYPH = 'mglyph', 112 MI = 'mi', 113 MO = 'mo', 114 MN = 'mn', 115 MS = 'ms', 116 MTEXT = 'mtext', 117 118 NAV = 'nav', 119 NOBR = 'nobr', 120 NOFRAMES = 'noframes', 121 NOEMBED = 'noembed', 122 NOSCRIPT = 'noscript', 123 124 OBJECT = 'object', 125 OL = 'ol', 126 OPTGROUP = 'optgroup', 127 OPTION = 'option', 128 129 P = 'p', 130 PARAM = 'param', 131 PLAINTEXT = 'plaintext', 132 PRE = 'pre', 133 134 RB = 'rb', 135 RP = 'rp', 136 RT = 'rt', 137 RTC = 'rtc', 138 RUBY = 'ruby', 139 140 S = 's', 141 SCRIPT = 'script', 142 SECTION = 'section', 143 SELECT = 'select', 144 SOURCE = 'source', 145 SMALL = 'small', 146 SPAN = 'span', 147 STRIKE = 'strike', 148 STRONG = 'strong', 149 STYLE = 'style', 150 SUB = 'sub', 151 SUMMARY = 'summary', 152 SUP = 'sup', 153 154 TABLE = 'table', 155 TBODY = 'tbody', 156 TEMPLATE = 'template', 157 TEXTAREA = 'textarea', 158 TFOOT = 'tfoot', 159 TD = 'td', 160 TH = 'th', 161 THEAD = 'thead', 162 TITLE = 'title', 163 TR = 'tr', 164 TRACK = 'track', 165 TT = 'tt', 166 167 U = 'u', 168 UL = 'ul', 169 170 SVG = 'svg', 171 172 VAR = 'var', 173 174 WBR = 'wbr', 175 176 XMP = 'xmp', 177// Unique self closing label 178 WEB = 'web', 179 XCOMPONENT = 'xcomponent', 180 RATING = 'rating', 181 CANVAS = 'canvas', 182 CAMERA = 'camera', 183 AUDIO = 'audio', 184 VIDEO = 'video', 185 SWITCH = 'switch', 186 QRCODE = 'qrcode', 187 PICKER_VIEW = 'picker-view', 188 PICKER = 'picker', 189 PROGRESS = 'progress', 190 SEARCH = 'search', 191 SLIDER = 'slider', 192 CHART = 'chart', 193 CALENDAR = 'calendar', 194 DIVIDER = 'divider', 195 IMAGE_ANIMATOR = 'image-animator', 196} 197 198/** 199 * Tag IDs are numeric IDs for known tag names. 200 * 201 * We use tag IDs to improve the performance of tag name comparisons. 202 */ 203export enum TAG_ID { 204 UNKNOWN, 205 206 A, 207 ADDRESS, 208 ANNOTATION_XML, 209 APPLET, 210 AREA, 211 ARTICLE, 212 ASIDE, 213 214 B, 215 BASE, 216 BASEFONT, 217 BGSOUND, 218 BIG, 219 BLOCKQUOTE, 220 BODY, 221 BR, 222 BUTTON, 223 224 CAPTION, 225 CENTER, 226 CODE, 227 COL, 228 COLGROUP, 229 230 DD, 231 DESC, 232 DETAILS, 233 DIALOG, 234 DIR, 235 DIV, 236 DL, 237 DT, 238 239 EM, 240 EMBED, 241 242 FIELDSET, 243 FIGCAPTION, 244 FIGURE, 245 FONT, 246 FOOTER, 247 FOREIGN_OBJECT, 248 FORM, 249 FRAME, 250 FRAMESET, 251 252 H1, 253 H2, 254 H3, 255 H4, 256 H5, 257 H6, 258 HEAD, 259 HEADER, 260 HGROUP, 261 HR, 262 HTML, 263 264 I, 265 IMG, 266 IMAGE, 267 INPUT, 268 IFRAME, 269 270 KEYGEN, 271 272 LABEL, 273 LI, 274 LINK, 275 LISTING, 276 277 MAIN, 278 MALIGNMARK, 279 MARQUEE, 280 MATH, 281 MENU, 282 META, 283 MGLYPH, 284 MI, 285 MO, 286 MN, 287 MS, 288 MTEXT, 289 290 NAV, 291 NOBR, 292 NOFRAMES, 293 NOEMBED, 294 NOSCRIPT, 295 296 OBJECT, 297 OL, 298 OPTGROUP, 299 OPTION, 300 301 P, 302 PARAM, 303 PLAINTEXT, 304 PRE, 305 306 RB, 307 RP, 308 RT, 309 RTC, 310 RUBY, 311 312 S, 313 SCRIPT, 314 SECTION, 315 SELECT, 316 SOURCE, 317 SMALL, 318 SPAN, 319 STRIKE, 320 STRONG, 321 STYLE, 322 SUB, 323 SUMMARY, 324 SUP, 325 326 TABLE, 327 TBODY, 328 TEMPLATE, 329 TEXTAREA, 330 TFOOT, 331 TD, 332 TH, 333 THEAD, 334 TITLE, 335 TR, 336 TRACK, 337 TT, 338 339 U, 340 UL, 341 342 SVG, 343 344 VAR, 345 346 WBR, 347 348 XMP, 349 WEB, 350 XCOMPONENT, 351 RATING, 352 CANVAS, 353 CAMERA, 354 AUDIO, 355 VIDEO, 356 SWITCH, 357 QRCODE, 358 PICKER_VIEW, 359 PICKER, 360 PROGRESS, 361 SEARCH, 362 SLIDER, 363 CHART, 364 CALENDAR, 365 DIVIDER, 366 IMAGE_ANIMATOR, 367} 368 369const TAG_NAME_TO_ID = new Map<string, TAG_ID>([ 370 [TAG_NAMES.A, TAG_ID.A], 371 [TAG_NAMES.ADDRESS, TAG_ID.ADDRESS], 372 [TAG_NAMES.ANNOTATION_XML, TAG_ID.ANNOTATION_XML], 373 [TAG_NAMES.APPLET, TAG_ID.APPLET], 374 [TAG_NAMES.AREA, TAG_ID.AREA], 375 [TAG_NAMES.ARTICLE, TAG_ID.ARTICLE], 376 [TAG_NAMES.ASIDE, TAG_ID.ASIDE], 377 [TAG_NAMES.B, TAG_ID.B], 378 [TAG_NAMES.BASE, TAG_ID.BASE], 379 [TAG_NAMES.BASEFONT, TAG_ID.BASEFONT], 380 [TAG_NAMES.BGSOUND, TAG_ID.BGSOUND], 381 [TAG_NAMES.BIG, TAG_ID.BIG], 382 [TAG_NAMES.BLOCKQUOTE, TAG_ID.BLOCKQUOTE], 383 [TAG_NAMES.BODY, TAG_ID.BODY], 384 [TAG_NAMES.BR, TAG_ID.BR], 385 [TAG_NAMES.BUTTON, TAG_ID.BUTTON], 386 [TAG_NAMES.CAPTION, TAG_ID.CAPTION], 387 [TAG_NAMES.CENTER, TAG_ID.CENTER], 388 [TAG_NAMES.CODE, TAG_ID.CODE], 389 [TAG_NAMES.COL, TAG_ID.COL], 390 [TAG_NAMES.COLGROUP, TAG_ID.COLGROUP], 391 [TAG_NAMES.DD, TAG_ID.DD], 392 [TAG_NAMES.DESC, TAG_ID.DESC], 393 [TAG_NAMES.DETAILS, TAG_ID.DETAILS], 394 [TAG_NAMES.DIALOG, TAG_ID.DIALOG], 395 [TAG_NAMES.DIR, TAG_ID.DIR], 396 [TAG_NAMES.DIV, TAG_ID.DIV], 397 [TAG_NAMES.DL, TAG_ID.DL], 398 [TAG_NAMES.DT, TAG_ID.DT], 399 [TAG_NAMES.EM, TAG_ID.EM], 400 [TAG_NAMES.EMBED, TAG_ID.EMBED], 401 [TAG_NAMES.FIELDSET, TAG_ID.FIELDSET], 402 [TAG_NAMES.FIGCAPTION, TAG_ID.FIGCAPTION], 403 [TAG_NAMES.FIGURE, TAG_ID.FIGURE], 404 [TAG_NAMES.FONT, TAG_ID.FONT], 405 [TAG_NAMES.FOOTER, TAG_ID.FOOTER], 406 [TAG_NAMES.FOREIGN_OBJECT, TAG_ID.FOREIGN_OBJECT], 407 [TAG_NAMES.FORM, TAG_ID.FORM], 408 [TAG_NAMES.FRAME, TAG_ID.FRAME], 409 [TAG_NAMES.FRAMESET, TAG_ID.FRAMESET], 410 [TAG_NAMES.H1, TAG_ID.H1], 411 [TAG_NAMES.H2, TAG_ID.H2], 412 [TAG_NAMES.H3, TAG_ID.H3], 413 [TAG_NAMES.H4, TAG_ID.H4], 414 [TAG_NAMES.H5, TAG_ID.H5], 415 [TAG_NAMES.H6, TAG_ID.H6], 416 [TAG_NAMES.HEAD, TAG_ID.HEAD], 417 [TAG_NAMES.HEADER, TAG_ID.HEADER], 418 [TAG_NAMES.HGROUP, TAG_ID.HGROUP], 419 [TAG_NAMES.HR, TAG_ID.HR], 420 [TAG_NAMES.HTML, TAG_ID.HTML], 421 [TAG_NAMES.I, TAG_ID.I], 422 [TAG_NAMES.IMG, TAG_ID.IMG], 423 [TAG_NAMES.IMAGE, TAG_ID.IMAGE], 424 [TAG_NAMES.INPUT, TAG_ID.INPUT], 425 [TAG_NAMES.IFRAME, TAG_ID.IFRAME], 426 [TAG_NAMES.KEYGEN, TAG_ID.KEYGEN], 427 [TAG_NAMES.LABEL, TAG_ID.LABEL], 428 [TAG_NAMES.LI, TAG_ID.LI], 429 [TAG_NAMES.LINK, TAG_ID.LINK], 430 [TAG_NAMES.LISTING, TAG_ID.LISTING], 431 [TAG_NAMES.MAIN, TAG_ID.MAIN], 432 [TAG_NAMES.MALIGNMARK, TAG_ID.MALIGNMARK], 433 [TAG_NAMES.MARQUEE, TAG_ID.MARQUEE], 434 [TAG_NAMES.MATH, TAG_ID.MATH], 435 [TAG_NAMES.MENU, TAG_ID.MENU], 436 [TAG_NAMES.META, TAG_ID.META], 437 [TAG_NAMES.MGLYPH, TAG_ID.MGLYPH], 438 [TAG_NAMES.MI, TAG_ID.MI], 439 [TAG_NAMES.MO, TAG_ID.MO], 440 [TAG_NAMES.MN, TAG_ID.MN], 441 [TAG_NAMES.MS, TAG_ID.MS], 442 [TAG_NAMES.MTEXT, TAG_ID.MTEXT], 443 [TAG_NAMES.NAV, TAG_ID.NAV], 444 [TAG_NAMES.NOBR, TAG_ID.NOBR], 445 [TAG_NAMES.NOFRAMES, TAG_ID.NOFRAMES], 446 [TAG_NAMES.NOEMBED, TAG_ID.NOEMBED], 447 [TAG_NAMES.NOSCRIPT, TAG_ID.NOSCRIPT], 448 [TAG_NAMES.OBJECT, TAG_ID.OBJECT], 449 [TAG_NAMES.OL, TAG_ID.OL], 450 [TAG_NAMES.OPTGROUP, TAG_ID.OPTGROUP], 451 [TAG_NAMES.OPTION, TAG_ID.OPTION], 452 [TAG_NAMES.P, TAG_ID.P], 453 [TAG_NAMES.PARAM, TAG_ID.PARAM], 454 [TAG_NAMES.PLAINTEXT, TAG_ID.PLAINTEXT], 455 [TAG_NAMES.PRE, TAG_ID.PRE], 456 [TAG_NAMES.RB, TAG_ID.RB], 457 [TAG_NAMES.RP, TAG_ID.RP], 458 [TAG_NAMES.RT, TAG_ID.RT], 459 [TAG_NAMES.RTC, TAG_ID.RTC], 460 [TAG_NAMES.RUBY, TAG_ID.RUBY], 461 [TAG_NAMES.S, TAG_ID.S], 462 [TAG_NAMES.SCRIPT, TAG_ID.SCRIPT], 463 [TAG_NAMES.SECTION, TAG_ID.SECTION], 464 [TAG_NAMES.SELECT, TAG_ID.SELECT], 465 [TAG_NAMES.SOURCE, TAG_ID.SOURCE], 466 [TAG_NAMES.SMALL, TAG_ID.SMALL], 467 [TAG_NAMES.SPAN, TAG_ID.SPAN], 468 [TAG_NAMES.STRIKE, TAG_ID.STRIKE], 469 [TAG_NAMES.STRONG, TAG_ID.STRONG], 470 [TAG_NAMES.STYLE, TAG_ID.STYLE], 471 [TAG_NAMES.SUB, TAG_ID.SUB], 472 [TAG_NAMES.SUMMARY, TAG_ID.SUMMARY], 473 [TAG_NAMES.SUP, TAG_ID.SUP], 474 [TAG_NAMES.TABLE, TAG_ID.TABLE], 475 [TAG_NAMES.TBODY, TAG_ID.TBODY], 476 [TAG_NAMES.TEMPLATE, TAG_ID.TEMPLATE], 477 [TAG_NAMES.TEXTAREA, TAG_ID.TEXTAREA], 478 [TAG_NAMES.TFOOT, TAG_ID.TFOOT], 479 [TAG_NAMES.TD, TAG_ID.TD], 480 [TAG_NAMES.TH, TAG_ID.TH], 481 [TAG_NAMES.THEAD, TAG_ID.THEAD], 482 [TAG_NAMES.TITLE, TAG_ID.TITLE], 483 [TAG_NAMES.TR, TAG_ID.TR], 484 [TAG_NAMES.TRACK, TAG_ID.TRACK], 485 [TAG_NAMES.TT, TAG_ID.TT], 486 [TAG_NAMES.U, TAG_ID.U], 487 [TAG_NAMES.UL, TAG_ID.UL], 488 [TAG_NAMES.SVG, TAG_ID.SVG], 489 [TAG_NAMES.VAR, TAG_ID.VAR], 490 [TAG_NAMES.WBR, TAG_ID.WBR], 491 [TAG_NAMES.XMP, TAG_ID.XMP], 492 [TAG_NAMES.WEB, TAG_ID.WEB], 493 [TAG_NAMES.XCOMPONENT, TAG_ID.XCOMPONENT], 494 [TAG_NAMES.RATING, TAG_ID.RATING], 495 [TAG_NAMES.CANVAS, TAG_ID.CANVAS], 496 [TAG_NAMES.CAMERA, TAG_ID.CAMERA], 497 [TAG_NAMES.AUDIO, TAG_ID.AUDIO], 498 [TAG_NAMES.VIDEO, TAG_ID.VIDEO], 499 [TAG_NAMES.SWITCH, TAG_ID.SWITCH], 500 [TAG_NAMES.QRCODE, TAG_ID.QRCODE], 501 [TAG_NAMES.PICKER_VIEW, TAG_ID.PICKER_VIEW], 502 [TAG_NAMES.PICKER, TAG_ID.PICKER], 503 [TAG_NAMES.PROGRESS, TAG_ID.PROGRESS], 504 [TAG_NAMES.SEARCH, TAG_ID.SEARCH], 505 [TAG_NAMES.SLIDER, TAG_ID.SLIDER], 506 [TAG_NAMES.CHART, TAG_ID.CHART], 507 [TAG_NAMES.CALENDAR, TAG_ID.CALENDAR], 508 [TAG_NAMES.DIVIDER, TAG_ID.DIVIDER], 509 [TAG_NAMES.IMAGE_ANIMATOR, TAG_ID.IMAGE_ANIMATOR], 510]); 511 512export function getTagID(tagName: string): TAG_ID { 513 return TAG_NAME_TO_ID.get(tagName) ?? TAG_ID.UNKNOWN; 514} 515 516const $ = TAG_ID; 517 518export const SPECIAL_ELEMENTS: Record<NS, Set<TAG_ID>> = { 519 [NS.HTML]: new Set([ 520 $.ADDRESS, 521 $.APPLET, 522 $.AREA, 523 $.ARTICLE, 524 $.ASIDE, 525 $.BASE, 526 $.BASEFONT, 527 $.BGSOUND, 528 $.BLOCKQUOTE, 529 $.BODY, 530 $.BR, 531 $.BUTTON, 532 $.CAPTION, 533 $.CENTER, 534 $.COL, 535 $.COLGROUP, 536 $.DD, 537 $.DETAILS, 538 $.DIR, 539 $.DIV, 540 $.DL, 541 $.DT, 542 $.EMBED, 543 $.FIELDSET, 544 $.FIGCAPTION, 545 $.FIGURE, 546 $.FOOTER, 547 $.FORM, 548 $.FRAME, 549 $.FRAMESET, 550 $.H1, 551 $.H2, 552 $.H3, 553 $.H4, 554 $.H5, 555 $.H6, 556 $.HEAD, 557 $.HEADER, 558 $.HGROUP, 559 $.HR, 560 $.HTML, 561 $.IFRAME, 562 $.IMG, 563 $.INPUT, 564 $.LI, 565 $.LINK, 566 $.LISTING, 567 $.MAIN, 568 $.MARQUEE, 569 $.MENU, 570 $.META, 571 $.NAV, 572 $.NOEMBED, 573 $.NOFRAMES, 574 $.NOSCRIPT, 575 $.OBJECT, 576 $.OL, 577 $.P, 578 $.PARAM, 579 $.PLAINTEXT, 580 $.PRE, 581 $.SCRIPT, 582 $.SECTION, 583 $.SELECT, 584 $.SOURCE, 585 $.STYLE, 586 $.SUMMARY, 587 $.TABLE, 588 $.TBODY, 589 $.TD, 590 $.TEMPLATE, 591 $.TEXTAREA, 592 $.TFOOT, 593 $.TH, 594 $.THEAD, 595 $.TITLE, 596 $.TR, 597 $.TRACK, 598 $.UL, 599 $.WBR, 600 $.XMP, 601 $.WEB, 602 $.XCOMPONENT, 603 $.RATING, 604 $.CANVAS, 605 $.CAMERA, 606 $.AUDIO, 607 $.VIDEO, 608 $.SWITCH, 609 $.QRCODE, 610 $.PICKER_VIEW, 611 $.PICKER, 612 $.PROGRESS, 613 $.SEARCH, 614 $.SLIDER, 615 $.CHART, 616 $.CALENDAR, 617 $.DIVIDER, 618 $.IMAGE_ANIMATOR, 619 ]), 620 [NS.MATHML]: new Set([$.MI, $.MO, $.MN, $.MS, $.MTEXT, $.ANNOTATION_XML]), 621 [NS.SVG]: new Set([$.TITLE, $.FOREIGN_OBJECT, $.DESC]), 622 [NS.XLINK]: new Set(), 623 [NS.XML]: new Set(), 624 [NS.XMLNS]: new Set(), 625}; 626 627export function isNumberedHeader(tn: TAG_ID): boolean { 628 return tn === $.H1 || tn === $.H2 || tn === $.H3 || tn === $.H4 || tn === $.H5 || tn === $.H6; 629} 630 631const UNESCAPED_TEXT = new Set<string>([ 632 TAG_NAMES.STYLE, 633 TAG_NAMES.SCRIPT, 634 TAG_NAMES.XMP, 635 TAG_NAMES.IFRAME, 636 TAG_NAMES.NOEMBED, 637 TAG_NAMES.NOFRAMES, 638 TAG_NAMES.PLAINTEXT, 639]); 640 641export function hasUnescapedText(tn: string, scriptingEnabled: boolean): boolean { 642 return UNESCAPED_TEXT.has(tn) || (scriptingEnabled && tn === TAG_NAMES.NOSCRIPT); 643} 644