/** All valid namespaces in HTML. */
export enum NS {
HTML = 'http://www.w3.org/1999/xhtml',
MATHML = 'http://www.w3.org/1998/Math/MathML',
SVG = 'http://www.w3.org/2000/svg',
XLINK = 'http://www.w3.org/1999/xlink',
XML = 'http://www.w3.org/XML/1998/namespace',
XMLNS = 'http://www.w3.org/2000/xmlns/',
}
export enum ATTRS {
TYPE = 'type',
ACTION = 'action',
ENCODING = 'encoding',
PROMPT = 'prompt',
NAME = 'name',
COLOR = 'color',
FACE = 'face',
SIZE = 'size',
}
/**
* The mode of the document.
*
* @see {@link https://dom.spec.whatwg.org/#concept-document-limited-quirks}
*/
export enum DOCUMENT_MODE {
NO_QUIRKS = 'no-quirks',
QUIRKS = 'quirks',
LIMITED_QUIRKS = 'limited-quirks',
}
export enum TAG_NAMES {
A = 'a',
ADDRESS = 'address',
ANNOTATION_XML = 'annotation-xml',
APPLET = 'applet',
AREA = 'area',
ARTICLE = 'article',
ASIDE = 'aside',
B = 'b',
BASE = 'base',
BASEFONT = 'basefont',
BGSOUND = 'bgsound',
BIG = 'big',
BLOCKQUOTE = 'blockquote',
BODY = 'body',
BR = 'br',
BUTTON = 'button',
CAPTION = 'caption',
CENTER = 'center',
CODE = 'code',
COL = 'col',
COLGROUP = 'colgroup',
DD = 'dd',
DESC = 'desc',
DETAILS = 'details',
DIALOG = 'dialog',
DIR = 'dir',
DIV = 'div',
DL = 'dl',
DT = 'dt',
EM = 'em',
EMBED = 'embed',
FIELDSET = 'fieldset',
FIGCAPTION = 'figcaption',
FIGURE = 'figure',
FONT = 'font',
FOOTER = 'footer',
FOREIGN_OBJECT = 'foreignObject',
FORM = 'form',
FRAME = 'frame',
FRAMESET = 'frameset',
H1 = 'h1',
H2 = 'h2',
H3 = 'h3',
H4 = 'h4',
H5 = 'h5',
H6 = 'h6',
HEAD = 'head',
HEADER = 'header',
HGROUP = 'hgroup',
HR = 'hr',
HTML = 'html',
I = 'i',
IMG = 'img',
IMAGE = 'image',
INPUT = 'input',
IFRAME = 'iframe',
KEYGEN = 'keygen',
LABEL = 'label',
LI = 'li',
LINK = 'link',
LISTING = 'listing',
MAIN = 'main',
MALIGNMARK = 'malignmark',
MARQUEE = 'marquee',
MATH = 'math',
MENU = 'menu',
META = 'meta',
MGLYPH = 'mglyph',
MI = 'mi',
MO = 'mo',
MN = 'mn',
MS = 'ms',
MTEXT = 'mtext',
NAV = 'nav',
NOBR = 'nobr',
NOFRAMES = 'noframes',
NOEMBED = 'noembed',
NOSCRIPT = 'noscript',
OBJECT = 'object',
OL = 'ol',
OPTGROUP = 'optgroup',
OPTION = 'option',
P = 'p',
PARAM = 'param',
PLAINTEXT = 'plaintext',
PRE = 'pre',
RB = 'rb',
RP = 'rp',
RT = 'rt',
RTC = 'rtc',
RUBY = 'ruby',
S = 's',
SCRIPT = 'script',
SECTION = 'section',
SELECT = 'select',
SOURCE = 'source',
SMALL = 'small',
SPAN = 'span',
STRIKE = 'strike',
STRONG = 'strong',
STYLE = 'style',
SUB = 'sub',
SUMMARY = 'summary',
SUP = 'sup',
TABLE = 'table',
TBODY = 'tbody',
TEMPLATE = 'template',
TEXTAREA = 'textarea',
TFOOT = 'tfoot',
TD = 'td',
TH = 'th',
THEAD = 'thead',
TITLE = 'title',
TR = 'tr',
TRACK = 'track',
TT = 'tt',
U = 'u',
UL = 'ul',
SVG = 'svg',
VAR = 'var',
WBR = 'wbr',
XMP = 'xmp',
// Unique self closing label
WEB = 'web',
XCOMPONENT = 'xcomponent',
RATING = 'rating',
CANVAS = 'canvas',
CAMERA = 'camera',
AUDIO = 'audio',
VIDEO = 'video',
SWITCH = 'switch',
QRCODE = 'qrcode',
PICKER_VIEW = 'picker-view',
PICKER = 'picker',
PROGRESS = 'progress',
SEARCH = 'search',
SLIDER = 'slider',
CHART = 'chart',
CALENDAR = 'calendar',
DIVIDER = 'divider',
IMAGE_ANIMATOR = 'image-animator',
}
/**
* Tag IDs are numeric IDs for known tag names.
*
* We use tag IDs to improve the performance of tag name comparisons.
*/
export enum TAG_ID {
UNKNOWN,
A,
ADDRESS,
ANNOTATION_XML,
APPLET,
AREA,
ARTICLE,
ASIDE,
B,
BASE,
BASEFONT,
BGSOUND,
BIG,
BLOCKQUOTE,
BODY,
BR,
BUTTON,
CAPTION,
CENTER,
CODE,
COL,
COLGROUP,
DD,
DESC,
DETAILS,
DIALOG,
DIR,
DIV,
DL,
DT,
EM,
EMBED,
FIELDSET,
FIGCAPTION,
FIGURE,
FONT,
FOOTER,
FOREIGN_OBJECT,
FORM,
FRAME,
FRAMESET,
H1,
H2,
H3,
H4,
H5,
H6,
HEAD,
HEADER,
HGROUP,
HR,
HTML,
I,
IMG,
IMAGE,
INPUT,
IFRAME,
KEYGEN,
LABEL,
LI,
LINK,
LISTING,
MAIN,
MALIGNMARK,
MARQUEE,
MATH,
MENU,
META,
MGLYPH,
MI,
MO,
MN,
MS,
MTEXT,
NAV,
NOBR,
NOFRAMES,
NOEMBED,
NOSCRIPT,
OBJECT,
OL,
OPTGROUP,
OPTION,
P,
PARAM,
PLAINTEXT,
PRE,
RB,
RP,
RT,
RTC,
RUBY,
S,
SCRIPT,
SECTION,
SELECT,
SOURCE,
SMALL,
SPAN,
STRIKE,
STRONG,
STYLE,
SUB,
SUMMARY,
SUP,
TABLE,
TBODY,
TEMPLATE,
TEXTAREA,
TFOOT,
TD,
TH,
THEAD,
TITLE,
TR,
TRACK,
TT,
U,
UL,
SVG,
VAR,
WBR,
XMP,
WEB,
XCOMPONENT,
RATING,
CANVAS,
CAMERA,
AUDIO,
VIDEO,
SWITCH,
QRCODE,
PICKER_VIEW,
PICKER,
PROGRESS,
SEARCH,
SLIDER,
CHART,
CALENDAR,
DIVIDER,
IMAGE_ANIMATOR,
}
const TAG_NAME_TO_ID = new Map([
[TAG_NAMES.A, TAG_ID.A],
[TAG_NAMES.ADDRESS, TAG_ID.ADDRESS],
[TAG_NAMES.ANNOTATION_XML, TAG_ID.ANNOTATION_XML],
[TAG_NAMES.APPLET, TAG_ID.APPLET],
[TAG_NAMES.AREA, TAG_ID.AREA],
[TAG_NAMES.ARTICLE, TAG_ID.ARTICLE],
[TAG_NAMES.ASIDE, TAG_ID.ASIDE],
[TAG_NAMES.B, TAG_ID.B],
[TAG_NAMES.BASE, TAG_ID.BASE],
[TAG_NAMES.BASEFONT, TAG_ID.BASEFONT],
[TAG_NAMES.BGSOUND, TAG_ID.BGSOUND],
[TAG_NAMES.BIG, TAG_ID.BIG],
[TAG_NAMES.BLOCKQUOTE, TAG_ID.BLOCKQUOTE],
[TAG_NAMES.BODY, TAG_ID.BODY],
[TAG_NAMES.BR, TAG_ID.BR],
[TAG_NAMES.BUTTON, TAG_ID.BUTTON],
[TAG_NAMES.CAPTION, TAG_ID.CAPTION],
[TAG_NAMES.CENTER, TAG_ID.CENTER],
[TAG_NAMES.CODE, TAG_ID.CODE],
[TAG_NAMES.COL, TAG_ID.COL],
[TAG_NAMES.COLGROUP, TAG_ID.COLGROUP],
[TAG_NAMES.DD, TAG_ID.DD],
[TAG_NAMES.DESC, TAG_ID.DESC],
[TAG_NAMES.DETAILS, TAG_ID.DETAILS],
[TAG_NAMES.DIALOG, TAG_ID.DIALOG],
[TAG_NAMES.DIR, TAG_ID.DIR],
[TAG_NAMES.DIV, TAG_ID.DIV],
[TAG_NAMES.DL, TAG_ID.DL],
[TAG_NAMES.DT, TAG_ID.DT],
[TAG_NAMES.EM, TAG_ID.EM],
[TAG_NAMES.EMBED, TAG_ID.EMBED],
[TAG_NAMES.FIELDSET, TAG_ID.FIELDSET],
[TAG_NAMES.FIGCAPTION, TAG_ID.FIGCAPTION],
[TAG_NAMES.FIGURE, TAG_ID.FIGURE],
[TAG_NAMES.FONT, TAG_ID.FONT],
[TAG_NAMES.FOOTER, TAG_ID.FOOTER],
[TAG_NAMES.FOREIGN_OBJECT, TAG_ID.FOREIGN_OBJECT],
[TAG_NAMES.FORM, TAG_ID.FORM],
[TAG_NAMES.FRAME, TAG_ID.FRAME],
[TAG_NAMES.FRAMESET, TAG_ID.FRAMESET],
[TAG_NAMES.H1, TAG_ID.H1],
[TAG_NAMES.H2, TAG_ID.H2],
[TAG_NAMES.H3, TAG_ID.H3],
[TAG_NAMES.H4, TAG_ID.H4],
[TAG_NAMES.H5, TAG_ID.H5],
[TAG_NAMES.H6, TAG_ID.H6],
[TAG_NAMES.HEAD, TAG_ID.HEAD],
[TAG_NAMES.HEADER, TAG_ID.HEADER],
[TAG_NAMES.HGROUP, TAG_ID.HGROUP],
[TAG_NAMES.HR, TAG_ID.HR],
[TAG_NAMES.HTML, TAG_ID.HTML],
[TAG_NAMES.I, TAG_ID.I],
[TAG_NAMES.IMG, TAG_ID.IMG],
[TAG_NAMES.IMAGE, TAG_ID.IMAGE],
[TAG_NAMES.INPUT, TAG_ID.INPUT],
[TAG_NAMES.IFRAME, TAG_ID.IFRAME],
[TAG_NAMES.KEYGEN, TAG_ID.KEYGEN],
[TAG_NAMES.LABEL, TAG_ID.LABEL],
[TAG_NAMES.LI, TAG_ID.LI],
[TAG_NAMES.LINK, TAG_ID.LINK],
[TAG_NAMES.LISTING, TAG_ID.LISTING],
[TAG_NAMES.MAIN, TAG_ID.MAIN],
[TAG_NAMES.MALIGNMARK, TAG_ID.MALIGNMARK],
[TAG_NAMES.MARQUEE, TAG_ID.MARQUEE],
[TAG_NAMES.MATH, TAG_ID.MATH],
[TAG_NAMES.MENU, TAG_ID.MENU],
[TAG_NAMES.META, TAG_ID.META],
[TAG_NAMES.MGLYPH, TAG_ID.MGLYPH],
[TAG_NAMES.MI, TAG_ID.MI],
[TAG_NAMES.MO, TAG_ID.MO],
[TAG_NAMES.MN, TAG_ID.MN],
[TAG_NAMES.MS, TAG_ID.MS],
[TAG_NAMES.MTEXT, TAG_ID.MTEXT],
[TAG_NAMES.NAV, TAG_ID.NAV],
[TAG_NAMES.NOBR, TAG_ID.NOBR],
[TAG_NAMES.NOFRAMES, TAG_ID.NOFRAMES],
[TAG_NAMES.NOEMBED, TAG_ID.NOEMBED],
[TAG_NAMES.NOSCRIPT, TAG_ID.NOSCRIPT],
[TAG_NAMES.OBJECT, TAG_ID.OBJECT],
[TAG_NAMES.OL, TAG_ID.OL],
[TAG_NAMES.OPTGROUP, TAG_ID.OPTGROUP],
[TAG_NAMES.OPTION, TAG_ID.OPTION],
[TAG_NAMES.P, TAG_ID.P],
[TAG_NAMES.PARAM, TAG_ID.PARAM],
[TAG_NAMES.PLAINTEXT, TAG_ID.PLAINTEXT],
[TAG_NAMES.PRE, TAG_ID.PRE],
[TAG_NAMES.RB, TAG_ID.RB],
[TAG_NAMES.RP, TAG_ID.RP],
[TAG_NAMES.RT, TAG_ID.RT],
[TAG_NAMES.RTC, TAG_ID.RTC],
[TAG_NAMES.RUBY, TAG_ID.RUBY],
[TAG_NAMES.S, TAG_ID.S],
[TAG_NAMES.SCRIPT, TAG_ID.SCRIPT],
[TAG_NAMES.SECTION, TAG_ID.SECTION],
[TAG_NAMES.SELECT, TAG_ID.SELECT],
[TAG_NAMES.SOURCE, TAG_ID.SOURCE],
[TAG_NAMES.SMALL, TAG_ID.SMALL],
[TAG_NAMES.SPAN, TAG_ID.SPAN],
[TAG_NAMES.STRIKE, TAG_ID.STRIKE],
[TAG_NAMES.STRONG, TAG_ID.STRONG],
[TAG_NAMES.STYLE, TAG_ID.STYLE],
[TAG_NAMES.SUB, TAG_ID.SUB],
[TAG_NAMES.SUMMARY, TAG_ID.SUMMARY],
[TAG_NAMES.SUP, TAG_ID.SUP],
[TAG_NAMES.TABLE, TAG_ID.TABLE],
[TAG_NAMES.TBODY, TAG_ID.TBODY],
[TAG_NAMES.TEMPLATE, TAG_ID.TEMPLATE],
[TAG_NAMES.TEXTAREA, TAG_ID.TEXTAREA],
[TAG_NAMES.TFOOT, TAG_ID.TFOOT],
[TAG_NAMES.TD, TAG_ID.TD],
[TAG_NAMES.TH, TAG_ID.TH],
[TAG_NAMES.THEAD, TAG_ID.THEAD],
[TAG_NAMES.TITLE, TAG_ID.TITLE],
[TAG_NAMES.TR, TAG_ID.TR],
[TAG_NAMES.TRACK, TAG_ID.TRACK],
[TAG_NAMES.TT, TAG_ID.TT],
[TAG_NAMES.U, TAG_ID.U],
[TAG_NAMES.UL, TAG_ID.UL],
[TAG_NAMES.SVG, TAG_ID.SVG],
[TAG_NAMES.VAR, TAG_ID.VAR],
[TAG_NAMES.WBR, TAG_ID.WBR],
[TAG_NAMES.XMP, TAG_ID.XMP],
[TAG_NAMES.WEB, TAG_ID.WEB],
[TAG_NAMES.XCOMPONENT, TAG_ID.XCOMPONENT],
[TAG_NAMES.RATING, TAG_ID.RATING],
[TAG_NAMES.CANVAS, TAG_ID.CANVAS],
[TAG_NAMES.CAMERA, TAG_ID.CAMERA],
[TAG_NAMES.AUDIO, TAG_ID.AUDIO],
[TAG_NAMES.VIDEO, TAG_ID.VIDEO],
[TAG_NAMES.SWITCH, TAG_ID.SWITCH],
[TAG_NAMES.QRCODE, TAG_ID.QRCODE],
[TAG_NAMES.PICKER_VIEW, TAG_ID.PICKER_VIEW],
[TAG_NAMES.PICKER, TAG_ID.PICKER],
[TAG_NAMES.PROGRESS, TAG_ID.PROGRESS],
[TAG_NAMES.SEARCH, TAG_ID.SEARCH],
[TAG_NAMES.SLIDER, TAG_ID.SLIDER],
[TAG_NAMES.CHART, TAG_ID.CHART],
[TAG_NAMES.CALENDAR, TAG_ID.CALENDAR],
[TAG_NAMES.DIVIDER, TAG_ID.DIVIDER],
[TAG_NAMES.IMAGE_ANIMATOR, TAG_ID.IMAGE_ANIMATOR],
]);
export function getTagID(tagName: string): TAG_ID {
return TAG_NAME_TO_ID.get(tagName) ?? TAG_ID.UNKNOWN;
}
const $ = TAG_ID;
export const SPECIAL_ELEMENTS: Record> = {
[NS.HTML]: new Set([
$.ADDRESS,
$.APPLET,
$.AREA,
$.ARTICLE,
$.ASIDE,
$.BASE,
$.BASEFONT,
$.BGSOUND,
$.BLOCKQUOTE,
$.BODY,
$.BR,
$.BUTTON,
$.CAPTION,
$.CENTER,
$.COL,
$.COLGROUP,
$.DD,
$.DETAILS,
$.DIR,
$.DIV,
$.DL,
$.DT,
$.EMBED,
$.FIELDSET,
$.FIGCAPTION,
$.FIGURE,
$.FOOTER,
$.FORM,
$.FRAME,
$.FRAMESET,
$.H1,
$.H2,
$.H3,
$.H4,
$.H5,
$.H6,
$.HEAD,
$.HEADER,
$.HGROUP,
$.HR,
$.HTML,
$.IFRAME,
$.IMG,
$.INPUT,
$.LI,
$.LINK,
$.LISTING,
$.MAIN,
$.MARQUEE,
$.MENU,
$.META,
$.NAV,
$.NOEMBED,
$.NOFRAMES,
$.NOSCRIPT,
$.OBJECT,
$.OL,
$.P,
$.PARAM,
$.PLAINTEXT,
$.PRE,
$.SCRIPT,
$.SECTION,
$.SELECT,
$.SOURCE,
$.STYLE,
$.SUMMARY,
$.TABLE,
$.TBODY,
$.TD,
$.TEMPLATE,
$.TEXTAREA,
$.TFOOT,
$.TH,
$.THEAD,
$.TITLE,
$.TR,
$.TRACK,
$.UL,
$.WBR,
$.XMP,
$.WEB,
$.XCOMPONENT,
$.RATING,
$.CANVAS,
$.CAMERA,
$.AUDIO,
$.VIDEO,
$.SWITCH,
$.QRCODE,
$.PICKER_VIEW,
$.PICKER,
$.PROGRESS,
$.SEARCH,
$.SLIDER,
$.CHART,
$.CALENDAR,
$.DIVIDER,
$.IMAGE_ANIMATOR,
]),
[NS.MATHML]: new Set([$.MI, $.MO, $.MN, $.MS, $.MTEXT, $.ANNOTATION_XML]),
[NS.SVG]: new Set([$.TITLE, $.FOREIGN_OBJECT, $.DESC]),
[NS.XLINK]: new Set(),
[NS.XML]: new Set(),
[NS.XMLNS]: new Set(),
};
export function isNumberedHeader(tn: TAG_ID): boolean {
return tn === $.H1 || tn === $.H2 || tn === $.H3 || tn === $.H4 || tn === $.H5 || tn === $.H6;
}
const UNESCAPED_TEXT = new Set([
TAG_NAMES.STYLE,
TAG_NAMES.SCRIPT,
TAG_NAMES.XMP,
TAG_NAMES.IFRAME,
TAG_NAMES.NOEMBED,
TAG_NAMES.NOFRAMES,
TAG_NAMES.PLAINTEXT,
]);
export function hasUnescapedText(tn: string, scriptingEnabled: boolean): boolean {
return UNESCAPED_TEXT.has(tn) || (scriptingEnabled && tn === TAG_NAMES.NOSCRIPT);
}