← 7 User interactionTable of contents8.5 Named character references →

8 The HTML syntax

This section only describes the rules for resources labeled with an HTML MIME type. Rules for XML resources are discussed in the section below entitled "The XHTML syntax".

8.1 Writing HTML documents

Status: Last call for comments

This section only applies to documents, authoring tools, and markup generators. In particular, it does not apply to conformance checkers; conformance checkers must use the requirements given in the next section ("parsing HTML documents").

Documents must consist of the following parts, in the given order:

  1. Optionally, a single U+FEFF BYTE ORDER MARK (BOM) character.
  2. Any number of comments and space characters.
  3. A DOCTYPE.
  4. Any number of comments and space characters.
  5. The root element, in the form of an html element.
  6. Any number of comments and space characters.

The various types of content mentioned above are described in the next few sections.

In addition, there are some restrictions on how character encoding declarations are to be serialized, as discussed in the section on that topic.

Space characters before the root html element, and space characters at the start of the html element and before the head element, will be dropped when the document is parsed; space characters after the root html element will be parsed as if they were at the end of the body element. Thus, space characters around the root element do not round-trip.

It is suggested that newlines be inserted after the DOCTYPE, after any comments that are before the root element, after the html element's start tag (if it is not omitted), and after any comments that are inside the html element but before the head element.

Many strings in the HTML syntax (e.g. the names of elements and their attributes) are case-insensitive, but only for characters in the ranges U+0041 to U+005A (LATIN CAPITAL LETTER A to LATIN CAPITAL LETTER Z) and U+0061 to U+007A (LATIN SMALL LETTER A to LATIN SMALL LETTER Z). For convenience, in this section this is just referred to as "case-insensitive".

8.1.1 The DOCTYPE

Status: Last call for comments. ISSUE-4 (html-versioning) and ISSUE-84 (legacy-doctypes) block progress to Last Call

A DOCTYPE is a mostly useless, but required, header.

DOCTYPEs are required for legacy reasons. When omitted, browsers tend to use a different rendering mode that is incompatible with some specifications. Including the DOCTYPE in a document ensures that the browser makes a best-effort attempt at following the relevant specifications.

A DOCTYPE must consist of the following characters, in this order:

  1. A U+003C LESS-THAN SIGN character (<).
  2. A U+0021 EXCLAMATION MARK character (!).
  3. A string that is an ASCII case-insensitive match for the string "DOCTYPE".
  4. One or more space characters.
  5. A string that is an ASCII case-insensitive match for the string "HTML".
  6. Optionally, a DOCTYPE legacy string or an obsolete permitted DOCTYPE string (defined below).
  7. Zero or more space characters.
  8. A U+003E GREATER-THAN SIGN character (>).

In other words, <!DOCTYPE HTML>, case-insensitively.


For the purposes of HTML generators that cannot output HTML markup with the short DOCTYPE "<!DOCTYPE HTML>", a DOCTYPE legacy string may be inserted into the DOCTYPE (in the position defined above). This string must consist of:

  1. One or more space characters.
  2. A string that is an ASCII case-insensitive match for the string "SYSTEM".
  3. One or more space characters.
  4. A U+0022 QUOTATION MARK or U+0027 APOSTROPHE character (the quote mark).
  5. The literal string "about:legacy-compat".
  6. A matching U+0022 QUOTATION MARK or U+0027 APOSTROPHE character (i.e. the same character as in the earlier step labeled quote mark).

In other words, <!DOCTYPE HTML SYSTEM "about:legacy-compat"> or <!DOCTYPE HTML SYSTEM 'about:legacy-compat'>, case-insensitively except for the bit in single or double quotes.

The DOCTYPE legacy string should not be used unless the document is generated from a system that cannot output the shorter string.


To help authors transition from HTML4 and XHTML1, an obsolete permitted DOCTYPE string can be inserted into the DOCTYPE (in the position defined above). This string must consist of:

  1. One or more space characters.
  2. A string that is an ASCII case-insensitive match for the string "PUBLIC".
  3. One or more space characters.
  4. A U+0022 QUOTATION MARK or U+0027 APOSTROPHE character (the first quote mark).
  5. The string from one of the cells in the first column of the table below. The row to which this cell belongs is the selected row.
  6. A matching U+0022 QUOTATION MARK or U+0027 APOSTROPHE character (i.e. the same character as in the earlier step labeled first quote mark).
  7. If the cell in the second column of the selected row is not blank, one or more space characters.
  8. If the cell in the second column of the selected row is not blank, a U+0022 QUOTATION MARK or U+0027 APOSTROPHE character (the third quote mark).
  9. If the cell in the second column of the selected row is not blank, the string from the cell in the second column of the selected row.
  10. If the cell in the second column of the selected row is not blank, a matching U+0022 QUOTATION MARK or U+0027 APOSTROPHE character (i.e. the same character as in the earlier step labeled third quote mark).
Allowed values for public and system identifiers in an obsolete permitted DOCTYPE string.
Public identifier System identifier
-//W3C//DTD HTML 4.0//EN
-//W3C//DTD HTML 4.0//EN http://www.w3.org/TR/REC-html40/strict.dtd
-//W3C//DTD HTML 4.01//EN
-//W3C//DTD HTML 4.01//EN http://www.w3.org/TR/html4/strict.dtd
-//W3C//DTD XHTML 1.0 Strict//EN http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd
-//W3C//DTD XHTML 1.1//EN http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd

A DOCTYPE containing an obsolete permitted DOCTYPE string is an obsolete permitted DOCTYPE. Authors should not use obsolete permitted DOCTYPEs, as they are unnecessarily long.

8.1.2 Elements

Status: Last call for comments

There are five different kinds of elements: void elements, raw text elements, RCDATA elements, foreign elements, and normal elements.

Void elements
area, base, br, col, command, embed, hr, img, input, keygen, link, meta, param, source
Raw text elements
script, style
RCDATA elements
textarea, title
Foreign elements
Elements from the MathML namespace and the SVG namespace.
Normal elements
All other allowed HTML elements are normal elements.

Tags are used to delimit the start and end of elements in the markup. Raw text, RCDATA, and normal elements have a start tag to indicate where they begin, and an end tag to indicate where they end. The start and end tags of certain normal elements can be omitted, as described later. Those that cannot be omitted must not be omitted. Void elements only have a start tag; end tags must not be specified for void elements. Foreign elements must either have a start tag and an end tag, or a start tag that is marked as self-closing, in which case they must not have an end tag.

The contents of the element must be placed between just after the start tag (which might be implied, in certain cases) and just before the end tag (which again, might be implied in certain cases). The exact allowed contents of each individual element depends on the content model of that element, as described earlier in this specification. Elements must not contain content that their content model disallows. In addition to the restrictions placed on the contents by those content models, however, the five types of elements have additional syntactic requirements.

Void elements can't have any contents (since there's no end tag, no content can be put between the start tag and the end tag).

Raw text elements can have text, though it has restrictions described below.

RCDATA elements can have text and character references, but the text must not contain an ambiguous ampersand. There are also further restrictions described below.

Foreign elements whose start tag is marked as self-closing can't have any contents (since, again, as there's no end tag, no content can be put between the start tag and the end tag). Foreign elements whose start tag is not marked as self-closing can have text, character references, CDATA sections, other elements, and comments, but the text must not contain the character U+003C LESS-THAN SIGN (<) or an ambiguous ampersand.

The HTML syntax does not support namespace declarations, even in foreign elements.

For instance, consider the following HTML fragment:

<p>
 <svg>
  <metadata>
   <!-- this is invalid -->
   <cdr:license xmlns:cdr="http://www.example.com/cdr/metadata" name="MIT"/>
  </metadata>
 </svg>
</p>

The innermost element, cdr:license, is actually in the SVG namespace, as the "xmlns:cdr" attribute has no effect (unlike in XML). In fact, as the comment in the fragment above says, the fragment is actually non-conforming. This is because the SVG specification does not define any elements called "cdr:license" in the SVG namespace.

Normal elements can have text, character references, other elements, and comments, but the text must not contain the character U+003C LESS-THAN SIGN (<) or an ambiguous ampersand. Some normal elements also have yet more restrictions on what content they are allowed to hold, beyond the restrictions imposed by the content model and those described in this paragraph. Those restrictions are described below.

Tags contain a tag name, giving the element's name. HTML elements all have names that only use characters in the range U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9), U+0061 LATIN SMALL LETTER A to U+007A LATIN SMALL LETTER Z, and U+0041 LATIN CAPITAL LETTER A to U+005A LATIN CAPITAL LETTER Z. In the HTML syntax, tag names, even those for foreign elements, may be written with any mix of lower- and uppercase letters that, when converted to all-lowercase, matches the element's tag name; tag names are case-insensitive.

8.1.2.1 Start tags

Status: Last call for comments

Start tags must have the following format:

  1. The first character of a start tag must be a U+003C LESS-THAN SIGN character (<).
  2. The next few characters of a start tag must be the element's tag name.
  3. If there are to be any attributes in the next step, there must first be one or more space characters.
  4. Then, the start tag may have a number of attributes, the syntax for which is described below. Attributes may be separated from each other by one or more space characters.
  5. After the attributes, or after the tag name if there are no attributes, there may be one or more space characters. (Some attributes are required to be followed by a space. See the attributes section below.)
  6. Then, if the element is one of the void elements, or if the element is a foreign element, then there may be a single U+002F SOLIDUS character (/). This character has no effect on void elements, but on foreign elements it marks the start tag as self-closing.
  7. Finally, start tags must be closed by a U+003E GREATER-THAN SIGN character (>).
8.1.2.2 End tags

Status: Last call for comments

End tags must have the following format:

  1. The first character of an end tag must be a U+003C LESS-THAN SIGN character (<).
  2. The second character of an end tag must be a U+002F SOLIDUS character (/).
  3. The next few characters of an end tag must be the element's tag name.
  4. After the tag name, there may be one or more space characters.
  5. Finally, end tags must be closed by a U+003E GREATER-THAN SIGN character (>).
8.1.2.3 Attributes

Status: Last call for comments

Attributes for an element are expressed inside the element's start tag.

Attributes have a name and a value. Attribute names must consist of one or more characters other than the space characters, U+0000 NULL, U+0022 QUOTATION MARK ("), U+0027 APOSTROPHE ('), U+003E GREATER-THAN SIGN (>), U+002F SOLIDUS (/), and U+003D EQUALS SIGN (=) characters, the control characters, and any characters that are not defined by Unicode. In the HTML syntax, attribute names, even those for foreign elements, may be written with any mix of lower- and uppercase letters that are an ASCII case-insensitive match for the attribute's name.

Attribute values are a mixture of text and character references, except with the additional restriction that the text cannot contain an ambiguous ampersand.

Attributes can be specified in four different ways:

Empty attribute syntax

Just the attribute name. The value is implicitly the empty string.

In the following example, the disabled attribute is given with the empty attribute syntax:

<input disabled>

If an attribute using the empty attribute syntax is to be followed by another attribute, then there must be a space character separating the two.

Unquoted attribute value syntax

The attribute name, followed by zero or more space characters, followed by a single U+003D EQUALS SIGN character, followed by zero or more space characters, followed by the attribute value, which, in addition to the requirements given above for attribute values, must not contain any literal space characters, any U+0022 QUOTATION MARK characters ("), U+0027 APOSTROPHE characters ('), U+003D EQUALS SIGN characters (=), U+003C LESS-THAN SIGN characters (<), U+003E GREATER-THAN SIGN characters (>), or U+0060 GRAVE ACCENT characters (`), and must not be the empty string.

In the following example, the value attribute is given with the unquoted attribute value syntax:

<input value=yes>

If an attribute using the unquoted attribute syntax is to be followed by another attribute or by the optional U+002F SOLIDUS character (/) allowed in step 6 of the start tag syntax above, then there must be a space character separating the two.

Single-quoted attribute value syntax

The attribute name, followed by zero or more space characters, followed by a single U+003D EQUALS SIGN character, followed by zero or more space characters, followed by a single U+0027 APOSTROPHE character ('), followed by the attribute value, which, in addition to the requirements given above for attribute values, must not contain any literal U+0027 APOSTROPHE characters ('), and finally followed by a second single U+0027 APOSTROPHE character (').

In the following example, the type attribute is given with the single-quoted attribute value syntax:

<input type='checkbox'>

If an attribute using the single-quoted attribute syntax is to be followed by another attribute, then there must be a space character separating the two.

Double-quoted attribute value syntax

The attribute name, followed by zero or more space characters, followed by a single U+003D EQUALS SIGN character, followed by zero or more space characters, followed by a single U+0022 QUOTATION MARK character ("), followed by the attribute value, which, in addition to the requirements given above for attribute values, must not contain any literal U+0022 QUOTATION MARK characters ("), and finally followed by a second single U+0022 QUOTATION MARK character (").

In the following example, the name attribute is given with the double-quoted attribute value syntax:

<input name="be evil">

If an attribute using the double-quoted attribute syntax is to be followed by another attribute, then there must be a space character separating the two.

There must never be two or more attributes on the same start tag whose names are an ASCII case-insensitive match for each other.


When a foreign element has one of the namespaced attributes given by the local name and namespace of the first and second cells of a row from the following table, it must be written using the name given by the third cell from the same row.

Local name Namespace Attribute name
actuate XLink namespace xlink:actuate
arcrole XLink namespace xlink:arcrole
href XLink namespace xlink:href
role XLink namespace xlink:role
show XLink namespace xlink:show
title XLink namespace xlink:title
type XLink namespace xlink:type
base XML namespace xml:base
lang XML namespace xml:lang
space XML namespace xml:space
xmlns XMLNS namespace xmlns
xlink XMLNS namespace xmlns:xlink

No other namespaced attribute can be expressed in the HTML syntax.

8.1.2.4 Optional tags

Status: Last call for comments

Certain tags can be omitted.

Omitting an element's start tag does not mean the element is not present; it is implied, but it is still there. An HTML document always has a root html element, even if the string <html> doesn't appear anywhere in the markup.

An html element's start tag may be omitted if the first thing inside the html element is not a comment.

An html element's end tag may be omitted if the html element is not immediately followed by a comment.

A head element's start tag may be omitted if the element is empty, or if the first thing inside the head element is an element.

A head element's end tag may be omitted if the head element is not immediately followed by a space character or a comment.

A body element's start tag may be omitted if the element is empty, or if the first thing inside the body element is not a space character or a comment, except if the first thing inside the body element is a script or style element.

A body element's end tag may be omitted if the body element is not immediately followed by a comment.

A li element's end tag may be omitted if the li element is immediately followed by another li element or if there is no more content in the parent element.

A dt element's end tag may be omitted if the dt element is immediately followed by another dt element or a dd element.

A dd element's end tag may be omitted if the dd element is immediately followed by another dd element or a dt element, or if there is no more content in the parent element.

A p element's end tag may be omitted if the p element is immediately followed by an address, article, aside, blockquote, dir, div, dl, fieldset, footer, form, h1, h2, h3, h4, h5, h6, header, hgroup, hr, menu, nav, ol, p, pre, section, table, or ul, element, or if there is no more content in the parent element and the parent element is not an a element.

An rt element's end tag may be omitted if the rt element is immediately followed by an rt or rp element, or if there is no more content in the parent element.

An rp element's end tag may be omitted if the rp element is immediately followed by an rt or rp element, or if there is no more content in the parent element.

An optgroup element's end tag may be omitted if the optgroup element is immediately followed by another optgroup element, or if there is no more content in the parent element.

An option element's end tag may be omitted if the option element is immediately followed by another option element, or if it is immediately followed by an optgroup element, or if there is no more content in the parent element.

A colgroup element's start tag may be omitted if the first thing inside the colgroup element is a col element, and if the element is not immediately preceded by another colgroup element whose end tag has been omitted. (It can't be omitted if the element is empty.)

A colgroup element's end tag may be omitted if the colgroup element is not immediately followed by a space character or a comment.

A thead element's end tag may be omitted if the thead element is immediately followed by a tbody or tfoot element.

A tbody element's start tag may be omitted if the first thing inside the tbody element is a tr element, and if the element is not immediately preceded by a tbody, thead, or tfoot element whose end tag has been omitted. (It can't be omitted if the element is empty.)

A tbody element's end tag may be omitted if the tbody element is immediately followed by a tbody or tfoot element, or if there is no more content in the parent element.

A tfoot element's end tag may be omitted if the tfoot element is immediately followed by a tbody element, or if there is no more content in the parent element.

A tr element's end tag may be omitted if the tr element is immediately followed by another tr element, or if there is no more content in the parent element.

A td element's end tag may be omitted if the td element is immediately followed by a td or th element, or if there is no more content in the parent element.

A th element's end tag may be omitted if the th element is immediately followed by a td or th element, or if there is no more content in the parent element.

However, a start tag must never be omitted if it has any attributes.

8.1.2.5 Restrictions on content models

Status: Last call for comments

For historical reasons, certain elements have extra restrictions beyond even the restrictions given by their content model.

A table element must not contain tr elements, even though these elements are technically allowed inside table elements according to the content models described in this specification. (If a tr element is put inside a table in the markup, it will in fact imply a tbody start tag before it.)

A single newline may be placed immediately after the start tag of pre and textarea elements. This does not affect the processing of the element. The otherwise optional newline must be included if the element's contents themselves start with a newline (because otherwise the leading newline in the contents would be treated like the optional newline, and ignored).

The following two pre blocks are equivalent:

<pre>Hello</pre>
<pre>
Hello</pre>
8.1.2.6 Restrictions on the contents of raw text and RCDATA elements

Status: Last call for comments

The text in raw text and RCDATAs element must not contain any occurrences of the string "</" (U+003C LESS-THAN SIGN, U+002F SOLIDUS) followed by characters that case-insensitively match the tag name of the element followed by one of U+0009 CHARACTER TABULATION, U+000A LINE FEED (LF), U+000C FORM FEED (FF), U+000D CARRIAGE RETURN (CR), U+0020 SPACE, U+003E GREATER-THAN SIGN (>), or U+002F SOLIDUS (/).

8.1.3 Text

Status: Last call for comments

Text is allowed inside elements, attributes, and comments. Text must consist of Unicode characters. Text must not contain U+0000 characters. Text must not contain permanently undefined Unicode characters (noncharacters). Text must not contain control characters other than space characters. Extra constraints are placed on what is and what is not allowed in text based on where the text is to be put, as described in the other sections.

8.1.3.1 Newlines

Status: Last call for comments

Newlines in HTML may be represented either as U+000D CARRIAGE RETURN (CR) characters, U+000A LINE FEED (LF) characters, or pairs of U+000D CARRIAGE RETURN (CR), U+000A LINE FEED (LF) characters in that order.

8.1.4 Character references

Status: Last call for comments

In certain cases described in other sections, text may be mixed with character references. These can be used to escape characters that couldn't otherwise legally be included in text.

Character references must start with a U+0026 AMPERSAND character (&). Following this, there are three possible kinds of character references:

Named character references
The ampersand must be followed by one of the names given in the named character references section, using the same case. The name must be one that is terminated by a U+003B SEMICOLON character (;).
Decimal numeric character reference
The ampersand must be followed by a U+0023 NUMBER SIGN character (#), followed by one or more digits in the range U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9), representing a base-ten integer that corresponds to a Unicode code point that is allowed according to the definition below. The digits must then be followed by a U+003B SEMICOLON character (;).
Hexadecimal numeric character reference
The ampersand must be followed by a U+0023 NUMBER SIGN character (#), which must be followed by either a U+0078 LATIN SMALL LETTER X character (x) or a U+0058 LATIN CAPITAL LETTER X character (X), which must then be followed by one or more digits in the range U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9), U+0061 LATIN SMALL LETTER A to U+0066 LATIN SMALL LETTER F, and U+0041 LATIN CAPITAL LETTER A to U+0046 LATIN CAPITAL LETTER F, representing a base-sixteen integer that corresponds to a Unicode code point that is allowed according to the definition below. The digits must then be followed by a U+003B SEMICOLON character (;).

The numeric character reference forms described above are allowed to reference any Unicode code point other than U+0000, permanently undefined Unicode characters (noncharacters), and control characters other than space characters.

An ambiguous ampersand is a U+0026 AMPERSAND character (&) that is followed by some text other than a space character, a U+003C LESS-THAN SIGN character (<), or another U+0026 AMPERSAND character (&).

8.1.5 CDATA sections

Status: Last call for comments

CDATA sections must start with the character sequence U+003C LESS-THAN SIGN, U+0021 EXCLAMATION MARK, U+005B LEFT SQUARE BRACKET, U+0043 LATIN CAPITAL LETTER C, U+0044 LATIN CAPITAL LETTER D, U+0041 LATIN CAPITAL LETTER A, U+0054 LATIN CAPITAL LETTER T, U+0041 LATIN CAPITAL LETTER A, U+005B LEFT SQUARE BRACKET (<![CDATA[). Following this sequence, the CDATA section may have text, with the additional restriction that the text must not contain the three character sequence U+005D RIGHT SQUARE BRACKET, U+005D RIGHT SQUARE BRACKET, U+003E GREATER-THAN SIGN (]]>). Finally, the CDATA section must be ended by the three character sequence U+005D RIGHT SQUARE BRACKET, U+005D RIGHT SQUARE BRACKET, U+003E GREATER-THAN SIGN (]]>).

CDATA sections can only be used in foreign content (MathML or SVG). In this example, a CDATA section is used to escape the contents of an ms element:

<p>You can add a string to a number, but this stringifies the number:</p>
<math>
 <ms><![CDATA[x<y]]></ms>
 <mo>+</mo>
 <mn>3</mn>
 <mo>=</mo>
 <ms><![CDATA[x<y3]]></ms>
</math>

8.1.6 Comments

Status: Last call for comments

Comments must start with the four character sequence U+003C LESS-THAN SIGN, U+0021 EXCLAMATION MARK, U+002D HYPHEN-MINUS, U+002D HYPHEN-MINUS (<!--). Following this sequence, the comment may have text, with the additional restriction that the text must not start with a single U+003E GREATER-THAN SIGN character (>), nor start with a U+002D HYPHEN-MINUS character (-) followed by a U+003E GREATER-THAN SIGN (>) character, nor contain two consecutive U+002D HYPHEN-MINUS characters (--), nor end with a U+002D HYPHEN-MINUS character (-). Finally, the comment must be ended by the three character sequence U+002D HYPHEN-MINUS, U+002D HYPHEN-MINUS, U+003E GREATER-THAN SIGN (-->).

8.2 Parsing HTML documents

Status: Last call for comments

This section only applies to user agents, data mining tools, and conformance checkers.

The rules for parsing XML documents into DOM trees are covered by the next section, entitled "The XHTML syntax".

For HTML documents, user agents must use the parsing rules described in this section to generate the DOM trees. Together, these rules define what is referred to as the HTML parser.

While the HTML syntax described in this specification bears a close resemblance to SGML and XML, it is a separate language with its own parsing rules.

Some earlier versions of HTML (in particular from HTML2 to HTML4) were based on SGML and used SGML parsing rules. However, few (if any) web browsers ever implemented true SGML parsing for HTML documents; the only user agents to strictly handle HTML as an SGML application have historically been validators. The resulting confusion — with validators claiming documents to have one representation while widely deployed Web browsers interoperably implemented a different representation — has wasted decades of productivity. This version of HTML thus returns to a non-SGML basis.

Authors interested in using SGML tools in their authoring pipeline are encouraged to use XML tools and the XML serialization of HTML.

This specification defines the parsing rules for HTML documents, whether they are syntactically correct or not. Certain points in the parsing algorithm are said to be parse errors. The error handling for parse errors is well-defined: user agents must either act as described below when encountering such problems, or must abort processing at the first error that they encounter for which they do not wish to apply the rules described below.

Conformance checkers must report at least one parse error condition to the user if one or more parse error conditions exist in the document and must not report parse error conditions if none exist in the document. Conformance checkers may report more than one parse error condition if more than one parse error condition exists in the document. Conformance checkers are not required to recover from parse errors.

Parse errors are only errors with the syntax of HTML. In addition to checking for parse errors, conformance checkers will also verify that the document obeys all the other conformance requirements described in this specification.

For the purposes of conformance checkers, if a resource is determined to be in the HTML syntax, then it is an HTML document.

8.2.1 Overview of the parsing model

Status: Last call for comments

The input to the HTML parsing process consists of a stream of Unicode characters, which is passed through a tokenization stage followed by a tree construction stage. The output is a Document object.

Implementations that do not support scripting do not have to actually create a DOM Document object, but the DOM tree in such cases is still used as the model for the rest of the specification.

In the common case, the data handled by the tokenization stage comes from the network, but it can also come from script, e.g. using the document.write() API.

There is only one set of states for the tokenizer stage and the tree construction stage, but the tree construction stage is reentrant, meaning that while the tree construction stage is handling one token, the tokenizer might be resumed, causing further tokens to be emitted and processed before the first token's processing is complete.

In the following example, the tree construction stage will be called upon to handle a "p" start tag token while handling the "script" start tag token:

...
<script>
 document.write('<p>');
</script>
...

To handle these cases, parsers have a script nesting level, which must be initially set to zero, and a parser pause flag, which must be initially set to false.

8.2.2 The input stream

Status: Last call for comments

The stream of Unicode characters that comprises the input to the tokenization stage will be initially seen by the user agent as a stream of bytes (typically coming over the network or from the local file system). The bytes encode the actual characters according to a particular character encoding, which the user agent must use to decode the bytes into characters.

For XML documents, the algorithm user agents must use to determine the character encoding is given by the XML specification. This section does not apply to XML documents. [XML]

8.2.2.1 Determining the character encoding

Status: Last call for comments

In some cases, it might be impractical to unambiguously determine the encoding before parsing the document. Because of this, this specification provides for a two-pass mechanism with an optional pre-scan. Implementations are allowed, as described below, to apply a simplified parsing algorithm to whatever bytes they have available before beginning to parse the document. Then, the real parser is started, using a tentative encoding derived from this pre-parse and other out-of-band metadata. If, while the document is being loaded, the user agent discovers an encoding declaration that conflicts with this information, then the parser can get reinvoked to perform a parse of the document with the real encoding.

User agents must use the following algorithm (the encoding sniffing algorithm) to determine the character encoding to use when decoding a document in the first pass. This algorithm takes as input any out-of-band metadata available to the user agent (e.g. the Content-Type metadata of the document) and all the bytes available so far, and returns an encoding and a confidence. The confidence is either tentative, certain, or irrelevant. The encoding used, and whether the confidence in that encoding is tentative or certain, is used during the parsing to determine whether to change the encoding. If no encoding is necessary, e.g. because the parser is operating on a stream of Unicode characters and doesn't have to use an encoding at all, then the confidence is irrelevant.

  1. If the transport layer specifies an encoding, and it is supported, return that encoding with the confidence certain, and abort these steps.

  2. The user agent may wait for more bytes of the resource to be available, either in this step or at any later step in this algorithm. For instance, a user agent might wait 500ms or 512 bytes, whichever came first. In general preparsing the source to find the encoding improves performance, as it reduces the need to throw away the data structures used when parsing upon finding the encoding information. However, if the user agent delays too long to obtain data to determine the encoding, then the cost of the delay could outweigh any performance improvements from the preparse.

  3. For each of the rows in the following table, starting with the first one and going down, if there are as many or more bytes available than the number of bytes in the first column, and the first bytes of the file match the bytes given in the first column, then return the encoding given in the cell in the second column of that row, with the confidence certain, and abort these steps:

    Bytes in Hexadecimal Encoding
    FE FF UTF-16BE
    FF FE UTF-16LE
    EF BB BF UTF-8

    This step looks for Unicode Byte Order Marks (BOMs).

  4. Otherwise, the user agent will have to search for explicit character encoding information in the file itself. This should proceed as follows:

    Let position be a pointer to a byte in the input stream, initially pointing at the first byte. If at any point during these substeps the user agent either runs out of bytes or decides that scanning further bytes would not be efficient, then skip to the next step of the overall character encoding detection algorithm. User agents may decide that scanning any bytes is not efficient, in which case these substeps are entirely skipped.

    Now, repeat the following "two" steps until the algorithm aborts (either because user agent aborts, as described above, or because a character encoding is found):

    1. If position points to:

      A sequence of bytes starting with: 0x3C 0x21 0x2D 0x2D (ASCII '<!--')

      Advance the position pointer so that it points at the first 0x3E byte which is preceded by two 0x2D bytes (i.e. at the end of an ASCII '-->' sequence) and comes after the 0x3C byte that was found. (The two 0x2D bytes can be the same as the those in the '<!--' sequence.)

      A sequence of bytes starting with: 0x3C, 0x4D or 0x6D, 0x45 or 0x65, 0x54 or 0x74, 0x41 or 0x61, and finally one of 0x09, 0x0A, 0x0C, 0x0D, 0x20, 0x2F (case-insensitive ASCII '<meta' followed by a space or slash)
      1. Advance the position pointer so that it points at the next 0x09, 0x0A, 0x0C, 0x0D, 0x20, or 0x2F byte (the one in sequence of characters matched above).

      2. Get an attribute and its value. If no attribute was sniffed, then skip this inner set of steps, and jump to the second step in the overall "two step" algorithm.

      3. If the attribute's name is neither "charset" nor "content", then return to step 2 in these inner steps.

      4. If the attribute's name is "charset", let charset be the attribute's value, interpreted as a character encoding.

      5. Otherwise, the attribute's name is "content": apply the algorithm for extracting an encoding from a Content-Type, giving the attribute's value as the string to parse. If an encoding is returned, let charset be that encoding. Otherwise, return to step 2 in these inner steps.

      6. If charset is a UTF-16 encoding, change the value of charset to UTF-8.

      7. If charset is a supported character encoding, then return the given encoding, with confidence tentative, and abort all these steps.

      8. Otherwise, return to step 2 in these inner steps.

      A sequence of bytes starting with a 0x3C byte (ASCII <), optionally a 0x2F byte (ASCII /), and finally a byte in the range 0x41-0x5A or 0x61-0x7A (an ASCII letter)
      1. Advance the position pointer so that it points at the next 0x09 (ASCII TAB), 0x0A (ASCII LF), 0x0C (ASCII FF), 0x0D (ASCII CR), 0x20 (ASCII space), or 0x3E (ASCII >) byte.

      2. Repeatedly get an attribute until no further attributes can be found, then jump to the second step in the overall "two step" algorithm.

      A sequence of bytes starting with: 0x3C 0x21 (ASCII '<!')
      A sequence of bytes starting with: 0x3C 0x2F (ASCII '</')
      A sequence of bytes starting with: 0x3C 0x3F (ASCII '<?')

      Advance the position pointer so that it points at the first 0x3E byte (ASCII >) that comes after the 0x3C byte that was found.

      Any other byte

      Do nothing with that byte.

    2. Move position so it points at the next byte in the input stream, and return to the first step of this "two step" algorithm.

    When the above "two step" algorithm says to get an attribute, it means doing this:

    1. If the byte at position is one of 0x09 (ASCII TAB), 0x0A (ASCII LF), 0x0C (ASCII FF), 0x0D (ASCII CR), 0x20 (ASCII space), or 0x2F (ASCII /) then advance position to the next byte and redo this substep.

    2. If the byte at position is 0x3E (ASCII >), then abort the "get an attribute" algorithm. There isn't one.

    3. Otherwise, the byte at position is the start of the attribute name. Let attribute name and attribute value be the empty string.

    4. Attribute name: Process the byte at position as follows:

      If it is 0x3D (ASCII =), and the attribute name is longer than the empty string
      Advance position to the next byte and jump to the step below labeled value.
      If it is 0x09 (ASCII TAB), 0x0A (ASCII LF), 0x0C (ASCII FF), 0x0D (ASCII CR), or 0x20 (ASCII space)
      Jump to the step below labeled spaces.
      If it is 0x2F (ASCII /) or 0x3E (ASCII >)
      Abort the "get an attribute" algorithm. The attribute's name is the value of attribute name, its value is the empty string.
      If it is in the range 0x41 (ASCII A) to 0x5A (ASCII Z)
      Append the Unicode character with code point b+0x20 to attribute name (where b is the value of the byte at position).
      Anything else
      Append the Unicode character with the same code point as the value of the byte at position) to attribute name. (It doesn't actually matter how bytes outside the ASCII range are handled here, since only ASCII characters can contribute to the detection of a character encoding.)
    5. Advance position to the next byte and return to the previous step.

    6. Spaces: If the byte at position is one of 0x09 (ASCII TAB), 0x0A (ASCII LF), 0x0C (ASCII FF), 0x0D (ASCII CR), or 0x20 (ASCII space) then advance position to the next byte, then, repeat this step.

    7. If the byte at position is not 0x3D (ASCII =), abort the "get an attribute" algorithm. The attribute's name is the value of attribute name, its value is the empty string.

    8. Advance position past the 0x3D (ASCII =) byte.

    9. Value: If the byte at position is one of 0x09 (ASCII TAB), 0x0A (ASCII LF), 0x0C (ASCII FF), 0x0D (ASCII CR), or 0x20 (ASCII space) then advance position to the next byte, then, repeat this step.

    10. Process the byte at position as follows:

      If it is 0x22 (ASCII ") or 0x27 (ASCII ')
      1. Let b be the value of the byte at position.
      2. Advance position to the next byte.
      3. If the value of the byte at position is the value of b, then advance position to the next byte and abort the "get an attribute" algorithm. The attribute's name is the value of attribute name, and its value is the value of attribute value.
      4. Otherwise, if the value of the byte at position is in the range 0x41 (ASCII A) to 0x5A (ASCII Z), then append a Unicode character to attribute value whose code point is 0x20 more than the value of the byte at position.
      5. Otherwise, append a Unicode character to attribute value whose code point is the same as the value of the byte at position.
      6. Return to the second step in these substeps.
      If it is 0x3E (ASCII >)
      Abort the "get an attribute" algorithm. The attribute's name is the value of attribute name, its value is the empty string.
      If it is in the range 0x41 (ASCII A) to 0x5A (ASCII Z)
      Append the Unicode character with code point b+0x20 to attribute value (where b is the value of the byte at position). Advance position to the next byte.
      Anything else
      Append the Unicode character with the same code point as the value of the byte at position) to attribute value. Advance position to the next byte.
    11. Process the byte at position as follows:

      If it is 0x09 (ASCII TAB), 0x0A (ASCII LF), 0x0C (ASCII FF), 0x0D (ASCII CR), 0x20 (ASCII space), or 0x3E (ASCII >)
      Abort the "get an attribute" algorithm. The attribute's name is the value of attribute name and its value is the value of attribute value.
      If it is in the range 0x41 (ASCII A) to 0x5A (ASCII Z)
      Append the Unicode character with code point b+0x20 to attribute value (where b is the value of the byte at position).
      Anything else
      Append the Unicode character with the same code point as the value of the byte at position) to attribute value.
    12. Advance position to the next byte and return to the previous step.

    For the sake of interoperability, user agents should not use a pre-scan algorithm that returns different results than the one described above. (But, if you do, please at least let us know, so that we can improve this algorithm and benefit everyone...)

  5. If the user agent has information on the likely encoding for this page, e.g. based on the encoding of the page when it was last visited, then return that encoding, with the confidence tentative, and abort these steps.

  6. The user agent may attempt to autodetect the character encoding from applying frequency analysis or other algorithms to the data stream. Such algorithms may use information about the resource other than the resource's contents, including the address of the resource. If autodetection succeeds in determining a character encoding, then return that encoding, with the confidence tentative, and abort these steps. [UNIVCHARDET]

    The UTF-8 encoding has a highly detectable bit pattern. Documents that contain bytes with values greater than 0x7F which match the UTF-8 pattern are very likely to be UTF-8, while documents with byte sequences that do not match it are very likely not. User-agents are therefore encouraged to search for this common encoding. [PPUTF8] [UTF8DET]

  7. Otherwise, return an implementation-defined or user-specified default character encoding, with the confidence tentative.

    In controlled environments or in environments where the encoding of documents can be prescribed (for example, for user agents intended for dedicated use in new networks), the comprehensive UTF-8 encoding is suggested.

    In other environments, the default encoding is typically dependent on the user's locale (an approximation of the languages, and thus often encodings, of the pages that the user is likely to frequent). The following table gives suggested defaults based on the user's locale, for compatibility with legacy content. Locales are identified by BCP 47 language codes. [BCP47]

    Locale language Suggested default encoding
    ar UTF-8
    be ISO-8859-5
    bg windows-1251
    cs ISO-8859-2
    cy UTF-8
    fa UTF-8
    he windows-1255
    hr UTF-8
    hu ISO-8859-2
    ja Windows-31J
    kk UTF-8
    ko windows-949
    ku windows-1254
    lt windows-1257
    lv ISO-8859-13
    mk UTF-8
    or UTF-8
    pl ISO-8859-2
    ro UTF-8
    ru windows-1251
    sk windows-1250
    sl ISO-8859-2
    sr UTF-8
    th windows-874
    tr windows-1254
    uk windows-1251
    vi UTF-8
    zh-CN GB18030
    zh-TW Big5
    All other locales windows-1252

The document's character encoding must immediately be set to the value returned from this algorithm, at the same time as the user agent uses the returned value to select the decoder to use for the input stream.

This algorithm is a willful violation of the HTTP specification, which requires that the encoding be assumed to be ISO-8859-1 in the absence of a character encoding declaration to the contrary, and of RFC 2046, which requires that the encoding be assumed to be US-ASCII in the absence of a character encoding declaration to the contrary. This specification's third approach is motivated by a desire to be maximally compatible with legacy content. [HTTP] [RFC2046]

8.2.2.2 Character encodings

Status: Last call for comments

User agents must at a minimum support the UTF-8 and Windows-1252 encodings, but may support more.

It is not unusual for Web browsers to support dozens if not upwards of a hundred distinct character encodings.

User agents must support the preferred MIME name of every character encoding they support, and should support all the IANA-registered names and aliases of every character encoding they support. [IANACHARSET]

When comparing a string specifying a character encoding with the name or alias of a character encoding to determine if they are equal, user agents must remove any leading or trailing space characters in both names, and then perform the comparison in an ASCII case-insensitive manner.


When a user agent would otherwise use an encoding given in the first column of the following table to either convert content to Unicode characters or convert Unicode characters to bytes, it must instead use the encoding given in the cell in the second column of the same row. When a byte or sequence of bytes is treated differently due to this encoding aliasing, it is said to have been misinterpreted for compatibility.

Character encoding overrides
Input encoding Replacement encoding References
EUC-KR windows-949 [EUCKR] [WIN949]
GB2312 GBK [RFC1345] [GBK]
GB_2312-80 GBK [RFC1345] [GBK]
ISO-8859-1 windows-1252 [RFC1345] [WIN1252]
ISO-8859-9 windows-1254 [RFC1345] [WIN1254]
ISO-8859-11 windows-874 [ISO885911] [WIN874]
KS_C_5601-1987 windows-949 [RFC1345] [WIN949]
Shift_JIS Windows-31J [SHIFTJIS] [WIN31J]
TIS-620 windows-874 [TIS620] [WIN874]
US-ASCII windows-1252 [RFC1345] [WIN1252]

The requirement to treat certain encodings as other encodings according to the table above is a willful violation of the W3C Character Model specification, motivated by a desire for compatibility with legacy content. [CHARMOD]

When a user agent is to use the UTF-16 encoding but no BOM has been found, user agents must default to UTF-16LE.

The requirement to default UTF-16 to LE rather than BE is a willful violation of RFC 2781, motivated by a desire for compatibility with legacy content. [RFC2781]


User agents must not support the CESU-8, UTF-7, BOCU-1 and SCSU encodings. [CESU8] [UTF7] [BOCU1] [SCSU]

Support for encodings based on EBCDIC is not recommended. This encoding is rarely used for publicly-facing Web content.

Support for UTF-32 is not recommended. This encoding is rarely used, and frequently implemented incorrectly.

This specification does not make any attempt to support EBCDIC-based encodings and UTF-32 in its algorithms; support and use of these encodings can thus lead to unexpected behavior in implementations of this specification.

8.2.2.3 Preprocessing the input stream

Status: Last call for comments

Given an encoding, the bytes in the input stream must be converted to Unicode characters for the tokenizer, as described by the rules for that encoding, except that the leading U+FEFF BYTE ORDER MARK character, if any, must not be stripped by the encoding layer (it is stripped by the rule below).

Bytes or sequences of bytes in the original byte stream that could not be converted to Unicode code points must be converted to U+FFFD REPLACEMENT CHARACTERs.

Bytes or sequences of bytes in the original byte stream that did not conform to the encoding specification (e.g. invalid UTF-8 byte sequences in a UTF-8 input stream) are errors that conformance checkers are expected to report.

Any byte or sequence of bytes in the original byte stream that is misinterpreted for compatibility is a parse error.

One leading U+FEFF BYTE ORDER MARK character must be ignored if any are present.

The requirement to strip a U+FEFF BYTE ORDER MARK character regardless of whether that character was used to determine the byte order is a willful violation of Unicode, motivated by a desire to increase the resilience of user agents in the face of naïve transcoders.

All U+0000 NULL characters and code points in the range U+D800 to U+DFFF in the input must be replaced by U+FFFD REPLACEMENT CHARACTERs. Any occurrences of such characters and code points are parse errors.

Any occurrences of any characters in the ranges U+0001 to U+0008, U+000E to U+001F, U+007F to U+009F, U+FDD0 to U+FDEF, and characters U+000B, U+FFFE, U+FFFF, U+1FFFE, U+1FFFF, U+2FFFE, U+2FFFF, U+3FFFE, U+3FFFF, U+4FFFE, U+4FFFF, U+5FFFE, U+5FFFF, U+6FFFE, U+6FFFF, U+7FFFE, U+7FFFF, U+8FFFE, U+8FFFF, U+9FFFE, U+9FFFF, U+AFFFE, U+AFFFF, U+BFFFE, U+BFFFF, U+CFFFE, U+CFFFF, U+DFFFE, U+DFFFF, U+EFFFE, U+EFFFF, U+FFFFE, U+FFFFF, U+10FFFE, and U+10FFFF are parse errors. These are all control characters or permanently undefined Unicode characters (noncharacters).

U+000D CARRIAGE RETURN (CR) characters and U+000A LINE FEED (LF) characters are treated specially. Any CR characters that are followed by LF characters must be removed, and any CR characters not followed by LF characters must be converted to LF characters. Thus, newlines in HTML DOMs are represented by LF characters, and there are never any CR characters in the input to the tokenization stage.

The next input character is the first character in the input stream that has not yet been consumed. Initially, the next input character is the first character in the input. The current input character is the last character to have been consumed.

The insertion point is the position (just before a character or just before the end of the input stream) where content inserted using document.write() is actually inserted. The insertion point is relative to the position of the character immediately after it, it is not an absolute offset into the input stream. Initially, the insertion point is undefined.

The "EOF" character in the tables below is a conceptual character representing the end of the input stream. If the parser is a script-created parser, then the end of the input stream is reached when an explicit "EOF" character (inserted by the document.close() method) is consumed. Otherwise, the "EOF" character is not a real character in the stream, but rather the lack of any further characters.

8.2.2.4 Changing the encoding while parsing

Status: Last call for comments

When the parser requires the user agent to change the encoding, it must run the following steps. This might happen if the encoding sniffing algorithm described above failed to find an encoding, or if it found an encoding that was not the actual encoding of the file.

  1. If the new encoding is identical or equivalent to the encoding that is already being used to interpret the input stream, then set the confidence to certain and abort these steps. This happens when the encoding information found in the file matches what the encoding sniffing algorithm determined to be the encoding, and in the second pass through the parser if the first pass found that the encoding sniffing algorithm described in the earlier section failed to find the right encoding.
  2. If the encoding that is already being used to interpret the input stream is a UTF-16 encoding, then set the confidence to certain and abort these steps. The new encoding is ignored; if it was anything but the same encoding, then it would be clearly incorrect.
  3. If the new encoding is a UTF-16 encoding, change it to UTF-8.
  4. If all the bytes up to the last byte converted by the current decoder have the same Unicode interpretations in both the current encoding and the new encoding, and if the user agent supports changing the converter on the fly, then the user agent may change to the new converter for the encoding on the fly. Set the document's character encoding and the encoding used to convert the input stream to the new encoding, set the confidence to certain, and abort these steps.
  5. Otherwise, navigate to the document again, with replacement enabled, and using the same source browsing context, but this time skip the encoding sniffing algorithm and instead just set the encoding to the new encoding and the confidence to certain. Whenever possible, this should be done without actually contacting the network layer (the bytes should be re-parsed from memory), even if, e.g., the document is marked as not being cacheable. If this is not possible and contacting the network layer would involve repeating a request that uses a method other than HTTP GET (or equivalent for non-HTTP URLs), then instead set the confidence to certain and ignore the new encoding. The resource will be misinterpreted. User agents may notify the user of the situation, to aid in application development.

8.2.3 Parse state

Status: Last call for comments

8.2.3.1 The insertion mode

Status: Last call for comments

The insertion mode is a state variable that controls the primary operation of the tree construction stage.

Initially, the insertion mode is "initial". It can change to "before html", "before head", "in head", "in head noscript", "after head", "in body", "text", "in table", "in table text", "in caption", "in column group", "in table body", "in row", "in cell", "in select", "in select in table", "in foreign content", "after body", "in frameset", "after frameset", "after after body", and "after after frameset" during the course of the parsing, as described in the tree construction stage. The insertion mode affects how tokens are processed and whether CDATA sections are supported.

Seven of these modes, namely "in head", "in body", "in table", "in table body", "in row", "in cell", and "in select", are special, in that the other modes defer to them at various times. When the algorithm below says that the user agent is to do something "using the rules for the m insertion mode", where m is one of these modes, the user agent must use the rules described under the m insertion mode's section, but must leave the insertion mode unchanged unless the rules in m themselves switch the insertion mode to a new value.

When the insertion mode is switched to "text" or "in table text", the original insertion mode is also set. This is the insertion mode to which the tree construction stage will return.

When the insertion mode is switched to "in foreign content", the secondary insertion mode is also set. This secondary mode is used within the rules for the "in foreign content" mode to handle HTML (i.e. not foreign) content.


When the steps below require the UA to reset the insertion mode appropriately, it means the UA must follow these steps:

  1. Let last be false.
  2. Let foreign be false.
  3. Let node be the last node in the stack of open elements.
  4. Loop: If node is the first node in the stack of open elements, then set last to true and set node to the context element. (fragment case)
  5. If node is a select element, then switch the insertion mode to "in select" and jump to the step labeled end. (fragment case)
  6. If node is a td or th element and last is false, then switch the insertion mode to "in cell" and jump to the step labeled end.
  7. If node is a tr element, then switch the insertion mode to "in row" and jump to the step labeled end.
  8. If node is a tbody, thead, or tfoot element, then switch the insertion mode to "in table body" and jump to the step labeled end.
  9. If node is a caption element, then switch the insertion mode to "in caption" and jump to the step labeled end.
  10. If node is a colgroup element, then switch the insertion mode to "in column group" and jump to the step labeled end. (fragment case)
  11. If node is a table element, then switch the insertion mode to "in table" and jump to the step labeled end.
  12. If node is a head element, then switch the insertion mode to "in body" ("in body"! not "in head"!) and jump to the step labeled end. (fragment case)
  13. If node is a body element, then switch the insertion mode to "in body" and jump to the step labeled end.
  14. If node is a frameset element, then switch the insertion mode to "in frameset" and jump to the step labeled end. (fragment case)
  15. If node is an html element, then switch the insertion mode to "before head" Then, jump to the step labeled end. (fragment case)
  16. If node is an element from the MathML namespace or the SVG namespace, then set the foreign flag to true.
  17. If last is true, then switch the insertion mode to "in body" and jump to the step labeled end. (fragment case)
  18. Let node now be the node before node in the stack of open elements.
  19. Return to the step labeled loop.
  20. End: If foreign is true, switch the secondary insertion mode to whatever the insertion mode is set to, and switch the insertion mode to "in foreign content".
8.2.3.2 The stack of open elements

Status: Last call for comments

Initially, the stack of open elements is empty. The stack grows downwards; the topmost node on the stack is the first one added to the stack, and the bottommost node of the stack is the most recently added node in the stack (notwithstanding when the stack is manipulated in a random access fashion as part of the handling for misnested tags).

The "before html" insertion mode creates the html root element node, which is then added to the stack.

In the fragment case, the stack of open elements is initialized to contain an html element that is created as part of that algorithm. (The fragment case skips the "before html" insertion mode.)

The html node, however it is created, is the topmost node of the stack. It only gets popped off the stack when the parser finishes.

The current node is the bottommost node in this stack.

The current table is the last table element in the stack of open elements, if there is one. If there is no table element in the stack of open elements (fragment case), then the current table is the first element in the stack of open elements (the html element).

Elements in the stack fall into the following categories:

Special

The following HTML elements have varying levels of special parsing rules: address, area, article, aside, base, basefont, bgsound, blockquote, body, br, center, col, colgroup, command, , dd, details, dir, div, dl, dt, embed, fieldset, figure, footer, form, frame, frameset, h1, h2, h3, h4, h5, h6, head, header, hgroup, hr, iframe, img, input, isindex, li, link, listing, menu, meta, nav, noembed, noframes, noscript, ol, p, param, plaintext, pre, script, section, select, style, tbody, textarea, tfoot, thead, title, tr, ul, wbr, and xmp.

Scoping

The following HTML elements introduce new scopes for various parts of the parsing: applet, button, caption, html, marquee, object, table, td, th, and SVG's foreignObject.

Formatting

The following HTML elements are those that end up in the list of active formatting elements: a, b, big, code, em, font, i, nobr, s, small, strike, strong, tt, and u.

Phrasing

All other elements found while parsing an HTML document.

The stack of open elements is said to have an element in a specific scope consisting of a list of element types list when the following algorithm terminates in a match state:

  1. Initialize node to be the current node (the bottommost node of the stack).

  2. If node is the target node, terminate in a match state.

  3. Otherwise, if node is one of the element types in list, terminate in a failure state.

  4. Otherwise, set node to the previous entry in the stack of open elements and return to step 2. (This will never fail, since the loop will always terminate in the previous step if the top of the stack — an html element — is reached.)

The stack of open elements is said to have an element in scope when it has an element in the specific scope consisting of the following element types:

The stack of open elements is said to have an element in list item scope when it has an element in the specific scope consisting of the following element types:

The stack of open elements is said to have an element in table scope when it has an element in the specific scope consisting of the following element types:

Nothing happens if at any time any of the elements in the stack of open elements are moved to a new location in, or removed from, the Document tree. In particular, the stack is not changed in this situation. This can cause, amongst other strange effects, content to be appended to nodes that are no longer in the DOM.

In some cases (namely, when closing misnested formatting elements), the stack is manipulated in a random-access fashion.

8.2.3.3 The list of active formatting elements

Status: Last call for comments

Initially, the list of active formatting elements is empty. It is used to handle mis-nested formatting element tags.

The list contains elements in the formatting category, and scope markers. The scope markers are inserted when entering applet elements, buttons, object elements, marquees, table cells, and table captions, and are used to prevent formatting from "leaking" into applet elements, buttons, object elements, marquees, and tables.

The scope markers are unrelated to the concept of an element being in scope.

In addition, each element in the list of active formatting elements is associated with the token for which it was created, so that further elements can be created for that token if necessary.

When the steps below require the UA to reconstruct the active formatting elements, the UA must perform the following steps:

  1. If there are no entries in the list of active formatting elements, then there is nothing to reconstruct; stop this algorithm.
  2. If the last (most recently added) entry in the list of active formatting elements is a marker, or if it is an element that is in the stack of open elements, then there is nothing to reconstruct; stop this algorithm.
  3. Let entry be the last (most recently added) element in the list of active formatting elements.
  4. If there are no entries before entry in the list of active formatting elements, then jump to step 8.
  5. Let entry be the entry one earlier than entry in the list of active formatting elements.
  6. If entry is neither a marker nor an element that is also in the stack of open elements, go to step 4.
  7. Let entry be the element one later than entry in the list of active formatting elements.
  8. Create an element for the token for which the element entry was created, to obtain new element.
  9. Append new element to the current node and push it onto the stack of open elements so that it is the new current node.
  10. Replace the entry for entry in the list with an entry for new element.
  11. If the entry for new element in the list of active formatting elements is not the last entry in the list, return to step 7.

This has the effect of reopening all the formatting elements that were opened in the current body, cell, or caption (whichever is youngest) that haven't been explicitly closed.

The way this specification is written, the list of active formatting elements always consists of elements in chronological order with the least recently added element first and the most recently added element last (except for while steps 8 to 11 of the above algorithm are being executed, of course).

When the steps below require the UA to clear the list of active formatting elements up to the last marker, the UA must perform the following steps:

  1. Let entry be the last (most recently added) entry in the list of active formatting elements.
  2. Remove entry from the list of active formatting elements.
  3. If entry was a marker, then stop the algorithm at this point. The list has been cleared up to the last marker.
  4. Go to step 1.
8.2.3.4 The element pointers

Status: Last call for comments

Initially, the head element pointer and the form element pointer are both null.

Once a head element has been parsed (whether implicitly or explicitly) the head element pointer gets set to point to this node.

The form element pointer points to the last form element that was opened and whose end tag has not yet been seen. It is used to make form controls associate with forms in the face of dramatically bad markup, for historical reasons.

8.2.3.5 Other parsing state flags

Status: Last call for comments

The scripting flag is set to "enabled" if scripting was enabled for the Document with which the parser is associated when the parser was created, and "disabled" otherwise.

The scripting flag can be enabled even when the parser was originally created for the HTML fragment parsing algorithm, even though script elements don't execute in that case.

The frameset-ok flag is set to "ok" when the parser is created. It is set to "not ok" after certain tokens are seen.

8.2.4 Tokenization

Status: Last call for comments

Implementations must act as if they used the following state machine to tokenize HTML. The state machine must start in the data state. Most states consume a single character, which may have various side-effects, and either switches the state machine to a new state to reconsume the same character, or switches it to a new state (to consume the next character), or repeats the same state (to consume the next character). Some states have more complicated behavior and can consume several characters before switching to another state. In some cases, the tokenizer state is also changed by the tree construction stage.

The exact behavior of certain states depends on the insertion mode and the stack of open elements. Certain states also use a temporary buffer to track progress.

The output of the tokenization step is a series of zero or more of the following tokens: DOCTYPE, start tag, end tag, comment, character, end-of-file. DOCTYPE tokens have a name, a public identifier, a system identifier, and a force-quirks flag. When a DOCTYPE token is created, its name, public identifier, and system identifier must be marked as missing (which is a distinct state from the empty string), and the force-quirks flag must be set to off (its other state is on). Start and end tag tokens have a tag name, a self-closing flag, and a list of attributes, each of which has a name and a value. When a start or end tag token is created, its self-closing flag must be unset (its other state is that it be set), and its attributes list must be empty. Comment and character tokens have data.

When a token is emitted, it must immediately be handled by the tree construction stage. The tree construction stage can affect the state of the tokenization stage, and can insert additional characters into the stream. (For example, the script element can result in scripts executing and using the dynamic markup insertion APIs to insert characters into the stream being tokenized.)

When a start tag token is emitted with its self-closing flag set, if the flag is not acknowledged when it is processed by the tree construction stage, that is a parse error.

When an end tag token is emitted with attributes, that is a parse error.

When an end tag token is emitted with its self-closing flag set, that is a parse error.

An appropriate end tag token is an end tag token whose tag name matches the tag name of the last start tag to have been emitted from this tokenizer, if any. If no start tag has been emitted from this tokenizer, then no end tag token is appropriate.

Before each step of the tokenizer, the user agent must first check the parser pause flag. If it is true, then the tokenizer must abort the processing of any nested invocations of the tokenizer, yielding control back to the caller.

The tokenizer state machine consists of the states defined in the following subsections.

8.2.4.1 Data state

Status: Last call for comments

Consume the next input character:

U+0026 AMPERSAND (&)
Switch to the character reference in data state.
U+003C LESS-THAN SIGN (<)
Switch to the tag open state.
EOF
Emit an end-of-file token.
Anything else
Emit the current input character as a character token. Stay in the data state.
8.2.4.2 Character reference in data state

Status: Last call for comments

Attempt to consume a character reference, with no additional allowed character.

If nothing is returned, emit a U+0026 AMPERSAND character token.

Otherwise, emit the character token that was returned.

Finally, switch to the data state.

8.2.4.3 RCDATA state

Status: Last call for comments

Consume the next input character:

U+0026 AMPERSAND (&)
Switch to the character reference in RCDATA state.
U+003C LESS-THAN SIGN (<)
Switch to the RCDATA less-than sign state.
EOF
Emit an end-of-file token.
Anything else
Emit the current input character as a character token. Stay in the RCDATA state.
8.2.4.4 Character reference in RCDATA state

Attempt to consume a character reference, with no additional allowed character.

If nothing is returned, emit a U+0026 AMPERSAND character token.

Otherwise, emit the character token that was returned.

Finally, switch to the RCDATA state.

8.2.4.5 RAWTEXT state

Status: Last call for comments

Consume the next input character:

U+003C LESS-THAN SIGN (<)
Switch to the RAWTEXT less-than sign state.
EOF
Emit an end-of-file token.
Anything else
Emit the current input character as a character token. Stay in the RAWTEXT state.
8.2.4.6 Script data state

Status: Last call for comments

Consume the next input character:

U+003C LESS-THAN SIGN (<)
Switch to the script data less-than sign state.
EOF
Emit an end-of-file token.
Anything else
Emit the current input character as a character token. Stay in the script data state.
8.2.4.7 PLAINTEXT state

Status: Last call for comments

Consume the next input character:

EOF
Emit an end-of-file token.
Anything else
Emit the current input character as a character token. Stay in the PLAINTEXT state.
8.2.4.8 Tag open state

Status: Last call for comments

Consume the next input character:

U+0021 EXCLAMATION MARK (!)
Switch to the markup declaration open state.
U+002F SOLIDUS (/)
Switch to the end tag open state.
U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
Create a new start tag token, set its tag name to the lowercase version of the current input character (add 0x0020 to the character's code point), then switch to the tag name state. (Don't emit the token yet; further details will be filled in before it is emitted.)
U+0061 LATIN SMALL LETTER A through to U+007A LATIN SMALL LETTER Z
Create a new start tag token, set its tag name to the current input character, then switch to the tag name state. (Don't emit the token yet; further details will be filled in before it is emitted.)
U+003F QUESTION MARK (?)
Parse error. Switch to the bogus comment state.
Anything else
Parse error. Emit a U+003C LESS-THAN SIGN character token and reconsume the current input character in the data state.
8.2.4.9 End tag open state

Consume the next input character:

U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
Create a new end tag token, set its tag name to the lowercase version of the current input character (add 0x0020 to the character's code point), then switch to the tag name state. (Don't emit the token yet; further details will be filled in before it is emitted.)
U+0061 LATIN SMALL LETTER A through to U+007A LATIN SMALL LETTER Z
Create a new end tag token, set its tag name to the current input character, then switch to the tag name state. (Don't emit the token yet; further details will be filled in before it is emitted.)
U+003E GREATER-THAN SIGN (>)
Parse error. Switch to the data state.
EOF
Parse error. Emit a U+003C LESS-THAN SIGN character token and a U+002F SOLIDUS character token. Reconsume the EOF character in the data state.
Anything else
Parse error. Switch to the bogus comment state.
8.2.4.10 Tag name state

Status: Last call for comments

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
Switch to the before attribute name state.
U+002F SOLIDUS (/)
Switch to the self-closing start tag state.
U+003E GREATER-THAN SIGN (>)
Emit the current tag token. Switch to the data state.
U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
Append the lowercase version of the current input character (add 0x0020 to the character's code point) to the current tag token's tag name. Stay in the tag name state.
EOF
Parse error. Reconsume the EOF character in the data state.
Anything else
Append the current input character to the current tag token's tag name. Stay in the tag name state.
8.2.4.11 RCDATA less-than sign state

Status: Last call for comments

Consume the next input character:

U+002F SOLIDUS (/)
Set the temporary buffer to the empty string. Switch to the RCDATA end tag open state.
Anything else
Emit a U+003C LESS-THAN SIGN character token and reconsume the current input character in the RCDATA state.
8.2.4.12 RCDATA end tag open state

Status: Last call for comments

Consume the next input character:

U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
Create a new end tag token, and set its tag name to the lowercase version of the current input character (add 0x0020 to the character's code point). Append the current input character to the temporary buffer. Finally, switch to the RCDATA end tag name state. (Don't emit the token yet; further details will be filled in before it is emitted.)
U+0061 LATIN SMALL LETTER A through to U+007A LATIN SMALL LETTER Z
Create a new end tag token, and set its tag name to the current input character. Append the current input character to the temporary buffer. Finally, switch to the RCDATA end tag name state. (Don't emit the token yet; further details will be filled in before it is emitted.)
Anything else
Emit a U+003C LESS-THAN SIGN character token, a U+002F SOLIDUS character token, and reconsume the current input character in the RCDATA state.
8.2.4.13 RCDATA end tag name state

Status: Last call for comments

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
If the current end tag token is an appropriate end tag token, then switch to the before attribute name state. Otherwise, treat it as per the "anything else" entry below.
U+002F SOLIDUS (/)
If the current end tag token is an appropriate end tag token, then switch to the self-closing start tag state. Otherwise, treat it as per the "anything else" entry below.
U+003E GREATER-THAN SIGN (>)
If the current end tag token is an appropriate end tag token, then emit the current tag token and switch to the data state. Otherwise, treat it as per the "anything else" entry below.
U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
Append the lowercase version of the current input character (add 0x0020 to the character's code point) to the current tag token's tag name. Append the current input character to the temporary buffer. Stay in the RCDATA end tag name state.
U+0061 LATIN SMALL LETTER A through to U+007A LATIN SMALL LETTER Z
Append the current input character to the current tag token's tag name. Append the current input character to the temporary buffer. Stay in the RCDATA end tag name state.
Anything else
Emit a U+003C LESS-THAN SIGN character token, a U+002F SOLIDUS character token, a character token for each of the characters in the temporary buffer (in the order they were added to the buffer), and reconsume the current input character in the RCDATA state.
8.2.4.14 RAWTEXT less-than sign state

Status: Last call for comments

Consume the next input character:

U+002F SOLIDUS (/)
Set the temporary buffer to the empty string. Switch to the RAWTEXT end tag open state.
Anything else
Emit a U+003C LESS-THAN SIGN character token and reconsume the current input character in the RAWTEXT state.
8.2.4.15 RAWTEXT end tag open state

Status: Last call for comments

Consume the next input character:

U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
Create a new end tag token, and set its tag name to the lowercase version of the current input character (add 0x0020 to the character's code point). Append the current input character to the temporary buffer. Finally, switch to the RAWTEXT end tag name state. (Don't emit the token yet; further details will be filled in before it is emitted.)
U+0061 LATIN SMALL LETTER A through to U+007A LATIN SMALL LETTER Z
Create a new end tag token, and set its tag name to the current input character. Append the current input character to the temporary buffer. Finally, switch to the RAWTEXT end tag name state. (Don't emit the token yet; further details will be filled in before it is emitted.)
Anything else
Emit a U+003C LESS-THAN SIGN character token, a U+002F SOLIDUS character token, and reconsume the current input character in the RAWTEXT state.
8.2.4.16 RAWTEXT end tag name state

Status: Last call for comments

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
If the current end tag token is an appropriate end tag token, then switch to the before attribute name state. Otherwise, treat it as per the "anything else" entry below.
U+002F SOLIDUS (/)
If the current end tag token is an appropriate end tag token, then switch to the self-closing start tag state. Otherwise, treat it as per the "anything else" entry below.
U+003E GREATER-THAN SIGN (>)
If the current end tag token is an appropriate end tag token, then emit the current tag token and switch to the data state. Otherwise, treat it as per the "anything else" entry below.
U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
Append the lowercase version of the current input character (add 0x0020 to the character's code point) to the current tag token's tag name. Append the current input character to the temporary buffer. Stay in the RAWTEXT end tag name state.
U+0061 LATIN SMALL LETTER A through to U+007A LATIN SMALL LETTER Z
Append the current input character to the current tag token's tag name. Append the current input character to the temporary buffer. Stay in the RAWTEXT end tag name state.
Anything else
Emit a U+003C LESS-THAN SIGN character token, a U+002F SOLIDUS character token, a character token for each of the characters in the temporary buffer (in the order they were added to the buffer), and reconsume the current input character in the RAWTEXT state.
8.2.4.17 Script data less-than sign state

Status: Last call for comments

Consume the next input character:

U+002F SOLIDUS (/)
Set the temporary buffer to the empty string. Switch to the script data end tag open state.
U+0021 EXCLAMATION MARK (!)
Emit a U+003C LESS-THAN SIGN character token and a U+0021 EXCLAMATION MARK character token. Switch to the script data escape start state.
Anything else
Emit a U+003C LESS-THAN SIGN character token and reconsume the current input character in the script data state.
8.2.4.18 Script data end tag open state

Status: Last call for comments

Consume the next input character:

U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
Create a new end tag token, and set its tag name to the lowercase version of the current input character (add 0x0020 to the character's code point). Append the current input character to the temporary buffer. Finally, switch to the script data end tag name state. (Don't emit the token yet; further details will be filled in before it is emitted.)
U+0061 LATIN SMALL LETTER A through to U+007A LATIN SMALL LETTER Z
Create a new end tag token, and set its tag name to the current input character. Append the current input character to the temporary buffer. Finally, switch to the script data end tag name state. (Don't emit the token yet; further details will be filled in before it is emitted.)
Anything else
Emit a U+003C LESS-THAN SIGN character token, a U+002F SOLIDUS character token, and reconsume the current input character in the script data state.
8.2.4.19 Script data end tag name state

Status: Last call for comments

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
If the current end tag token is an appropriate end tag token, then switch to the before attribute name state. Otherwise, treat it as per the "anything else" entry below.
U+002F SOLIDUS (/)
If the current end tag token is an appropriate end tag token, then switch to the self-closing start tag state. Otherwise, treat it as per the "anything else" entry below.
U+003E GREATER-THAN SIGN (>)
If the current end tag token is an appropriate end tag token, then emit the current tag token and switch to the data state. Otherwise, treat it as per the "anything else" entry below.
U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
Append the lowercase version of the current input character (add 0x0020 to the character's code point) to the current tag token's tag name. Append the current input character to the temporary buffer. Stay in the script data end tag name state.
U+0061 LATIN SMALL LETTER A through to U+007A LATIN SMALL LETTER Z
Append the current input character to the current tag token's tag name. Append the current input character to the temporary buffer. Stay in the script data end tag name state.
Anything else
Emit a U+003C LESS-THAN SIGN character token, a U+002F SOLIDUS character token, a character token for each of the characters in the temporary buffer (in the order they were added to the buffer), and reconsume the current input character in the script data state.
8.2.4.20 Script data escape start state

Status: Last call for comments

Consume the next input character:

U+002D HYPHEN-MINUS (-)
Emit a U+002D HYPHEN-MINUS character token. Switch to the script data escape start dash state.
Anything else
Reconsume the current input character in the script data state.
8.2.4.21 Script data escape start dash state

Status: Last call for comments

Consume the next input character:

U+002D HYPHEN-MINUS (-)
Emit a U+002D HYPHEN-MINUS character token. Switch to the script data escaped dash dash state.
Anything else
Reconsume the current input character in the script data state.
8.2.4.22 Script data escaped state

Status: Last call for comments

Consume the next input character:

U+002D HYPHEN-MINUS (-)
Emit a U+002D HYPHEN-MINUS character token. Switch to the script data escaped dash state.
U+003C LESS-THAN SIGN (<)

Switch to the script data escaped less-than sign state.

EOF
Parse error. Reconsume the EOF character in the data state.
Anything else
Emit the current input character as a character token. Stay in the script data escaped state.
8.2.4.23 Script data escaped dash state

Status: Last call for comments

Consume the next input character:

U+002D HYPHEN-MINUS (-)
Emit a U+002D HYPHEN-MINUS character token. Switch to the script data escaped dash dash state.
U+003C LESS-THAN SIGN (<)

Switch to the script data escaped less-than sign state.

EOF
Parse error. Reconsume the EOF character in the data state.
Anything else
Emit the current input character as a character token. Switch to the script data escaped state.
8.2.4.24 Script data escaped dash dash state

Status: Last call for comments

Consume the next input character:

U+002D HYPHEN-MINUS (-)
Emit a U+002D HYPHEN-MINUS character token. Stay in the script data escaped dash dash state.
U+003C LESS-THAN SIGN (<)

Switch to the script data escaped less-than sign state.

U+003E GREATER-THAN SIGN (>)
Emit a U+003E GREATER-THAN SIGN character token. Switch to the script data state.
EOF
Parse error. Reconsume the EOF character in the data state.
Anything else
Emit the current input character as a character token. Switch to the script data escaped state.
8.2.4.25 Script data escaped less-than sign state

Status: Last call for comments

Consume the next input character:

U+002F SOLIDUS (/)
Set the temporary buffer to the empty string. Switch to the script data escaped end tag open state.
U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
Emit a U+003C LESS-THAN SIGN character token and the current input character as a character token. Set the temporary buffer to the empty string. Append the lowercase version of the current input character (add 0x0020 to the character's code point) to the temporary buffer. Switch to the script data double escape start state.
U+0061 LATIN SMALL LETTER A through to U+007A LATIN SMALL LETTER Z
Emit a U+003C LESS-THAN SIGN character token and the current input character as a character token. Set the temporary buffer to the empty string. Append the current input character to the temporary buffer. Switch to the script data double escape start state.
Anything else
Emit a U+003C LESS-THAN SIGN character token and reconsume the current input character in the script data escaped state.
8.2.4.26 Script data escaped end tag open state

Status: Last call for comments

Consume the next input character:

U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
Create a new end tag token, and set its tag name to the lowercase version of the current input character (add 0x0020 to the character's code point). Append the current input character to the temporary buffer. Finally, switch to the script data escaped end tag name state. (Don't emit the token yet; further details will be filled in before it is emitted.)
U+0061 LATIN SMALL LETTER A through to U+007A LATIN SMALL LETTER Z
Create a new end tag token, and set its tag name to the current input character. Append the current input character to the temporary buffer. Finally, switch to the script data escaped end tag name state. (Don't emit the token yet; further details will be filled in before it is emitted.)
Anything else
Emit a U+003C LESS-THAN SIGN character token, a U+002F SOLIDUS character token, and reconsume the current input character in the script data escaped state.
8.2.4.27 Script data escaped end tag name state

Status: Last call for comments

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
If the current end tag token is an appropriate end tag token, then switch to the before attribute name state. Otherwise, treat it as per the "anything else" entry below.
U+002F SOLIDUS (/)
If the current end tag token is an appropriate end tag token, then switch to the self-closing start tag state. Otherwise, treat it as per the "anything else" entry below.
U+003E GREATER-THAN SIGN (>)
If the current end tag token is an appropriate end tag token, then emit the current tag token and switch to the data state. Otherwise, treat it as per the "anything else" entry below.
U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
Append the lowercase version of the current input character (add 0x0020 to the character's code point) to the current tag token's tag name. Append the current input character to the temporary buffer. Stay in the script data escaped end tag name state.
U+0061 LATIN SMALL LETTER A through to U+007A LATIN SMALL LETTER Z
Append the current input character to the current tag token's tag name. Append the current input character to the temporary buffer. Stay in the script data escaped end tag name state.
Anything else
Emit a U+003C LESS-THAN SIGN character token, a U+002F SOLIDUS character token, a character token for each of the characters in the temporary buffer (in the order they were added to the buffer), and reconsume the current input character in the script data escaped state.
8.2.4.28 Script data double escape start state

Status: Last call for comments

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
U+002F SOLIDUS (/)
U+003E GREATER-THAN SIGN (>)
Emit the current input character as a character token. If the temporary buffer is the string "script", then switch to the script data double escaped state. Otherwise, switch to the script data escaped state.
U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
Emit the current input character as a character token. Append the lowercase version of the current input character (add 0x0020 to the character's code point) to the temporary buffer. Stay in the script data double escape start state.
U+0061 LATIN SMALL LETTER A through to U+007A LATIN SMALL LETTER Z
Emit the current input character as a character token. Append the current input character to the temporary buffer. Stay in the script data double escape start state.
Anything else
Reconsume the current input character in the script data escaped state.
8.2.4.29 Script data double escaped state

Status: Last call for comments

Consume the next input character:

U+002D HYPHEN-MINUS (-)
Emit a U+002D HYPHEN-MINUS character token. Switch to the script data double escaped dash state.
U+003C LESS-THAN SIGN (<)

Emit a U+003C LESS-THAN SIGN character token. Switch to the script data double escaped less-than sign state.

EOF
Parse error. Reconsume the EOF character in the data state.
Anything else
Emit the current input character as a character token. Stay in the script data double escaped state.
8.2.4.30 Script data double escaped dash state

Status: Last call for comments

Consume the next input character:

U+002D HYPHEN-MINUS (-)
Emit a U+002D HYPHEN-MINUS character token. Switch to the script data double escaped dash dash state.
U+003C LESS-THAN SIGN (<)

Emit a U+003C LESS-THAN SIGN character token. Switch to the script data double escaped less-than sign state.

EOF
Parse error. Reconsume the EOF character in the data state.
Anything else
Emit the current input character as a character token. Switch to the script data double escaped state.
8.2.4.31 Script data double escaped dash dash state

Status: Last call for comments

Consume the next input character:

U+002D HYPHEN-MINUS (-)
Emit a U+002D HYPHEN-MINUS character token. Stay in the script data double escaped dash dash state.
U+003C LESS-THAN SIGN (<)

Emit a U+003C LESS-THAN SIGN character token. Switch to the script data double escaped less-than sign state.

U+003E GREATER-THAN SIGN (>)
Emit a U+003E GREATER-THAN SIGN character token. Switch to the script data state.
EOF
Parse error. Reconsume the EOF character in the data state.
Anything else
Emit the current input character as a character token. Switch to the script data double escaped state.
8.2.4.32 Script data double escaped less-than sign state

Status: Last call for comments

Consume the next input character:

U+002F SOLIDUS (/)
Emit a U+002F SOLIDUS character token. Set the temporary buffer to the empty string. Switch to the script data double escape end state.
Anything else
Reconsume the current input character in the script data double escaped state.
8.2.4.33 Script data double escape end state

Status: Last call for comments

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
U+002F SOLIDUS (/)
U+003E GREATER-THAN SIGN (>)
Emit the current input character as a character token. If the temporary buffer is the string "script", then switch to the script data escaped state. Otherwise, switch to the script data double escaped state.
U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
Emit the current input character as a character token. Append the lowercase version of the current input character (add 0x0020 to the character's code point) to the temporary buffer. Stay in the script data double escape end state.
U+0061 LATIN SMALL LETTER A through to U+007A LATIN SMALL LETTER Z
Emit the current input character as a character token. Append the current input character to the temporary buffer. Stay in the script data double escape end state.
Anything else
Reconsume the current input character in the script data double escaped state.
8.2.4.34 Before attribute name state

Status: Last call for comments

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
Stay in the before attribute name state.
U+002F SOLIDUS (/)
Switch to the self-closing start tag state.
U+003E GREATER-THAN SIGN (>)
Emit the current tag token. Switch to the data state.
U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
Start a new attribute in the current tag token. Set that attribute's name to the lowercase version of the current input character (add 0x0020 to the character's code point), and its value to the empty string. Switch to the attribute name state.
U+0022 QUOTATION MARK (")
U+0027 APOSTROPHE (')
U+003C LESS-THAN SIGN (<)
U+003D EQUALS SIGN (=)
Parse error. Treat it as per the "anything else" entry below.
EOF
Parse error. Reconsume the EOF character in the data state.
Anything else
Start a new attribute in the current tag token. Set that attribute's name to the current input character, and its value to the empty string. Switch to the attribute name state.
8.2.4.35 Attribute name state

Status: Last call for comments

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
Switch to the after attribute name state.
U+002F SOLIDUS (/)
Switch to the self-closing start tag state.
U+003D EQUALS SIGN (=)
Switch to the before attribute value state.
U+003E GREATER-THAN SIGN (>)
Emit the current tag token. Switch to the data state.
U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
Append the lowercase version of the current input character (add 0x0020 to the character's code point) to the current attribute's name. Stay in the attribute name state.
U+0022 QUOTATION MARK (")
U+0027 APOSTROPHE (')
U+003C LESS-THAN SIGN (<)
Parse error. Treat it as per the "anything else" entry below.
EOF
Parse error. Reconsume the EOF character in the data state.
Anything else
Append the current input character to the current attribute's name. Stay in the attribute name state.

When the user agent leaves the attribute name state (and before emitting the tag token, if appropriate), the complete attribute's name must be compared to the other attributes on the same token; if there is already an attribute on the token with the exact same name, then this is a parse error and the new attribute must be dropped, along with the value that gets associated with it (if any).

8.2.4.36 After attribute name state

Status: Last call for comments

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
Stay in the after attribute name state.
U+002F SOLIDUS (/)
Switch to the self-closing start tag state.
U+003D EQUALS SIGN (=)
Switch to the before attribute value state.
U+003E GREATER-THAN SIGN (>)
Emit the current tag token. Switch to the data state.
U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
Start a new attribute in the current tag token. Set that attribute's name to the lowercase version of the current input character (add 0x0020 to the character's code point), and its value to the empty string. Switch to the attribute name state.
U+0022 QUOTATION MARK (")
U+0027 APOSTROPHE (')
U+003C LESS-THAN SIGN (<)
Parse error. Treat it as per the "anything else" entry below.
EOF
Parse error. Reconsume the EOF character in the data state.
Anything else
Start a new attribute in the current tag token. Set that attribute's name to the current input character, and its value to the empty string. Switch to the attribute name state.
8.2.4.37 Before attribute value state

Status: Last call for comments

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
Stay in the before attribute value state.
U+0022 QUOTATION MARK (")
Switch to the attribute value (double-quoted) state.
U+0026 AMPERSAND (&)
Switch to the attribute value (unquoted) state and reconsume this current input character.
U+0027 APOSTROPHE (')
Switch to the attribute value (single-quoted) state.
U+003E GREATER-THAN SIGN (>)
Parse error. Emit the current tag token. Switch to the data state.
U+003C LESS-THAN SIGN (<)
U+003D EQUALS SIGN (=)
U+0060 GRAVE ACCENT (`)
Parse error. Treat it as per the "anything else" entry below.
EOF
Parse error. Reconsume the EOF character in the data state.
Anything else
Append the current input character to the current attribute's value. Switch to the attribute value (unquoted) state.
8.2.4.38 Attribute value (double-quoted) state

Consume the next input character:

U+0022 QUOTATION MARK (")
Switch to the after attribute value (quoted) state.
U+0026 AMPERSAND (&)
Switch to the character reference in attribute value state, with the additional allowed character being U+0022 QUOTATION MARK (").
EOF
Parse error. Reconsume the EOF character in the data state.
Anything else
Append the current input character to the current attribute's value. Stay in the attribute value (double-quoted) state.
8.2.4.39 Attribute value (single-quoted) state

Consume the next input character:

U+0027 APOSTROPHE (')
Switch to the after attribute value (quoted) state.
U+0026 AMPERSAND (&)
Switch to the character reference in attribute value state, with the additional allowed character being U+0027 APOSTROPHE (').
EOF
Parse error. Reconsume the EOF character in the data state.
Anything else
Append the current input character to the current attribute's value. Stay in the attribute value (single-quoted) state.
8.2.4.40 Attribute value (unquoted) state

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
Switch to the before attribute name state.
U+0026 AMPERSAND (&)
Switch to the character reference in attribute value state, with the additional allowed character being U+003E GREATER-THAN SIGN (>).
U+003E GREATER-THAN SIGN (>)
Emit the current tag token. Switch to the data state.
U+0022 QUOTATION MARK (")
U+0027 APOSTROPHE (')
U+003C LESS-THAN SIGN (<)
U+003D EQUALS SIGN (=)
U+0060 GRAVE ACCENT (`)
Parse error. Treat it as per the "anything else" entry below.
EOF
Parse error. Reconsume the EOF character in the data state.
Anything else
Append the current input character to the current attribute's value. Stay in the attribute value (unquoted) state.
8.2.4.41 Character reference in attribute value state

Status: Last call for comments

Attempt to consume a character reference.

If nothing is returned, append a U+0026 AMPERSAND character to the current attribute's value.

Otherwise, append the returned character token to the current attribute's value.

Finally, switch back to the attribute value state that you were in when were switched into this state.

8.2.4.42 After attribute value (quoted) state

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
Switch to the before attribute name state.
U+002F SOLIDUS (/)
Switch to the self-closing start tag state.
U+003E GREATER-THAN SIGN (>)
Emit the current tag token. Switch to the data state.
EOF
Parse error. Reconsume the EOF character in the data state.
Anything else
Parse error. Reconsume the character in the before attribute name state.
8.2.4.43 Self-closing start tag state

Status: Last call for comments

Consume the next input character:

U+003E GREATER-THAN SIGN (>)
Set the self-closing flag of the current tag token. Emit the current tag token. Switch to the data state.
EOF
Parse error. Reconsume the EOF character in the data state.
Anything else
Parse error. Reconsume the character in the before attribute name state.
8.2.4.44 Bogus comment state

Status: Last call for comments

Consume every character up to and including the first U+003E GREATER-THAN SIGN character (>) or the end of the file (EOF), whichever comes first. Emit a comment token whose data is the concatenation of all the characters starting from and including the character that caused the state machine to switch into the bogus comment state, up to and including the character immediately before the last consumed character (i.e. up to the character just before the U+003E or EOF character). (If the comment was started by the end of the file (EOF), the token is empty.)

Switch to the data state.

If the end of the file was reached, reconsume the EOF character.

8.2.4.45 Markup declaration open state

Status: Last call for comments

If the next two characters are both U+002D HYPHEN-MINUS characters (-), consume those two characters, create a comment token whose data is the empty string, and switch to the comment start state.

Otherwise, if the next seven characters are an ASCII case-insensitive match for the word "DOCTYPE", then consume those characters and switch to the DOCTYPE state.

Otherwise, if the insertion mode is "in foreign content" and the current node is not an element in the HTML namespace and the next seven characters are an case-sensitive match for the string "[CDATA[" (the five uppercase letters "CDATA" with a U+005B LEFT SQUARE BRACKET character before and after), then consume those characters and switch to the CDATA section state.

Otherwise, this is a parse error. Switch to the bogus comment state. The next character that is consumed, if any, is the first character that will be in the comment.

8.2.4.46 Comment start state

Status: Last call for comments

Consume the next input character:

U+002D HYPHEN-MINUS (-)
Switch to the comment start dash state.
U+003E GREATER-THAN SIGN (>)
Parse error. Emit the comment token. Switch to the data state.
EOF
Parse error. Emit the comment token. Reconsume the EOF character in the data state.
Anything else
Append the current input character to the comment token's data. Switch to the comment state.
8.2.4.47 Comment start dash state

Status: Last call for comments

Consume the next input character:

U+002D HYPHEN-MINUS (-)
Switch to the comment end state
U+003E GREATER-THAN SIGN (>)
Parse error. Emit the comment token. Switch to the data state.
EOF
Parse error. Emit the comment token. Reconsume the EOF character in the data state.
Anything else
Append a U+002D HYPHEN-MINUS character (-) and the current input character to the comment token's data. Switch to the comment state.
8.2.4.48 Comment state

Status: Last call for comments

Consume the next input character:

U+002D HYPHEN-MINUS (-)
Switch to the comment end dash state
EOF
Parse error. Emit the comment token. Reconsume the EOF character in the data state.
Anything else
Append the current input character to the comment token's data. Stay in the comment state.
8.2.4.49 Comment end dash state

Status: Last call for comments

Consume the next input character:

U+002D HYPHEN-MINUS (-)
Switch to the comment end state
EOF
Parse error. Emit the comment token. Reconsume the EOF character in the data state.
Anything else
Append a U+002D HYPHEN-MINUS character (-) and the current input character to the comment token's data. Switch to the comment state.
8.2.4.50 Comment end state

Status: Last call for comments

Consume the next input character:

U+003E GREATER-THAN SIGN (>)
Emit the comment token. Switch to the data state.
U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
Parse error. Append two U+002D HYPHEN-MINUS characters (-) and the current input character to the comment token's data. Switch to the comment end space state.
U+0021 EXCLAMATION MARK (!)
Parse error. Switch to the comment end bang state.
U+002D HYPHEN-MINUS (-)
Parse error. Append a U+002D HYPHEN-MINUS character (-) to the comment token's data. Stay in the comment end state.
EOF
Parse error. Emit the comment token. Reconsume the EOF character in the data state.
Anything else
Parse error. Append two U+002D HYPHEN-MINUS characters (-) and the current input character to the comment token's data. Switch to the comment state.
8.2.4.51 Comment end bang state

Status: Last call for comments

Consume the next input character:

U+002D HYPHEN-MINUS (-)
Append two U+002D HYPHEN-MINUS characters (-) and a U+0021 EXCLAMATION MARK character (!) to the comment token's data. Switch to the comment end dash state.
U+003E GREATER-THAN SIGN (>)
Emit the comment token. Switch to the data state.
EOF
Parse error. Emit the comment token. Reconsume the EOF character in the data state.
Anything else
Append two U+002D HYPHEN-MINUS characters (-), a U+0021 EXCLAMATION MARK character (!), and the current input character to the comment token's data. Switch to the comment state.
8.2.4.52 Comment end space state

Status: Last call for comments

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
Append the current input character to the comment token's data. Stay in the comment end space state.
U+002D HYPHEN-MINUS (-)
Switch to the comment end dash state.
U+003E GREATER-THAN SIGN (>)
Emit the comment token. Switch to the data state.
EOF
Parse error. Emit the comment token. Reconsume the EOF character in the data state.
Anything else
Append the current input character to the comment token's data. Switch to the comment state.
8.2.4.53 DOCTYPE state

Status: Last call for comments

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
Switch to the before DOCTYPE name state.
EOF
Parse error. Create a new DOCTYPE token. Set its force-quirks flag to on. Emit the token. Reconsume the EOF character in the data state.
Anything else
Parse error. Reconsume the character in the before DOCTYPE name state.
8.2.4.54 Before DOCTYPE name state

Status: Last call for comments

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
Stay in the before DOCTYPE name state.
U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
Create a new DOCTYPE token. Set the token's name to the lowercase version of the current input character (add 0x0020 to the character's code point). Switch to the DOCTYPE name state.
U+003E GREATER-THAN SIGN (>)
Parse error. Create a new DOCTYPE token. Set its force-quirks flag to on. Emit the token. Switch to the data state.
EOF
Parse error. Create a new DOCTYPE token. Set its force-quirks flag to on. Emit the token. Reconsume the EOF character in the data state.
Anything else
Create a new DOCTYPE token. Set the token's name to the current input character. Switch to the DOCTYPE name state.
8.2.4.55 DOCTYPE name state

Status: Last call for comments

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
Switch to the after DOCTYPE name state.
U+003E GREATER-THAN SIGN (>)
Emit the current DOCTYPE token. Switch to the data state.
U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
Append the lowercase version of the current input character (add 0x0020 to the character's code point) to the current DOCTYPE token's name. Stay in the DOCTYPE name state.
EOF
Parse error. Set the DOCTYPE token's force-quirks flag to on. Emit that DOCTYPE token. Reconsume the EOF character in the data state.
Anything else
Append the current input character to the current DOCTYPE token's name. Stay in the DOCTYPE name state.
8.2.4.56 After DOCTYPE name state

Status: Last call for comments

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
Stay in the after DOCTYPE name state.
U+003E GREATER-THAN SIGN (>)
Emit the current DOCTYPE token. Switch to the data state.
EOF
Parse error. Set the DOCTYPE token's force-quirks flag to on. Emit that DOCTYPE token. Reconsume the EOF character in the data state.
Anything else

If the six characters starting from the current input character are an ASCII case-insensitive match for the word "PUBLIC", then consume those characters and switch to the after DOCTYPE public keyword state.

Otherwise, if the six characters starting from the current input character are an ASCII case-insensitive match for the word "SYSTEM", then consume those characters and switch to the after DOCTYPE system keyword state.

Otherwise, this is the parse error. Set the DOCTYPE token's force-quirks flag to on. Switch to the bogus DOCTYPE state.

8.2.4.57 After DOCTYPE public keyword state

Status: Last call for comments

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
Switch to the before DOCTYPE public identifier state.
U+0022 QUOTATION MARK (")
Parse error. Set the DOCTYPE token's public identifier to the empty string (not missing), then switch to the DOCTYPE public identifier (double-quoted) state.
U+0027 APOSTROPHE (')
Parse error. Set the DOCTYPE token's public identifier to the empty string (not missing), then switch to the DOCTYPE public identifier (single-quoted) state.
U+003E GREATER-THAN SIGN (>)
Parse error. Set the DOCTYPE token's force-quirks flag to on. Emit that DOCTYPE token. Switch to the data state.
EOF
Parse error. Set the DOCTYPE token's force-quirks flag to on. Emit that DOCTYPE token. Reconsume the EOF character in the data state.
Anything else
Parse error. Set the DOCTYPE token's force-quirks flag to on. Switch to the bogus DOCTYPE state.
8.2.4.58 Before DOCTYPE public identifier state

Status: Last call for comments

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
Stay in the before DOCTYPE public identifier state.
U+0022 QUOTATION MARK (")
Set the DOCTYPE token's public identifier to the empty string (not missing), then switch to the DOCTYPE public identifier (double-quoted) state.
U+0027 APOSTROPHE (')
Set the DOCTYPE token's public identifier to the empty string (not missing), then switch to the DOCTYPE public identifier (single-quoted) state.
U+003E GREATER-THAN SIGN (>)
Parse error. Set the DOCTYPE token's force-quirks flag to on. Emit that DOCTYPE token. Switch to the data state.
EOF
Parse error. Set the DOCTYPE token's force-quirks flag to on. Emit that DOCTYPE token. Reconsume the EOF character in the data state.
Anything else
Parse error. Set the DOCTYPE token's force-quirks flag to on. Switch to the bogus DOCTYPE state.
8.2.4.59 DOCTYPE public identifier (double-quoted) state

Consume the next input character:

U+0022 QUOTATION MARK (")
Switch to the after DOCTYPE public identifier state.
U+003E GREATER-THAN SIGN (>)
Parse error. Set the DOCTYPE token's force-quirks flag to on. Emit that DOCTYPE token. Switch to the data state.
EOF
Parse error. Set the DOCTYPE token's force-quirks flag to on. Emit that DOCTYPE token. Reconsume the EOF character in the data state.
Anything else
Append the current input character to the current DOCTYPE token's public identifier. Stay in the DOCTYPE public identifier (double-quoted) state.
8.2.4.60 DOCTYPE public identifier (single-quoted) state

Consume the next input character:

U+0027 APOSTROPHE (')
Switch to the after DOCTYPE public identifier state.
U+003E GREATER-THAN SIGN (>)
Parse error. Set the DOCTYPE token's force-quirks flag to on. Emit that DOCTYPE token. Switch to the data state.
EOF
Parse error. Set the DOCTYPE token's force-quirks flag to on. Emit that DOCTYPE token. Reconsume the EOF character in the data state.
Anything else
Append the current input character to the current DOCTYPE token's public identifier. Stay in the DOCTYPE public identifier (single-quoted) state.
8.2.4.61 After DOCTYPE public identifier state

Status: Last call for comments

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
Switch to the between DOCTYPE public and system identifiers state.
U+003E GREATER-THAN SIGN (>)
Emit the current DOCTYPE token. Switch to the data state.
U+0022 QUOTATION MARK (")
Parse error. Set the DOCTYPE token's system identifier to the empty string (not missing), then switch to the DOCTYPE system identifier (double-quoted) state.
U+0027 APOSTROPHE (')
Parse error. Set the DOCTYPE token's system identifier to the empty string (not missing), then switch to the DOCTYPE system identifier (single-quoted) state.
EOF
Parse error. Set the DOCTYPE token's force-quirks flag to on. Emit that DOCTYPE token. Reconsume the EOF character in the data state.
Anything else
Parse error. Set the DOCTYPE token's force-quirks flag to on. Switch to the bogus DOCTYPE state.
8.2.4.62 Between DOCTYPE public and system identifiers state

Status: Last call for comments

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
Stay in the between DOCTYPE public and system identifiers state.
U+003E GREATER-THAN SIGN (>)
Emit the current DOCTYPE token. Switch to the data state.
U+0022 QUOTATION MARK (")
Set the DOCTYPE token's system identifier to the empty string (not missing), then switch to the DOCTYPE system identifier (double-quoted) state.
U+0027 APOSTROPHE (')
Set the DOCTYPE token's system identifier to the empty string (not missing), then switch to the DOCTYPE system identifier (single-quoted) state.
EOF
Parse error. Set the DOCTYPE token's force-quirks flag to on. Emit that DOCTYPE token. Reconsume the EOF character in the data state.
Anything else
Parse error. Set the DOCTYPE token's force-quirks flag to on. Switch to the bogus DOCTYPE state.
8.2.4.63 After DOCTYPE system keyword state

Status: Last call for comments

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
Switch to the before DOCTYPE system identifier state.
U+0022 QUOTATION MARK (")
Parse error. Set the DOCTYPE token's system identifier to the empty string (not missing), then switch to the DOCTYPE system identifier (double-quoted) state.
U+0027 APOSTROPHE (')
Parse error. Set the DOCTYPE token's system identifier to the empty string (not missing), then switch to the DOCTYPE system identifier (single-quoted) state.
U+003E GREATER-THAN SIGN (>)
Parse error. Set the DOCTYPE token's force-quirks flag to on. Emit that DOCTYPE token. Switch to the data state.
EOF
Parse error. Set the DOCTYPE token's force-quirks flag to on. Emit that DOCTYPE token. Reconsume the EOF character in the data state.
Anything else
Parse error. Set the DOCTYPE token's force-quirks flag to on. Switch to the bogus DOCTYPE state.
8.2.4.64 Before DOCTYPE system identifier state

Status: Last call for comments

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
Stay in the before DOCTYPE system identifier state.
U+0022 QUOTATION MARK (")
Set the DOCTYPE token's system identifier to the empty string (not missing), then switch to the DOCTYPE system identifier (double-quoted) state.
U+0027 APOSTROPHE (')
Set the DOCTYPE token's system identifier to the empty string (not missing), then switch to the DOCTYPE system identifier (single-quoted) state.
U+003E GREATER-THAN SIGN (>)
Parse error. Set the DOCTYPE token's force-quirks flag to on. Emit that DOCTYPE token. Switch to the data state.
EOF
Parse error. Set the DOCTYPE token's force-quirks flag to on. Emit that DOCTYPE token. Reconsume the EOF character in the data state.
Anything else
Parse error. Set the DOCTYPE token's force-quirks flag to on. Switch to the bogus DOCTYPE state.
8.2.4.65 DOCTYPE system identifier (double-quoted) state

Consume the next input character:

U+0022 QUOTATION MARK (")
Switch to the after DOCTYPE system identifier state.
U+003E GREATER-THAN SIGN (>)
Parse error. Set the DOCTYPE token's force-quirks flag to on. Emit that DOCTYPE token. Switch to the data state.
EOF
Parse error. Set the DOCTYPE token's force-quirks flag to on. Emit that DOCTYPE token. Reconsume the EOF character in the data state.
Anything else
Append the current input character to the current DOCTYPE token's system identifier. Stay in the DOCTYPE system identifier (double-quoted) state.
8.2.4.66 DOCTYPE system identifier (single-quoted) state

Consume the next input character:

U+0027 APOSTROPHE (')
Switch to the after DOCTYPE system identifier state.
U+003E GREATER-THAN SIGN (>)
Parse error. Set the DOCTYPE token's force-quirks flag to on. Emit that DOCTYPE token. Switch to the data state.
EOF
Parse error. Set the DOCTYPE token's force-quirks flag to on. Emit that DOCTYPE token. Reconsume the EOF character in the data state.
Anything else
Append the current input character to the current DOCTYPE token's system identifier. Stay in the DOCTYPE system identifier (single-quoted) state.
8.2.4.67 After DOCTYPE system identifier state

Status: Last call for comments

Consume the next input character:

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
Stay in the after DOCTYPE system identifier state.
U+003E GREATER-THAN SIGN (>)
Emit the current DOCTYPE token. Switch to the data state.
EOF
Parse error. Set the DOCTYPE token's force-quirks flag to on. Emit that DOCTYPE token. Reconsume the EOF character in the data state.
Anything else
Parse error. Switch to the bogus DOCTYPE state. (This does not set the DOCTYPE token's force-quirks flag to on.)
8.2.4.68 Bogus DOCTYPE state

Status: Last call for comments

Consume the next input character:

U+003E GREATER-THAN SIGN (>)
Emit the DOCTYPE token. Switch to the data state.
EOF
Emit the DOCTYPE token. Reconsume the EOF character in the data state.
Anything else
Stay in the bogus DOCTYPE state.
8.2.4.69 CDATA section state

Status: Last call for comments

Consume every character up to the next occurrence of the three character sequence U+005D RIGHT SQUARE BRACKET U+005D RIGHT SQUARE BRACKET U+003E GREATER-THAN SIGN (]]>), or the end of the file (EOF), whichever comes first. Emit a series of character tokens consisting of all the characters consumed except the matching three character sequence at the end (if one was found before the end of the file).

Switch to the data state.

If the end of the file was reached, reconsume the EOF character.

8.2.4.70 Tokenizing character references

Status: Last call for comments

This section defines how to consume a character reference. This definition is used when parsing character references in text and in attributes.

The behavior depends on the identity of the next character (the one immediately after the U+0026 AMPERSAND character):

U+0009 CHARACTER TABULATION
U+000A LINE FEED (LF)
U+000C FORM FEED (FF)
U+0020 SPACE
U+003C LESS-THAN SIGN
U+0026 AMPERSAND
EOF
The additional allowed character, if there is one
Not a character reference. No characters are consumed, and nothing is returned. (This is not an error, either.)
U+0023 NUMBER SIGN (#)

Consume the U+0023 NUMBER SIGN.

The behavior further depends on the character after the U+0023 NUMBER SIGN:

U+0078 LATIN SMALL LETTER X
U+0058 LATIN CAPITAL LETTER X

Consume the X.

Follow the steps below, but using the range of characters U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9), U+0061 LATIN SMALL LETTER A to U+0066 LATIN SMALL LETTER F, and U+0041 LATIN CAPITAL LETTER A to U+0046 LATIN CAPITAL LETTER F (in other words, 0-9, A-F, a-f).

When it comes to interpreting the number, interpret it as a hexadecimal number.

Anything else

Follow the steps below, but using the range of characters U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9).

When it comes to interpreting the number, interpret it as a decimal number.

Consume as many characters as match the range of characters given above.

If no characters match the range, then don't consume any characters (and unconsume the U+0023 NUMBER SIGN character and, if appropriate, the X character). This is a parse error; nothing is returned.

Otherwise, if the next character is a U+003B SEMICOLON, consume that too. If it isn't, there is a parse error.

If one or more characters match the range, then take them all and interpret the string of characters as a number (either hexadecimal or decimal as appropriate).

If that number is one of the numbers in the first column of the following table, then this is a parse error. Find the row with that number in the first column, and return a character token for the Unicode character given in the second column of that row.

Number Unicode character
0x00 U+FFFD REPLACEMENT CHARACTER
0x0D U+000A LINE FEED (LF)
0x80 U+20AC EURO SIGN (€)
0x81 U+0081 <control>
0x82 U+201A SINGLE LOW-9 QUOTATION MARK (‚)
0x83 U+0192 LATIN SMALL LETTER F WITH HOOK (ƒ)
0x84 U+201E DOUBLE LOW-9 QUOTATION MARK („)
0x85 U+2026 HORIZONTAL ELLIPSIS (…)
0x86 U+2020 DAGGER (†)
0x87 U+2021 DOUBLE DAGGER (‡)
0x88 U+02C6 MODIFIER LETTER CIRCUMFLEX ACCENT (ˆ)
0x89 U+2030 PER MILLE SIGN (‰)
0x8A U+0160 LATIN CAPITAL LETTER S WITH CARON (Š)
0x8B U+2039 SINGLE LEFT-POINTING ANGLE QUOTATION MARK (‹)
0x8C U+0152 LATIN CAPITAL LIGATURE OE (Œ)
0x8D U+008D <control>
0x8E U+017D LATIN CAPITAL LETTER Z WITH CARON (Ž)
0x8F U+008F <control>
0x90 U+0090 <control>
0x91 U+2018 LEFT SINGLE QUOTATION MARK (‘)
0x92 U+2019 RIGHT SINGLE QUOTATION MARK (’)
0x93 U+201C LEFT DOUBLE QUOTATION MARK (“)
0x94 U+201D RIGHT DOUBLE QUOTATION MARK (”)
0x95 U+2022 BULLET (•)
0x96 U+2013 EN DASH (–)
0x97 U+2014 EM DASH (—)
0x98 U+02DC SMALL TILDE (˜)
0x99 U+2122 TRADE MARK SIGN (™)
0x9A U+0161 LATIN SMALL LETTER S WITH CARON (š)
0x9B U+203A SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (›)
0x9C U+0153 LATIN SMALL LIGATURE OE (œ)
0x9D U+009D <control>
0x9E U+017E LATIN SMALL LETTER Z WITH CARON (ž)
0x9F U+0178 LATIN CAPITAL LETTER Y WITH DIAERESIS (Ÿ)

Otherwise, if the number is in the range 0xD800 to 0xDFFF or is greater than 0x10FFFF, then this is a parse error. Return a U+FFFD REPLACEMENT CHARACTER.

Otherwise, return a character token for the Unicode character whose code point is that number. If the number is in the range 0x0001 to 0x0008, 0x000E to 0x001F, 0x007F to 0x009F, 0xFDD0 to 0xFDEF, or is one of 0x000B, 0xFFFE, 0xFFFF, 0x1FFFE, 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, 0x3FFFF, 0x4FFFE, 0x4FFFF, 0x5FFFE, 0x5FFFF, 0x6FFFE, 0x6FFFF, 0x7FFFE, 0x7FFFF, 0x8FFFE, 0x8FFFF, 0x9FFFE, 0x9FFFF, 0xAFFFE, 0xAFFFF, 0xBFFFE, 0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE, 0xDFFFF, 0xEFFFE, 0xEFFFF, 0xFFFFE, 0xFFFFF, 0x10FFFE, or 0x10FFFF, then this is a parse error.

Anything else

Consume the maximum number of characters possible, with the consumed characters matching one of the identifiers in the first column of the named character references table (in a case-sensitive manner).

If no match can be made, then this is a parse error. No characters are consumed, and nothing is returned.

If the last character matched is not a U+003B SEMICOLON character (;), there is a parse error.

If the character reference is being consumed as part of an attribute, and the last character matched is not a U+003B SEMICOLON character (;), and the next character is in the range U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9), U+0041 LATIN CAPITAL LETTER A to U+005A LATIN CAPITAL LETTER Z, or U+0061 LATIN SMALL LETTER A to U+007A LATIN SMALL LETTER Z, then, for historical reasons, all the characters that were matched after the U+0026 AMPERSAND character (&) must be unconsumed, and nothing is returned.

Otherwise, return a character token for the character corresponding to the character reference name (as given by the second column of the named character references table).

If the markup contains I'm &notit; I tell you, the character reference is parsed as "not", as in, I'm ¬it; I tell you. But if the markup was I'm &notin; I tell you, the character reference would be parsed as "notin;", resulting in I'm ∉ I tell you.

8.2.5 Tree construction

Status: Last call for comments

The input to the tree construction stage is a sequence of tokens from the tokenization stage. The tree construction stage is associated with a DOM Document object when a parser is created. The "output" of this stage consists of dynamically modifying or extending that document's DOM tree.

This specification does not define when an interactive user agent has to render the Document so that it is available to the user, or when it has to begin accepting user input.

As each token is emitted from the tokenizer, the user agent must process the token according to the rules given in the section corresponding to the current insertion mode.

When the steps below require the UA to insert a character into a node, if that node has a child immediately before where the character is to be inserted, and that child is a Text node, and that Text node was the last node that the parser inserted into the document, then the character must be appended to that Text node; otherwise, a new Text node whose data is just that character must be inserted in the appropriate place.

Here are some sample inputs to the parser and the corresponding number of text nodes that they result in, assuming a user agent that executes scripts.

Input Number of text nodes
A<script>
var script = document.getElementsByTagName('script')[0];
document.body.removeChild(script);
</script>B
Two adjacent text nodes in the document, containing "A" and "B".
A<script>
var text = document.createTextNode('B');
document.body.appendChild(text);
</script>C
Four text nodes; "A" before the script, the script's contents, "B" after the script, and then, immediately after that, "C".
A<script>
var text = document.getElementsByTagName('script')[0].firstChild;
text.data = 'B';
document.body.appendChild(text);
</script>B
Two adjacent text nodes in the document, containing "A" and "BB".
A<table>B<tr>C</tr>C</table>
Three adjacent text nodes before the table, containing "A", "B", and "CC" respectively. (This is caused by foster parenting.)
A<table><tr> B</tr> B</table>
Two adjacent text nodes before the table, containing "A" and " B B" (space-B-space-B) respectively. (This is caused by foster parenting.)
A<table><tr> B</tr> </em>C</table>
Three adjacent text nodes before the table, containing "A", " B" (space-B), and "C" respectively, and one text node inside the table (as a child of a tbody) with a single space character. (Space characters separated from non-space characters by non-character tokens are not affected by foster parenting, even if those other tokens then get ignored.)

DOM mutation events must not fire for changes caused by the UA parsing the document. (Conceptually, the parser is not mutating the DOM, it is constructing it.) This includes the parsing of any content inserted using document.write() and document.writeln() calls. [DOMEVENTS]

Not all of the tag names mentioned below are conformant tag names in this specification; many are included to handle legacy content. They still form part of the algorithm that implementations are required to implement to claim conformance.

The algorithm described below places no limit on the depth of the DOM tree generated, or on the length of tag names, attribute names, attribute values, text nodes, etc. While implementors are encouraged to avoid arbitrary limits, it is recognized that practical concerns will likely force user agents to impose nesting depth constraints.

8.2.5.1 Creating and inserting elements

Status: Last call for comments

When the steps below require the UA to create an element for a token in a particular namespace, the UA must create a node implementing the interface appropriate for the element type corresponding to the tag name of the token in the given namespace (as given in the specification that defines that element, e.g. for an a element in the HTML namespace, this specification defines it to be the HTMLAnchorElement interface), with the tag name being the name of that element, with the node being in the given namespace, and with the attributes on the node being those given in the given token.

The interface appropriate for an element in the HTML namespace that is not defined in this specification (or other applicable specifications) is HTMLUnknownElement. Element in other namespaces whose interface is not defined by that namespace's specification must use the interface Element.

When a resettable element is created in this manner, its reset algorithm must be invoked once the attributes are set. (This initializes the element's value and checkedness based on the element's attributes.)


When the steps below require the UA to insert an HTML element for a token, the UA must first create an element for the token in the HTML namespace, and then append this node to the current node, and push it onto the stack of open elements so that it is the new current node.

The steps below may also require that the UA insert an HTML element in a particular place, in which case the UA must follow the same steps except that it must insert or append the new node in the location specified instead of appending it to the current node. (This happens in particular during the parsing of tables with invalid content.)

If an element created by the insert an HTML element algorithm is a form-associated element, and the form element pointer is not null, and the newly created element doesn't have a form attribute, the user agent must associate the newly created element with the form element pointed to by the form element pointer before inserting it wherever it is to be inserted.


When the steps below require the UA to insert a foreign element for a token, the UA must first create an element for the token in the given namespace, and then append this node to the current node, and push it onto the stack of open elements so that it is the new current node. If the newly created element has an xmlns attribute in the XMLNS namespace whose value is not exactly the same as the element's namespace, that is a parse error. Similarly, if the newly created element has an xmlns:xlink attribute in the XMLNS namespace whose value is not the XLink Namespace, that is a parse error.

When the steps below require the user agent to adjust MathML attributes for a token, then, if the token has an attribute named definitionurl, change its name to definitionURL (note the case difference).

When the steps below require the user agent to adjust SVG attributes for a token, then, for each attribute on the token whose attribute name is one of the ones in the first column of the following table, change the attribute's name to the name given in the corresponding cell in the second column. (This fixes the case of SVG attributes that are not all lowercase.)

Attribute name on token Attribute name on element
attributename attributeName
attributetype attributeType
basefrequency baseFrequency
baseprofile baseProfile
calcmode calcMode
clippathunits clipPathUnits
contentscripttype contentScriptType
contentstyletype contentStyleType
diffuseconstant diffuseConstant
edgemode edgeMode
externalresourcesrequired externalResourcesRequired
filterres filterRes
filterunits filterUnits
glyphref glyphRef
gradienttransform gradientTransform
gradientunits gradientUnits
kernelmatrix kernelMatrix
kernelunitlength kernelUnitLength
keypoints keyPoints
keysplines keySplines
keytimes keyTimes
lengthadjust lengthAdjust
limitingconeangle limitingConeAngle
markerheight markerHeight
markerunits markerUnits
markerwidth markerWidth
maskcontentunits maskContentUnits
maskunits maskUnits
numoctaves numOctaves
pathlength pathLength
patterncontentunits patternContentUnits
patterntransform patternTransform
patternunits patternUnits
pointsatx pointsAtX
pointsaty pointsAtY
pointsatz pointsAtZ
preservealpha preserveAlpha
preserveaspectratio preserveAspectRatio
primitiveunits primitiveUnits
refx refX
refy refY
repeatcount repeatCount
repeatdur repeatDur
requiredextensions requiredExtensions
requiredfeatures requiredFeatures
specularconstant specularConstant
specularexponent specularExponent
spreadmethod spreadMethod
startoffset startOffset
stddeviation stdDeviation
stitchtiles stitchTiles
surfacescale surfaceScale
systemlanguage systemLanguage
tablevalues tableValues
targetx targetX
targety targetY
textlength textLength
viewbox viewBox
viewtarget viewTarget
xchannelselector xChannelSelector
ychannelselector yChannelSelector
zoomandpan zoomAndPan

When the steps below require the user agent to adjust foreign attributes for a token, then, if any of the attributes on the token match the strings given in the first column of the following table, let the attribute be a namespaced attribute, with the prefix being the string given in the corresponding cell in the second column, the local name being the string given in the corresponding cell in the third column, and the namespace being the namespace given in the corresponding cell in the fourth column. (This fixes the use of namespaced attributes, in particular lang attributes in the XML namespace.)

Attribute name Prefix Local name Namespace
xlink:actuate xlink actuate XLink namespace
xlink:arcrole xlink arcrole XLink namespace
xlink:href xlink href XLink namespace
xlink:role xlink role XLink namespace
xlink:show xlink show XLink namespace
xlink:title xlink title XLink namespace
xlink:type xlink type XLink namespace
xml:base xml base XML namespace
xml:lang xml lang XML namespace
xml:space xml space XML namespace
xmlns (none) xmlns XMLNS namespace
xmlns:xlink xmlns xlink XMLNS namespace

The generic raw text element parsing algorithm and the generic RCDATA element parsing algorithm consist of the following steps. These algorithms are always invoked in response to a start tag token.

  1. Insert an HTML element for the token.

  2. If the algorithm that was invoked is the generic raw text element parsing algorithm, switch the tokenizer to the RAWTEXT state; otherwise the algorithm invoked was the generic RCDATA element parsing algorithm, switch the tokenizer to the RCDATA state.

  3. Let the original insertion mode be the current insertion mode.

  4. Then, switch the insertion mode to "text".

8.2.5.2 Closing elements that have implied end tags

Status: Last call for comments

When the steps below require the UA to generate implied end tags, then, while the current node is a dd element, a dt element, an li element, an option element, an optgroup element, a p element, an rp element, or an rt element, the UA must pop the current node off the stack of open elements.

If a step requires the UA to generate implied end tags but lists an element to exclude from the process, then the UA must perform the above steps as if that element was not in the above list.

8.2.5.3 Foster parenting

Status: Last call for comments

Foster parenting happens when content is misnested in tables.

When a node node is to be foster parented, the node node must be inserted into the foster parent element.

The foster parent element is the parent element of the last table element in the stack of open elements, if there is a table element and it has such a parent element. If there is no table element in the stack of open elements (fragment case), then the foster parent element is the first element in the stack of open elements (the html element). Otherwise, if there is a table element in the stack of open elements, but the last table element in the stack of open elements has no parent, or its parent node is not an element, then the foster parent element is the element before the last table element in the stack of open elements.

If the foster parent element is the parent element of the last table element in the stack of open elements, then node must be inserted immediately before the last table element in the stack of open elements in the foster parent element; otherwise, node must be appended to the foster parent element.

8.2.5.4 The "initial" insertion mode

Status: Last call for comments

When the insertion mode is "initial", tokens must be handled as follows:

A character token that is one of U+0009 CHARACTER TABULATION, U+000A LINE FEED (LF), U+000C FORM FEED (FF), or U+0020 SPACE

Ignore the token.

A comment token

Append a Comment node to the Document object with the data attribute set to the data given in the comment token.

A DOCTYPE token

If the DOCTYPE token's name is not a case-sensitive match for the string "html", or the token's public identifier is not missing, or the token's system identifier is neither missing nor a case-sensitive match for the string "about:legacy-compat", and none of the sets of conditions in the following list are matched, then there is a parse error.

  • The DOCTYPE token's name is a case-sensitive match for the string "html", the token's public identifier is the case-sensitive string "-//W3C//DTD HTML 4.0//EN", and the token's system identifier is either missing or the case-sensitive string "http://www.w3.org/TR/REC-html40/strict.dtd".
  • The DOCTYPE token's name is a case-sensitive match for the string "html", the token's public identifier is the case-sensitive string "-//W3C//DTD HTML 4.01//EN", and the token's system identifier is either missing or the case-sensitive string "http://www.w3.org/TR/html4/strict.dtd".
  • The DOCTYPE token's name is a case-sensitive match for the string "html", the token's public identifier is the case-sensitive string "-//W3C//DTD XHTML 1.0 Strict//EN", and the token's system identifier is the case-sensitive string "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd".
  • The DOCTYPE token's name is a case-sensitive match for the string "html", the token's public identifier is the case-sensitive string "-//W3C//DTD XHTML 1.1//EN", and the token's system identifier is the case-sensitive string "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd".

Conformance checkers may, based on the values (including presence or lack thereof) of the DOCTYPE token's name, public identifier, or system identifier, switch to a conformance checking mode for another language (e.g. based on the DOCTYPE token a conformance checker could recognize that the document is an HTML4-era document, and defer to an HTML4 conformance checker.)

Append a DocumentType node to the Document node, with the name attribute set to the name given in the DOCTYPE token, or the empty string if the name was missing; the publicId attribute set to the public identifier given in the DOCTYPE token, or the empty string if the public identifier was missing; the systemId attribute set to the system identifier given in the DOCTYPE token, or the empty string if the system identifier was missing; and the other attributes specific to DocumentType objects set to null and empty lists as appropriate. Associate the DocumentType node with the Document object so that it is returned as the value of the doctype attribute of the Document object.

Then, if the DOCTYPE token matches one of the conditions in the following list, then set the Document to quirks mode:

  • The force-quirks flag is set to on.
  • The name is set to anything other than "html" (compared case-sensitively).
  • The public identifier starts with: "+//Silmaril//dtd html Pro v0r11 19970101//"
  • The public identifier starts with: "-//AdvaSoft Ltd//DTD HTML 3.0 asWedit + extensions//"
  • The public identifier starts with: "-//AS//DTD HTML 3.0 asWedit + extensions//"
  • The public identifier starts with: "-//IETF//DTD HTML 2.0 Level 1//"
  • The public identifier starts with: "-//IETF//DTD HTML 2.0 Level 2//"
  • The public identifier starts with: "-//IETF//DTD HTML 2.0 Strict Level 1//"
  • The public identifier starts with: "-//IETF//DTD HTML 2.0 Strict Level 2//"
  • The public identifier starts with: "-//IETF//DTD HTML 2.0 Strict//"
  • The public identifier starts with: "-//IETF//DTD HTML 2.0//"
  • The public identifier starts with: "-//IETF//DTD HTML 2.1E//"
  • The public identifier starts with: "-//IETF//DTD HTML 3.0//"
  • The public identifier starts with: "-//IETF//DTD HTML 3.2 Final//"
  • The public identifier starts with: "-//IETF//DTD HTML 3.2//"
  • The public identifier starts with: "-//IETF//DTD HTML 3//"
  • The public identifier starts with: "-//IETF//DTD HTML Level 0//"
  • The public identifier starts with: "-//IETF//DTD HTML Level 1//"
  • The public identifier starts with: "-//IETF//DTD HTML Level 2//"
  • The public identifier starts with: "-//IETF//DTD HTML Level 3//"
  • The public identifier starts with: "-//IETF//DTD HTML Strict Level 0//"
  • The public identifier starts with: "-//IETF//DTD HTML Strict Level 1//"
  • The public identifier starts with: "-//IETF//DTD HTML Strict Level 2//"
  • The public identifier starts with: "-//IETF//DTD HTML Strict Level 3//"
  • The public identifier starts with: "-//IETF//DTD HTML Strict//"
  • The public identifier starts with: "-//IETF//DTD HTML//"
  • The public identifier starts with: "-//Metrius//DTD Metrius Presentational//"
  • The public identifier starts with: "-//Microsoft//DTD Internet Explorer 2.0 HTML Strict//"
  • The public identifier starts with: "-//Microsoft//DTD Internet Explorer 2.0 HTML//"
  • The public identifier starts with: "-//Microsoft//DTD Internet Explorer 2.0 Tables//"
  • The public identifier starts with: "-//Microsoft//DTD Internet Explorer 3.0 HTML Strict//"
  • The public identifier starts with: "-//Microsoft//DTD Internet Explorer 3.0 HTML//"
  • The public identifier starts with: "-//Microsoft//DTD Internet Explorer 3.0 Tables//"
  • The public identifier starts with: "-//Netscape Comm. Corp.//DTD HTML//"
  • The public identifier starts with: "-//Netscape Comm. Corp.//DTD Strict HTML//"
  • The public identifier starts with: "-//O'Reilly and Associates//DTD HTML 2.0//"
  • The public identifier starts with: "-//O'Reilly and Associates//DTD HTML Extended 1.0//"
  • The public identifier starts with: "-//O'Reilly and Associates//DTD HTML Extended Relaxed 1.0//"
  • The public identifier starts with: "-//SoftQuad Software//DTD HoTMetaL PRO 6.0::19990601::extensions to HTML 4.0//"
  • The public identifier starts with: "-//SoftQuad//DTD HoTMetaL PRO 4.0::19971010::extensions to HTML 4.0//"
  • The public identifier starts with: "-//Spyglass//DTD HTML 2.0 Extended//"
  • The public identifier starts with: "-//SQ//DTD HTML 2.0 HoTMetaL + extensions//"
  • The public identifier starts with: "-//Sun Microsystems Corp.//DTD HotJava HTML//"
  • The public identifier starts with: "-//Sun Microsystems Corp.//DTD HotJava Strict HTML//"
  • The public identifier starts with: "-//W3C//DTD HTML 3 1995-03-24//"
  • The public identifier starts with: "-//W3C//DTD HTML 3.2 Draft//"
  • The public identifier starts with: "-//W3C//DTD HTML 3.2 Final//"
  • The public identifier starts with: "-//W3C//DTD HTML 3.2//"
  • The public identifier starts with: "-//W3C//DTD HTML 3.2S Draft//"
  • The public identifier starts with: "-//W3C//DTD HTML 4.0 Frameset//"
  • The public identifier starts with: "-//W3C//DTD HTML 4.0 Transitional//"
  • The public identifier starts with: "-//W3C//DTD HTML Experimental 19960712//"
  • The public identifier starts with: "-//W3C//DTD HTML Experimental 970421//"
  • The public identifier starts with: "-//W3C//DTD W3 HTML//"
  • The public identifier starts with: "-//W3O//DTD W3 HTML 3.0//"
  • The public identifier is set to: "-//W3O//DTD W3 HTML Strict 3.0//EN//"
  • The public identifier starts with: "-//WebTechs//DTD Mozilla HTML 2.0//"
  • The public identifier starts with: "-//WebTechs//DTD Mozilla HTML//"
  • The public identifier is set to: "-/W3C/DTD HTML 4.0 Transitional/EN"
  • The public identifier is set to: "HTML"
  • The system identifier is set to: "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd"
  • The system identifier is missing and the public identifier starts with: "-//W3C//DTD HTML 4.01 Frameset//"
  • The system identifier is missing and the public identifier starts with: "-//W3C//DTD HTML 4.01 Transitional//"

Otherwise, if the DOCTYPE token matches one of the conditions in the following list, then set the Document to limited quirks mode:

  • The public identifier starts with: "-//W3C//DTD XHTML 1.0 Frameset//"
  • The public identifier starts with: "-//W3C//DTD XHTML 1.0 Transitional//"
  • The system identifier is not missing and the public identifier starts with: "-//W3C//DTD HTML 4.01 Frameset//"
  • The system identifier is not missing and the public identifier starts with: "-//W3C//DTD HTML 4.01 Transitional//"

The system identifier and public identifier strings must be compared to the values given in the lists above in an ASCII case-insensitive manner. A system identifier whose value is the empty string is not considered missing for the purposes of the conditions above.

Then, switch the insertion mode to "before html".

Anything else

If the document is not an iframe srcdoc document, then this is a parse error; set the Document to quirks mode.

In any case, switch the insertion mode to "before html", then reprocess the current token.

8.2.5.5 The "before html" insertion mode

Status: Last call for comments

When the insertion mode is "before html", tokens must be handled as follows:

A DOCTYPE token

Parse error. Ignore the token.

A comment token

Append a Comment node to the Document object with the data attribute set to the data given in the comment token.

A character token that is one of U+0009 CHARACTER TABULATION, U+000A LINE FEED (LF), U+000C FORM FEED (FF), or U+0020 SPACE

Ignore the token.

A start tag whose tag name is "html"

Create an element for the token in the HTML namespace. Append it to the Document object. Put this element in the stack of open elements.

If the Document is being loaded as part of navigation of a browsing context, then: if the newly created element has a manifest attribute, then resolve the value of that attribute to an absolute URL, relative to the newly created element, and if that is successful, run the application cache selection algorithm with the resulting absolute URL with any <fragment> component removed; otherwise, if there is no such attribute or resolving it fails, run the application cache selection algorithm with no manifest. The algorithm must be passed the Document object.

Switch the insertion mode to "before head".

An end tag whose tag name is one of: "head", "body", "html", "br"

Act as described in the "anything else" entry below.

Any other end tag

Parse error. Ignore the token.

Anything else

Create an html element. Append it to the Document object. Put this element in the stack of open elements.

If the Document is being loaded as part of navigation of a browsing context, then: run the application cache selection algorithm with no manifest, passing it the Document object.

Switch the insertion mode to "before head", then reprocess the current token.

The root element can end up being removed from the Document object, e.g. by scripts; nothing in particular happens in such cases, content continues being appended to the nodes as described in the next section.

8.2.5.6 The "before head" insertion mode

Status: Last call for comments

When the insertion mode is "before head", tokens must be handled as follows:

A character token that is one of U+0009 CHARACTER TABULATION, U+000A LINE FEED (LF), U+000C FORM FEED (FF), or U+0020 SPACE

Ignore the token.

A comment token

Append a Comment node to the current node with the data attribute set to the data given in the comment token.

A DOCTYPE token

Parse error. Ignore the token.

A start tag whose tag name is "html"

Process the token using the rules for the "in body" insertion mode.

A start tag whose tag name is "head"

Insert an HTML element for the token.

Set the head element pointer to the newly created head element.

Switch the insertion mode to "in head".

An end tag whose tag name is one of: "head", "body", "html", "br"

Act as if a start tag token with the tag name "head" and no attributes had been seen, then reprocess the current token.

Any other end tag

Parse error. Ignore the token.

Anything else

Act as if a start tag token with the tag name "head" and no attributes had been seen, then reprocess the current token.

8.2.5.7 The "in head" insertion mode

Status: Last call for comments

When the insertion mode is "in head", tokens must be handled as follows:

A character token that is one of U+0009 CHARACTER TABULATION, U+000A LINE FEED (LF), U+000C FORM FEED (FF), or U+0020 SPACE

Insert the character into the current node.

A comment token

Append a Comment node to the current node with the data attribute set to the data given in the comment token.

A DOCTYPE token

Parse error. Ignore the token.

A start tag whose tag name is "html"

Process the token using the rules for the "in body" insertion mode.

A start tag whose tag name is one of: "base", "command", "link"

Insert an HTML element for the token. Immediately pop the current node off the stack of open elements.

Acknowledge the token's self-closing flag, if it is set.

A start tag whose tag name is "meta"

Insert an HTML element for the token. Immediately pop the current node off the stack of open elements.

Acknowledge the token's self-closing flag, if it is set.

If the element has a charset attribute, and its value is a supported encoding, and the confidence is currently tentative, then change the encoding to the encoding given by the value of the charset attribute.

Otherwise, if the element has a content attribute, and applying the algorithm for extracting an encoding from a Content-Type to its value returns a supported encoding encoding, and the confidence is currently tentative, then change the encoding to the encoding encoding.

A start tag whose tag name is "title"

Follow the generic RCDATA element parsing algorithm.

A start tag whose tag name is "noscript", if the scripting flag is enabled
A start tag whose tag name is one of: "noframes", "style"

Follow the generic raw text element parsing algorithm.

A start tag whose tag name is "noscript", if the scripting flag is disabled

Insert an HTML element for the token.

Switch the insertion mode to "in head noscript".

A start tag whose tag name is "script"

Run these steps:

  1. Create an element for the token in the HTML namespace.

  2. Mark the element as being "parser-inserted".

    This ensures that, if the script is external, any document.write() calls in the script will execute in-line, instead of blowing the document away, as would happen in most other cases. It also prevents the script from executing until the end tag is seen.

  3. If the parser was originally created for the HTML fragment parsing algorithm, then mark the script element as "already started". (fragment case)

  4. Append the new element to the current node and push it onto the stack of open elements.

  5. Switch the tokenizer to the script data state.

  6. Let the original insertion mode be the current insertion mode.

  7. Switch the insertion mode to "text".

An end tag whose tag name is "head"

Pop the current node (which will be the head element) off the stack of open elements.

Switch the insertion mode to "after head".

An end tag whose tag name is one of: "body", "html", "br"

Act as described in the "anything else" entry below.

A start tag whose tag name is "head"
Any other end tag

Parse error. Ignore the token.

Anything else

Act as if an end tag token with the tag name "head" had been seen, and reprocess the current token.

8.2.5.8 The "in head noscript" insertion mode

Status: Last call for comments

When the insertion mode is "in head noscript", tokens must be handled as follows:

A DOCTYPE token

Parse error. Ignore the token.

A start tag whose tag name is "html"

Process the token using the rules for the "in body" insertion mode.

An end tag whose tag name is "noscript"

Pop the current node (which will be a noscript element) from the stack of open elements; the new current node will be a head element.

Switch the insertion mode to "in head".

A character token that is one of U+0009 CHARACTER TABULATION, U+000A LINE FEED (LF), U+000C FORM FEED (FF), or U+0020 SPACE
A comment token
A start tag whose tag name is one of: "link", "meta", "noframes", "style"

Process the token using the rules for the "in head" insertion mode.

An end tag whose tag name is "br"

Act as described in the "anything else" entry below.

A start tag whose tag name is one of: "head", "noscript"
Any other end tag

Parse error. Ignore the token.

Anything else

Parse error. Act as if an end tag with the tag name "noscript" had been seen and reprocess the current token.

8.2.5.9 The "after head" insertion mode

Status: Last call for comments

When the insertion mode is "after head", tokens must be handled as follows:

A character token that is one of U+0009 CHARACTER TABULATION, U+000A LINE FEED (LF), U+000C FORM FEED (FF), or U+0020 SPACE

Insert the character into the current node.

A comment token

Append a Comment node to the current node with the data attribute set to the data given in the comment token.

A DOCTYPE token

Parse error. Ignore the token.

A start tag whose tag name is "html"

Process the token using the rules for the "in body" insertion mode.

A start tag whose tag name is "body"

Insert an HTML element for the token.

Set the frameset-ok flag to "not ok".

Switch the insertion mode to "in body".

A start tag whose tag name is "frameset"

Insert an HTML element for the token.

Switch the insertion mode to "in frameset".

A start tag token whose tag name is one of: "base", "link", "meta", "noframes", "script", "style", "title"

Parse error.

Push the node pointed to by the head element pointer onto the stack of open elements.

Process the token using the rules for the "in head" insertion mode.

Remove the node pointed to by the head element pointer from the stack of open elements.

The head element pointer cannot be null at this point.

An end tag whose tag name is one of: "body", "html", "br"

Act as described in the "anything else" entry below.

A start tag whose tag name is "head"
Any other end tag

Parse error. Ignore the token.

Anything else

Act as if a start tag token with the tag name "body" and no attributes had been seen, then set the frameset-ok flag back to "ok", and then reprocess the current token.

8.2.5.10 The "in body" insertion mode

Status: Last call for comments

When the insertion mode is "in body", tokens must be handled as follows:

A character token

Reconstruct the active formatting elements, if any.

Insert the token's character into the current node.

If the token is not one of U+0009 CHARACTER TABULATION, U+000A LINE FEED (LF), U+000C FORM FEED (FF), or U+0020 SPACE, then set the frameset-ok flag to "not ok".

A comment token

Append a Comment node to the current node with the data attribute set to the data given in the comment token.

A DOCTYPE token

Parse error. Ignore the token.

A start tag whose tag name is "html"

Parse error. For each attribute on the token, check to see if the attribute is already present on the top element of the stack of open elements. If it is not, add the attribute and its corresponding value to that element.

A start tag token whose tag name is one of: "base", "command", "link", "meta", "noframes", "script", "style", "title"

Process the token using the rules for the "in head" insertion mode.

A start tag whose tag name is "body"

Parse error.

If the second element on the stack of open elements is not a body element, or, if the stack of open elements has only one node on it, then ignore the token. (fragment case)

Otherwise, for each attribute on the token, check to see if the attribute is already present on the body element (the second element) on the stack of open elements. If it is not, add the attribute and its corresponding value to that element.

A start tag whose tag name is "frameset"

Parse error.

If the second element on the stack of open elements is not a body element, or, if the stack of open elements has only one node on it, then ignore the token. (fragment case)

If the frameset-ok flag is set to "not ok", ignore the token.

Otherwise, run the following steps:

  1. Remove the second element on the stack of open elements from its parent node, if it has one.

  2. Pop all the nodes from the bottom of the stack of open elements, from the current node up to, but not including, the root html element.

  3. Insert an HTML element for the token.

  4. Switch the insertion mode to "in frameset".

An end-of-file token

If there is a node in the stack of open elements that is not either a dd element, a dt element, an li element, a p element, a tbody element, a td element, a tfoot element, a th element, a thead element, a tr element, the body element, or the html element, then this is a parse error.

Stop parsing.

An end tag whose tag name is "body"

If the stack of open elements does not have a body element in scope, this is a parse error; ignore the token.

Otherwise, if there is a node in the stack of open elements that is not either a dd element, a dt element, an li element, an optgroup element, an option element, a p element, an rp element, an rt element, a tbody element, a td element, a tfoot element, a th element, a thead element, a tr element, the body element, or the html element, then this is a parse error.

Switch the insertion mode to "after body".

An end tag whose tag name is "html"

Act as if an end tag with tag name "body" had been seen, then, if that token wasn't ignored, reprocess the current token.

A start tag whose tag name is one of: "address", "article", "aside", "blockquote", "center", "details", "dir", "div", "dl", "fieldset", "figure", "footer", "header", "hgroup", "menu", "nav", "ol", "p", "section", "ul"

If the stack of open elements has a p element in scope, then act as if an end tag with the tag name "p" had been seen.

Insert an HTML element for the token.

A start tag whose tag name is one of: "h1", "h2", "h3", "h4", "h5", "h6"

If the stack of open elements has a p element in scope, then act as if an end tag with the tag name "p" had been seen.

If the current node is an element whose tag name is one of "h1", "h2", "h3", "h4", "h5", or "h6", then this is a parse error; pop the current node off the stack of open elements.

Insert an HTML element for the token.

A start tag whose tag name is one of: "pre", "listing"

If the stack of open elements has a p element in scope, then act as if an end tag with the tag name "p" had been seen.

Insert an HTML element for the token.

If the next token is a U+000A LINE FEED (LF) character token, then ignore that token and move on to the next one. (Newlines at the start of pre blocks are ignored as an authoring convenience.)

Set the frameset-ok flag to "not ok".

A start tag whose tag name is "form"

If the form element pointer is not null, then this is a parse error; ignore the token.

Otherwise:

If the stack of open elements has a p element in scope, then act as if an end tag with the tag name "p" had been seen.

Insert an HTML element for the token, and set the form element pointer to point to the element created.

A start tag whose tag name is "li"

Run these steps:

  1. Set the frameset-ok flag to "not ok".

  2. Initialize node to be the current node (the bottommost node of the stack).

  3. Loop: If node is an li element, then act as if an end tag with the tag name "li" had been seen, then jump to the last step.

  4. If node is not in the formatting category, and is not in the phrasing category, and is not an address, div, or p element, then jump to the last step.

  5. Otherwise, set node to the previous entry in the stack of open elements and return to the step labeled loop.

  6. This is the last step.

    If the stack of open elements has a p element in scope, then act as if an end tag with the tag name "p" had been seen.

    Finally, insert an HTML element for the token.

A start tag whose tag name is one of: "dd", "dt"

Run these steps:

  1. Set the frameset-ok flag to "not ok".

  2. Initialize node to be the current node (the bottommost node of the stack).

  3. Loop: If node is a dd or dt element, then act as if an end tag with the same tag name as node had been seen, then jump to the last step.

  4. If node is not in the formatting category, and is not in the phrasing category, and is not an address, div, or p element, then jump to the last step.

  5. Otherwise, set node to the previous entry in the stack of open elements and return to the step labeled loop.

  6. This is the last step.

    If the stack of open elements has a p element in scope, then act as if an end tag with the tag name "p" had been seen.

    Finally, insert an HTML element for the token.

A start tag whose tag name is "plaintext"

If the stack of open elements has a p element in scope, then act as if an end tag with the tag name "p" had been seen.

Insert an HTML element for the token.

Switch the tokenizer to the PLAINTEXT state.

Once a start tag with the tag name "plaintext" has been seen, that will be the last token ever seen other than character tokens (and the end-of-file token), because there is no way to switch out of the PLAINTEXT state.

An end tag whose tag name is one of: "address", "article", "aside", "blockquote", "center", "details", "dir", "div", "dl", "fieldset", "figure", "footer", "header", "hgroup", "listing", "menu", "nav", "ol", "pre", "section", "ul"

If the stack of open elements does not have an element in scope with the same tag name as that of the token, then this is a parse error; ignore the token.

Otherwise, run these steps:

  1. Generate implied end tags.

  2. If the current node is not an element with the same tag name as that of the token, then this is a parse error.

  3. Pop elements from the stack of open elements until an element with the same tag name as the token has been popped from the stack.

An end tag whose tag name is "form"

Let node be the element that the form element pointer is set to.

Set the form element pointer to null.

If node is null or the stack of open elements does not have node in scope, then this is a parse error; ignore the token.

Otherwise, run these steps:

  1. Generate implied end tags.

  2. If the current node is not node, then this is a parse error.

  3. Remove node from the stack of open elements.

An end tag whose tag name is "p"

If the stack of open elements does not have an element in scope with the same tag name as that of the token, then this is a parse error; act as if a start tag with the tag name "p" had been seen, then reprocess the current token.

Otherwise, run these steps:

  1. Generate implied end tags, except for elements with the same tag name as the token.

  2. If the current node is not an element with the same tag name as that of the token, then this is a parse error.

  3. Pop elements from the stack of open elements until an element with the same tag name as the token has been popped from the stack.

An end tag whose tag name is "li"

If the stack of open elements does not have an element in list item scope with the same tag name as that of the token, then this is a parse error; ignore the token.

Otherwise, run these steps:

  1. Generate implied end tags, except for elements with the same tag name as the token.

  2. If the current node is not an element with the same tag name as that of the token, then this is a parse error.

  3. Pop elements from the stack of open elements until an element with the same tag name as the token has been popped from the stack.

An end tag whose tag name is one of: "dd", "dt"

If the stack of open elements does not have an element in scope with the same tag name as that of the token, then this is a parse error; ignore the token.

Otherwise, run these steps:

  1. Generate implied end tags, except for elements with the same tag name as the token.

  2. If the current node is not an element with the same tag name as that of the token, then this is a parse error.

  3. Pop elements from the stack of open elements until an element with the same tag name as the token has been popped from the stack.

An end tag whose tag name is one of: "h1", "h2", "h3", "h4", "h5", "h6"

If the stack of open elements does not have an element in scope whose tag name is one of "h1", "h2", "h3", "h4", "h5", or "h6", then this is a parse error; ignore the token.

Otherwise, run these steps:

  1. Generate implied end tags.

  2. If the current node is not an element with the same tag name as that of the token, then this is a parse error.

  3. Pop elements from the stack of open elements until an element whose tag name is one of "h1", "h2", "h3", "h4", "h5", or "h6" has been popped from the stack.

An end tag whose tag name is "sarcasm"

Take a deep breath, then act as described in the "any other end tag" entry below.

A start tag whose tag name is "a"

If the list of active formatting elements contains an element whose tag name is "a" between the end of the list and the last marker on the list (or the start of the list if there is no marker on the list), then this is a parse error; act as if an end tag with the tag name "a" had been seen, then remove that element from the list of active formatting elements and the stack of open elements if the end tag didn't already remove it (it might not have if the element is not in table scope).

In the non-conforming stream <a href="a">a<table><a href="b">b</table>x, the first a element would be closed upon seeing the second one, and the "x" character would be inside a link to "b", not to "a". This is despite the fact that the outer a element is not in table scope (meaning that a regular </a> end tag at the start of the table wouldn't close the outer a element).

Reconstruct the active formatting elements, if any.

Insert an HTML element for the token. Add that element to the list of active formatting elements.

A start tag whose tag name is one of: "b", "big", "code", "em", "font", "i", "s", "small", "strike", "strong", "tt", "u"

Reconstruct the active formatting elements, if any.

Insert an HTML element for the token. Add that element to the list of active formatting elements.

A start tag whose tag name is "nobr"

Reconstruct the active formatting elements, if any.

If the stack of open elements has a nobr element in scope, then this is a parse error; act as if an end tag with the tag name "nobr" had been seen, then once again reconstruct the active formatting elements, if any.

Insert an HTML element for the token. Add that element to the list of active formatting elements.

An end tag whose tag name is one of: "a", "b", "big", "code", "em", "font", "i", "nobr", "s", "small", "strike", "strong", "tt", "u"

Run these steps:

  1. Let the formatting element be the last element in the list of active formatting elements that:

    • is between the end of the list and the last scope marker in the list, if any, or the start of the list otherwise, and
    • has the same tag name as the token.

    If there is no such node, or, if that node is also in the stack of open elements but the element is not in scope, then this is a parse error; ignore the token, and abort these steps.

    Otherwise, if there is such a node, but that node is not in the stack of open elements, then this is a parse error; remove the element from the list, and abort these steps.

    Otherwise, there is a formatting element and that element is in the stack and is in scope. If the element is not the current node, this is a parse error. In any case, proceed with the algorithm as written in the following steps.

  2. Let the furthest block be the topmost node in the stack of open elements that is lower in the stack than the formatting element, and is not an element in the phrasing or formatting categories. There might not be one.

  3. If there is no furthest block, then the UA must skip the subsequent steps and instead just pop all the nodes from the bottom of the stack of open elements, from the current node up to and including the formatting element, and remove the formatting element from the list of active formatting elements.

  4. Let the common ancestor be the element immediately above the formatting element in the stack of open elements.

  5. Let a bookmark note the position of the formatting element in the list of active formatting elements relative to the elements on either side of it in the list.

  6. Let node and last node be the furthest block. Follow these steps:

    1. Let node be the element immediately above node in the stack of open elements, or if node is no longer in the stack of open elements (e.g. because it got removed by the next step), the element that was immediately above node in the stack of open elements before node was removed.
    2. If node is not in the list of active formatting elements, then remove node from the stack of open elements and then go back to step 1.
    3. Otherwise, if node is the formatting element, then go to the next step in the overall algorithm.
    4. Otherwise, if last node is the furthest block, then move the aforementioned bookmark to be immediately after the node in the list of active formatting elements.
    5. Create an element for the token for which the element node was created, replace the entry for node in the list of active formatting elements with an entry for the new element, replace the entry for node in the stack of open elements with an entry for the new element, and let node be the new element.
    6. Insert last node into node, first removing it from its previous parent node if any.
    7. Let last node be node.
    8. Return to step 1 of this inner set of steps.
  7. If the common ancestor node is a table, tbody, tfoot, thead, or tr element, then, foster parent whatever last node ended up being in the previous step, first removing it from its previous parent node if any.

    Otherwise, append whatever last node ended up being in the previous step to the common ancestor node, first removing it from its previous parent node if any.

  8. Create an element for the token for which the formatting element was created.

  9. Take all of the child nodes of the furthest block and append them to the element created in the last step.

  10. Append that new element to the furthest block.

  11. Remove the formatting element from the list of active formatting elements, and insert the new element into the list of active formatting elements at the position of the aforementioned bookmark.

  12. Remove the formatting element from the stack of open elements, and insert the new element into the stack of open elements immediately below the position of the furthest block in that stack.

  13. Jump back to step 1 in this series of steps.

Because of the way this algorithm causes elements to change parents, it has been dubbed the "adoption agency algorithm" (in contrast with other possible algorithms for dealing with misnested content, which included the "incest algorithm", the "secret affair algorithm", and the "Heisenberg algorithm").

A start tag whose tag name is "button"

If the stack of open elements has a button element in scope, then this is a parse error; act as if an end tag with the tag name "button" had been seen, then reprocess the token.

Otherwise:

Reconstruct the active formatting elements, if any.

Insert an HTML element for the token.

Insert a marker at the end of the list of active formatting elements.

Set the frameset-ok flag to "not ok".

A start tag token whose tag name is one of: "applet", "marquee", "object"

Reconstruct the active formatting elements, if any.

Insert an HTML element for the token.

Insert a marker at the end of the list of active formatting elements.

Set the frameset-ok flag to "not ok".

An end tag token whose tag name is one of: "applet", "button", "marquee", "object"

If the stack of open elements does not have an element in scope with the same tag name as that of the token, then this is a parse error; ignore the token.

Otherwise, run these steps:

  1. Generate implied end tags.

  2. If the current node is not an element with the same tag name as that of the token, then this is a parse error.

  3. Pop elements from the stack of open elements until an element with the same tag name as the token has been popped from the stack.

  4. Clear the list of active formatting elements up to the last marker.
A start tag whose tag name is "table"

If the Document is not set to quirks mode, and the stack of open elements has a p element in scope, then act as if an end tag with the tag name "p" had been seen.

Insert an HTML element for the token.

Set the frameset-ok flag to "not ok".

Switch the insertion mode to "in table".

A start tag whose tag name is one of: "area", "basefont", "bgsound", "br", "embed", "img", "input", "keygen", "wbr"

Reconstruct the active formatting elements, if any.

Insert an HTML element for the token. Immediately pop the current node off the stack of open elements.

Acknowledge the token's self-closing flag, if it is set.

Set the frameset-ok flag to "not ok".

A start tag whose tag name is one of: "param", "source"

Insert an HTML element for the token. Immediately pop the current node off the stack of open elements.

Acknowledge the token's self-closing flag, if it is set.

A start tag whose tag name is "hr"

If the stack of open elements has a p element in scope, then act as if an end tag with the tag name "p" had been seen.

Insert an HTML element for the token. Immediately pop the current node off the stack of open elements.

Acknowledge the token's self-closing flag, if it is set.

Set the frameset-ok flag to "not ok".

A start tag whose tag name is "image"

Parse error. Change the token's tag name to "img" and reprocess it. (Don't ask.)

A start tag whose tag name is "isindex"

Parse error.

If the form element pointer is not null, then ignore the token.

Otherwise:

Acknowledge the token's self-closing flag, if it is set.

Act as if a start tag token with the tag name "form" had been seen.

If the token has an attribute called "action", set the action attribute on the resulting form element to the value of the "action" attribute of the token.

Act as if a start tag token with the tag name "hr" had been seen.

Act as if a start tag token with the tag name "label" had been seen.

Act as if a stream of character tokens had been seen (see below for what they should say).

Act as if a start tag token with the tag name "input" had been seen, with all the attributes from the "isindex" token except "name", "action", and "prompt". Set the name attribute of the resulting input element to the value "isindex".

Act as if a stream of character tokens had been seen (see below for what they should say).

Act as if an end tag token with the tag name "label" had been seen.

Act as if a start tag token with the tag name "hr" had been seen.

Act as if an end tag token with the tag name "form" had been seen.

If the token has an attribute with the name "prompt", then the first stream of characters must be the same string as given in that attribute, and the second stream of characters must be empty. Otherwise, the two streams of character tokens together should, together with the input element, express the equivalent of "This is a searchable index. Insert your search keywords here: (input field)" in the user's preferred language.

A start tag whose tag name is "textarea"

Run these steps:

  1. Insert an HTML element for the token.

  2. If the next token is a U+000A LINE FEED (LF) character token, then ignore that token and move on to the next one. (Newlines at the start of textarea elements are ignored as an authoring convenience.)

  3. Switch the tokenizer to the RCDATA state.

  4. Let the original insertion mode be the current insertion mode.

  5. Set the frameset-ok flag to "not ok".

  6. Switch the insertion mode to "text".

A start tag whose tag name is "xmp"

If the stack of open elements has a p element in scope, then act as if an end tag with the tag name "p" had been seen.

Reconstruct the active formatting elements, if any.

Set the frameset-ok flag to "not ok".

Follow the generic raw text element parsing algorithm.

A start tag whose tag name is "iframe"

Set the frameset-ok flag to "not ok".

Follow the generic raw text element parsing algorithm.

A start tag whose tag name is "noembed"
A start tag whose tag name is "noscript", if the scripting flag is enabled

Follow the generic raw text element parsing algorithm.

A start tag whose tag name is "select"

Reconstruct the active formatting elements, if any.

Insert an HTML element for the token.

Set the frameset-ok flag to "not ok".

If the insertion mode is one of in table", "in caption", "in column group", "in table body", "in row", or "in cell", then switch the insertion mode to "in select in table". Otherwise, switch the insertion mode to "in select".

A start tag whose tag name is one of: "optgroup", "option"

If the stack of open elements has an option element in scope, then act as if an end tag with the tag name "option" had been seen.

Reconstruct the active formatting elements, if any.

Insert an HTML element for the token.

A start tag whose tag name is one of: "rp", "rt"

If the stack of open elements has a ruby element in scope, then generate implied end tags. If the current node is not then a ruby element, this is a parse error; pop all the nodes from the current node up to the node immediately before the bottommost ruby element on the stack of open elements.

Insert an HTML element for the token.

An end tag whose tag name is "br"

Parse error. Act as if a start tag token with the tag name "br" had been seen. Ignore the end tag token.

A start tag whose tag name is "math"

Reconstruct the active formatting elements, if any.

Adjust MathML attributes for the token. (This fixes the case of MathML attributes that are not all lowercase.)

Adjust foreign attributes for the token. (This fixes the use of namespaced attributes, in particular XLink.)

Insert a foreign element for the token, in the MathML namespace.

If the token has its self-closing flag set, pop the current node off the stack of open elements and acknowledge the token's self-closing flag.

Otherwise, if the insertion mode is not already "in foreign content", let the secondary insertion mode be the current insertion mode, and then switch the insertion mode to "in foreign content".

A start tag whose tag name is "svg"

Reconstruct the active formatting elements, if any.

Adjust SVG attributes for the token. (This fixes the case of SVG attributes that are not all lowercase.)

Adjust foreign attributes for the token. (This fixes the use of namespaced attributes, in particular XLink in SVG.)

Insert a foreign element for the token, in the SVG namespace.

If the token has its self-closing flag set, pop the current node off the stack of open elements and acknowledge the token's self-closing flag.

Otherwise, if the insertion mode is not already "in foreign content", let the secondary insertion mode be the current insertion mode, and then switch the insertion mode to "in foreign content".

A start tag whose tag name is one of: "caption", "col", "colgroup", "frame", "head", "tbody", "td", "tfoot", "th", "thead", "tr"

Parse error. Ignore the token.

Any other start tag

Reconstruct the active formatting elements, if any.

Insert an HTML element for the token.

This element will be a phrasing element.

Any other end tag

Run these steps:

  1. Initialize node to be the current node (the bottommost node of the stack).

  2. If node has the same tag name as the token, then:

    1. Generate implied end tags.

    2. If the tag name of the end tag token does not match the tag name of the current node, this is a parse error.

    3. Pop all the nodes from the current node up to node, including node, then stop these steps.

  3. Otherwise, if node is in neither the formatting category nor the phrasing category, then this is a parse error; ignore the token, and abort these steps.

  4. Set node to the previous entry in the stack of open elements.

  5. Return to step 2.

8.2.5.11 The "text" insertion mode

Status: Last call for comments

When the insertion mode is "text", tokens must be handled as follows:

A character token

Insert the token's character into the current node.

An end-of-file token

Parse error.

If the current node is a script element, mark the script element as "already started".

Pop the current node off the stack of open elements.

Switch the insertion mode to the original insertion mode and reprocess the current token.

An end tag whose tag name is "script"

Let script be the current node (which will be a script element).

Pop the current node off the stack of open elements.

Switch the insertion mode to the original insertion mode.

Let the old insertion point have the same value as the current insertion point. Let the insertion point be just before the next input character.

Increment the parser's script nesting level by one.

Run the script. This might cause some script to execute, which might cause new characters to be inserted into the tokenizer, and might cause the tokenizer to output more tokens, resulting in a reentrant invocation of the parser.

Decrement the parser's script nesting level by one. If the parser's script nesting level is zero, then set the parser pause flag to false.

Let the insertion point have the value of the old insertion point. (In other words, restore the insertion point to its previous value. This value might be the "undefined" value.)

At this stage, if there is a pending parsing-blocking script, then:

If the script nesting level is not zero:

Set the parser pause flag to true, and abort the processing of any nested invocations of the tokenizer, yielding control back to the caller. (Tokenization will resume when the caller returns to the "outer" tree construction stage.)

The tree construction stage of this particular parser is being called reentrantly, say from a call to document.write().

Otherwise:

Run these steps:

  1. Let the script be the pending parsing-blocking script. There is no longer a pending parsing-blocking script.

  2. Block the tokenizer for this instance of the HTML parser, such that the event loop will not run tasks that invoke the tokenizer.

  3. Spin the event loop until there is no style sheet blocking scripts and the script's "ready to be parser-executed" flag is set.

  4. Unblock the tokenizer for this instance of the HTML parser, such that tasks that invoke the tokenizer can again be run.

  5. Let the insertion point be just before the next input character.

  6. Increment the parser's script nesting level by one (it should be zero before this step, so this sets it to one).

  7. Execute the script.

  8. Decrement the parser's script nesting level by one. If the parser's script nesting level is zero (which it always should be at this point), then set the parser pause flag to false.

  9. Let the insertion point be undefined again.

  10. If there is once again a pending parsing-blocking script, then repeat these steps from step 1.

Any other end tag

Pop the current node off the stack of open elements.

Switch the insertion mode to the original insertion mode.

8.2.5.12 The "in table" insertion mode

Status: Last call for comments

When the insertion mode is "in table", tokens must be handled as follows:

A character token

Let the pending table character tokens be an empty list of tokens.

Let the original insertion mode be the current insertion mode.

Switch the insertion mode to "in table text" and reprocess the token.

A comment token

Append a Comment node to the current node with the data attribute set to the data given in the comment token.

A DOCTYPE token

Parse error. Ignore the token.

A start tag whose tag name is "caption"

Clear the stack back to a table context. (See below.)

Insert a marker at the end of the list of active formatting elements.

Insert an HTML element for the token, then switch the insertion mode to "in caption".

A start tag whose tag name is "colgroup"

Clear the stack back to a table context. (See below.)

Insert an HTML element for the token, then switch the insertion mode to "in column group".

A start tag whose tag name is "col"

Act as if a start tag token with the tag name "colgroup" had been seen, then reprocess the current token.

A start tag whose tag name is one of: "tbody", "tfoot", "thead"

Clear the stack back to a table context. (See below.)

Insert an HTML element for the token, then switch the insertion mode to "in table body".

A start tag whose tag name is one of: "td", "th", "tr"

Act as if a start tag token with the tag name "tbody" had been seen, then reprocess the current token.

A start tag whose tag name is "table"

Parse error. Act as if an end tag token with the tag name "table" had been seen, then, if that token wasn't ignored, reprocess the current token.

The fake end tag token here can only be ignored in the fragment case.

An end tag whose tag name is "table"

If the stack of open elements does not have an element in table scope with the same tag name as the token, this is a parse error. Ignore the token. (fragment case)

Otherwise:

Pop elements from this stack until a table element has been popped from the stack.

Reset the insertion mode appropriately.

An end tag whose tag name is one of: "body", "caption", "col", "colgroup", "html", "tbody", "td", "tfoot", "th", "thead", "tr"

Parse error. Ignore the token.

A start tag whose tag name is one of: "style", "script"

Process the token using the rules for the "in head" insertion mode.

A start tag whose tag name is "input"

If the token does not have an attribute with the name "type", or if it does, but that attribute's value is not an ASCII case-insensitive match for the string "hidden", then: act as described in the "anything else" entry below.

Otherwise:

Parse error.

Insert an HTML element for the token.

Pop that input element off the stack of open elements.

A start tag whose tag name is "form"

Parse error.

If the form element pointer is not null, ignore the token.

Otherwise:

Insert an HTML element for the token.

Pop that form element off the stack of open elements.

An end-of-file token

If the current node is not the root html element, then this is a parse error.

It can only be the current node in the fragment case.

Stop parsing.

Anything else

Parse error. Process the token using the rules for the "in body" insertion mode, except that if the current node is a table, tbody, tfoot, thead, or tr element, then, whenever a node would be inserted into the current node, it must instead be foster parented.

When the steps above require the UA to clear the stack back to a table context, it means that the UA must, while the current node is not a table element or an html element, pop elements from the stack of open elements.

The current node being an html element after this process is a fragment case.

8.2.5.13 The "in table text" insertion mode

Status: Last call for comments

When the insertion mode is "in table text", tokens must be handled as follows:

A character token

Append the character token to the pending table character tokens list.

Anything else

If any of the tokens in the pending table character tokens list are character tokens that are not one of U+0009 CHARACTER TABULATION, U+000A LINE FEED (LF), U+000C FORM FEED (FF), or U+0020 SPACE, then reprocess those character tokens using the rules given in the "anything else" entry in the in table" insertion mode.

Otherwise, insert the characters given by the pending table character tokens list into the current node.

Switch the insertion mode to the original insertion mode and reprocess the token.

8.2.5.14 The "in caption" insertion mode

Status: Last call for comments

When the insertion mode is "in caption", tokens must be handled as follows:

An end tag whose tag name is "caption"

If the stack of open elements does not have an element in table scope with the same tag name as the token, this is a parse error. Ignore the token. (fragment case)

Otherwise:

Generate implied end tags.

Now, if the current node is not a caption element, then this is a parse error.

Pop elements from this stack until a caption element has been popped from the stack.

Clear the list of active formatting elements up to the last marker.

Switch the insertion mode to "in table".

A start tag whose tag name is one of: "caption", "col", "colgroup", "tbody", "td", "tfoot", "th", "thead", "tr"
An end tag whose tag name is "table"

Parse error. Act as if an end tag with the tag name "caption" had been seen, then, if that token wasn't ignored, reprocess the current token.

The fake end tag token here can only be ignored in the fragment case.

An end tag whose tag name is one of: "body", "col", "colgroup", "html", "tbody", "td", "tfoot", "th", "thead", "tr"

Parse error. Ignore the token.

Anything else

Process the token using the rules for the "in body" insertion mode.

8.2.5.15 The "in column group" insertion mode

Status: Last call for comments

When the insertion mode is "in column group", tokens must be handled as follows:

A character token that is one of U+0009 CHARACTER TABULATION, U+000A LINE FEED (LF), U+000C FORM FEED (FF), or U+0020 SPACE

Insert the character into the current node.

A comment token

Append a Comment node to the current node with the data attribute set to the data given in the comment token.

A DOCTYPE token

Parse error. Ignore the token.

A start tag whose tag name is "html"

Process the token using the rules for the "in body" insertion mode.

A start tag whose tag name is "col"

Insert an HTML element for the token. Immediately pop the current node off the stack of open elements.

Acknowledge the token's self-closing flag, if it is set.

An end tag whose tag name is "colgroup"

If the current node is the root html element, then this is a parse error; ignore the token. (fragment case)

Otherwise, pop the current node (which will be a colgroup element) from the stack of open elements. Switch the insertion mode to "in table".

An end tag whose tag name is "col"

Parse error. Ignore the token.

An end-of-file token

If the current node is the root html element, then stop parsing. (fragment case)

Otherwise, act as described in the "anything else" entry below.

Anything else

Act as if an end tag with the tag name "colgroup" had been seen, and then, if that token wasn't ignored, reprocess the current token.

The fake end tag token here can only be ignored in the fragment case.

8.2.5.16 The "in table body" insertion mode

Status: Last call for comments

When the insertion mode is "in table body", tokens must be handled as follows:

A start tag whose tag name is "tr"

Clear the stack back to a table body context. (See below.)

Insert an HTML element for the token, then switch the insertion mode to "in row".

A start tag whose tag name is one of: "th", "td"

Parse error. Act as if a start tag with the tag name "tr" had been seen, then reprocess the current token.

An end tag whose tag name is one of: "tbody", "tfoot", "thead"

If the stack of open elements does not have an element in table scope with the same tag name as the token, this is a parse error. Ignore the token.

Otherwise:

Clear the stack back to a table body context. (See below.)

Pop the current node from the stack of open elements. Switch the insertion mode to "in table".

A start tag whose tag name is one of: "caption", "col", "colgroup", "tbody", "tfoot", "thead"
An end tag whose tag name is "table"

If the stack of open elements does not have a tbody, thead, or tfoot element in table scope, this is a parse error. Ignore the token. (fragment case)

Otherwise:

Clear the stack back to a table body context. (See below.)

Act as if an end tag with the same tag name as the current node ("tbody", "tfoot", or "thead") had been seen, then reprocess the current token.

An end tag whose tag name is one of: "body", "caption", "col", "colgroup", "html", "td", "th", "tr"

Parse error. Ignore the token.

Anything else

Process the token using the rules for the "in table" insertion mode.

When the steps above require the UA to clear the stack back to a table body context, it means that the UA must, while the current node is not a tbody, tfoot, thead, or html element, pop elements from the stack of open elements.

The current node being an html element after this process is a fragment case.

8.2.5.17 The "in row" insertion mode

Status: Last call for comments

When the insertion mode is "in row", tokens must be handled as follows:

A start tag whose tag name is one of: "th", "td"

Clear the stack back to a table row context. (See below.)

Insert an HTML element for the token, then switch the insertion mode to "in cell".

Insert a marker at the end of the list of active formatting elements.

An end tag whose tag name is "tr"

If the stack of open elements does not have an element in table scope with the same tag name as the token, this is a parse error. Ignore the token. (fragment case)

Otherwise:

Clear the stack back to a table row context. (See below.)

Pop the current node (which will be a tr element) from the stack of open elements. Switch the insertion mode to "in table body".

A start tag whose tag name is one of: "caption", "col", "colgroup", "tbody", "tfoot", "thead", "tr"
An end tag whose tag name is "table"

Act as if an end tag with the tag name "tr" had been seen, then, if that token wasn't ignored, reprocess the current token.

The fake end tag token here can only be ignored in the fragment case.

An end tag whose tag name is one of: "tbody", "tfoot", "thead"

If the stack of open elements does not have an element in table scope with the same tag name as the token, this is a parse error. Ignore the token.

Otherwise, act as if an end tag with the tag name "tr" had been seen, then reprocess the current token.

An end tag whose tag name is one of: "body", "caption", "col", "colgroup", "html", "td", "th"

Parse error. Ignore the token.

Anything else

Process the token using the rules for the "in table" insertion mode.

When the steps above require the UA to clear the stack back to a table row context, it means that the UA must, while the current node is not a tr element or an html element, pop elements from the stack of open elements.

The current node being an html element after this process is a fragment case.

8.2.5.18 The "in cell" insertion mode

Status: Last call for comments

When the insertion mode is "in cell", tokens must be handled as follows:

An end tag whose tag name is one of: "td", "th"

If the stack of open elements does not have an element in table scope with the same tag name as that of the token, then this is a parse error and the token must be ignored.

Otherwise:

Generate implied end tags.

Now, if the current node is not an element with the same tag name as the token, then this is a parse error.

Pop elements from the stack of open elements stack until an element with the same tag name as the token has been popped from the stack.

Clear the list of active formatting elements up to the last marker.

Switch the insertion mode to "in row". (The current node will be a tr element at this point.)

A start tag whose tag name is one of: "caption", "col", "colgroup", "tbody", "td", "tfoot", "th", "thead", "tr"

If the stack of open elements does not have a td or th element in table scope, then this is a parse error; ignore the token. (fragment case)

Otherwise, close the cell (see below) and reprocess the current token.

An end tag whose tag name is one of: "body", "caption", "col", "colgroup", "html"

Parse error. Ignore the token.

An end tag whose tag name is one of: "table", "tbody", "tfoot", "thead", "tr"

If the stack of open elements does not have an element in table scope with the same tag name as that of the token (which can only happen for "tbody", "tfoot" and "thead", or, in the fragment case), then this is a parse error and the token must be ignored.

Otherwise, close the cell (see below) and reprocess the current token.

Anything else

Process the token using the rules for the "in body" insertion mode.

Where the steps above say to close the cell, they mean to run the following algorithm:

  1. If the stack of open elements has a td element in table scope, then act as if an end tag token with the tag name "td" had been seen.

  2. Otherwise, the stack of open elements will have a th element in table scope; act as if an end tag token with the tag name "th" had been seen.

The stack of open elements cannot have both a td and a th element in table scope at the same time, nor can it have neither when the insertion mode is "in cell".

8.2.5.19 The "in select" insertion mode

Status: Last call for comments

When the insertion mode is "in select", tokens must be handled as follows:

A character token

Insert the token's character into the current node.

A comment token

Append a Comment node to the current node with the data attribute set to the data given in the comment token.

A DOCTYPE token

Parse error. Ignore the token.

A start tag whose tag name is "html"

Process the token using the rules for the "in body" insertion mode.

A start tag whose tag name is "option"

If the current node is an option element, act as if an end tag with the tag name "option" had been seen.

Insert an HTML element for the token.

A start tag whose tag name is "optgroup"

If the current node is an option element, act as if an end tag with the tag name "option" had been seen.

If the current node is an optgroup element, act as if an end tag with the tag name "optgroup" had been seen.

Insert an HTML element for the token.

An end tag whose tag name is "optgroup"

First, if the current node is an option element, and the node immediately before it in the stack of open elements is an optgroup element, then act as if an end tag with the tag name "option" had been seen.

If the current node is an optgroup element, then pop that node from the stack of open elements. Otherwise, this is a parse error; ignore the token.

An end tag whose tag name is "option"

If the current node is an option element, then pop that node from the stack of open elements. Otherwise, this is a parse error; ignore the token.

An end tag whose tag name is "select"

If the stack of open elements does not have an element in table scope with the same tag name as the token, this is a parse error. Ignore the token. (fragment case)

Otherwise:

Pop elements from the stack of open elements until a select element has been popped from the stack.

Reset the insertion mode appropriately.

A start tag whose tag name is "select"

Parse error. Act as if the token had been an end tag with the tag name "select" instead.

A start tag whose tag name is one of: "input", "keygen", "textarea"

Parse error.

If the stack of open elements does not have a select element in table scope, ignore the token. (fragment case)

Otherwise, act as if an end tag with the tag name "select" had been seen, and reprocess the token.

A start tag token whose tag name is "script"

Process the token using the rules for the "in head" insertion mode.

An end-of-file token

If the current node is not the root html element, then this is a parse error.

It can only be the current node in the fragment case.

Stop parsing.

Anything else

Parse error. Ignore the token.

8.2.5.20 The "in select in table" insertion mode

Status: Last call for comments

When the insertion mode is "in select in table", tokens must be handled as follows:

A start tag whose tag name is one of: "caption", "table", "tbody", "tfoot", "thead", "tr", "td", "th"

Parse error. Act as if an end tag with the tag name "select" had been seen, and reprocess the token.

An end tag whose tag name is one of: "caption", "table", "tbody", "tfoot", "thead", "tr", "td", "th"

Parse error.

If the stack of open elements has an element in table scope with the same tag name as that of the token, then act as if an end tag with the tag name "select" had been seen, and reprocess the token. Otherwise, ignore the token.

Anything else

Process the token using the rules for the "in select" insertion mode.

8.2.5.21 The "in foreign content" insertion mode

Status: Last call for comments

When the insertion mode is "in foreign content", tokens must be handled as follows:

A character token

Insert the token's character into the current node.

If the token is not one of U+0009 CHARACTER TABULATION, U+000A LINE FEED (LF), U+000C FORM FEED (FF), or U+0020 SPACE, then set the frameset-ok flag to "not ok".

A comment token

Append a Comment node to the current node with the data attribute set to the data given in the comment token.

A DOCTYPE token

Parse error. Ignore the token.

An end tag whose tag name is "script", if the current node is a script element in the SVG namespace.

Pop the current node off the stack of open elements.

Let the old insertion point have the same value as the current insertion point. Let the insertion point be just before the next input character.

Increment the parser's script nesting level by one. Set the parser pause flag to true.

Process the script element according to the SVG rules, if the user agent supports SVG. [SVG]

Even if this causes new characters to be inserted into the tokenizer, the parser will not be executed reentrantly, since the parser pause flag is true.

Decrement the parser's script nesting level by one. If the parser's script nesting level is zero, then set the parser pause flag to false.

Let the insertion point have the value of the old insertion point. (In other words, restore the insertion point to its previous value. This value might be the "undefined" value.)

An end tag, if the current node is not an element in the HTML namespace.

Run these steps:

  1. Initialize node to be the current node (the bottommost node of the stack).

  2. If node is not an element with the same tag name as the token, then this is a parse error.

  3. Loop: If node has the same tag name as the token, pop elements from the stack of open elements until node has been popped from the stack, and then abort these steps.

  4. Set node to the previous entry in the stack of open elements.

  5. If node is an element in the HTML namespace, process the token using the rules for the secondary insertion mode. If, after doing so, the insertion mode is still "in foreign content", but there is no element in scope that has a namespace other than the HTML namespace, switch the insertion mode to the secondary insertion mode.

  6. Return to the step labeled loop.

A start tag whose tag name is neither "mglyph" nor "malignmark", if the current node is an mi element in the MathML namespace.
A start tag whose tag name is neither "mglyph" nor "malignmark", if the current node is an mo element in the MathML namespace.
A start tag whose tag name is neither "mglyph" nor "malignmark", if the current node is an mn element in the MathML namespace.
A start tag whose tag name is neither "mglyph" nor "malignmark", if the current node is an ms element in the MathML namespace.
A start tag whose tag name is neither "mglyph" nor "malignmark", if the current node is an mtext element in the MathML namespace.
A start tag whose tag name is "svg", if the current node is an annotation-xml element in the MathML namespace.
A start tag, if the current node is a foreignObject element in the SVG namespace.
A start tag, if the current node is a desc element in the SVG namespace.
A start tag, if the current node is a title element in the SVG namespace.
A start tag, if the current node is an element in the HTML namespace.
Any other end tag

Process the token using the rules for the secondary insertion mode.

If, after doing so, the insertion mode is still "in foreign content", but there is no element in scope that has a namespace other than the HTML namespace, switch the insertion mode to the secondary insertion mode.

A start tag whose tag name is one of: "b", "big", "blockquote", "body", "br", "center", "code", "dd", "div", "dl", "dt", "em", "embed", "h1", "h2", "h3", "h4", "h5", "h6", "head", "hr", "i", "img", "li", "listing", "menu", "meta", "nobr", "ol", "p", "pre", "ruby", "s", "small", "span", "strong", "strike", "sub", "sup", "table", "tt", "u", "ul", "var"
A start tag whose tag name is "font", if the token has any attributes named "color", "face", or "size"
An end-of-file token

Parse error.

Pop elements from the stack of open elements until either a math element or an svg element has been popped from the stack, and reprocess the token.

Any other start tag

If the current node is an element in the MathML namespace, adjust MathML attributes for the token. (This fixes the case of MathML attributes that are not all lowercase.)

If the current node is an element in the SVG namespace, and the token's tag name is one of the ones in the first column of the following table, change the tag name to the name given in the corresponding cell in the second column. (This fixes the case of SVG elements that are not all lowercase.)

Tag name Element name
altglyph altGlyph
altglyphdef altGlyphDef
altglyphitem altGlyphItem
animatecolor animateColor
animatemotion animateMotion
animatetransform animateTransform
clippath clipPath
feblend feBlend
fecolormatrix feColorMatrix
fecomponenttransfer feComponentTransfer
fecomposite feComposite
feconvolvematrix feConvolveMatrix
fediffuselighting feDiffuseLighting
fedisplacementmap feDisplacementMap
fedistantlight feDistantLight
feflood feFlood
fefunca feFuncA
fefuncb feFuncB
fefuncg feFuncG
fefuncr feFuncR
fegaussianblur feGaussianBlur
feimage feImage
femerge feMerge
femergenode feMergeNode
femorphology feMorphology
feoffset feOffset
fepointlight fePointLight
fespecularlighting feSpecularLighting
fespotlight feSpotLight
fetile feTile
feturbulence feTurbulence
foreignobject foreignObject
glyphref glyphRef
lineargradient linearGradient
radialgradient radialGradient
textpath textPath

If the current node is an element in the SVG namespace, adjust SVG attributes for the token. (This fixes the case of SVG attributes that are not all lowercase.)

Adjust foreign attributes for the token. (This fixes the use of namespaced attributes, in particular XLink in SVG.)

Insert a foreign element for the token, in the same namespace as the current node.

If the token has its self-closing flag set, pop the current node off the stack of open elements and acknowledge the token's self-closing flag.

8.2.5.22 The "after body" insertion mode

Status: Last call for comments

When the insertion mode is "after body", tokens must be handled as follows:

A character token that is one of U+0009 CHARACTER TABULATION, U+000A LINE FEED (LF), U+000C FORM FEED (FF), or U+0020 SPACE

Process the token using the rules for the "in body" insertion mode.

A comment token

Append a Comment node to the first element in the stack of open elements (the html element), with the data attribute set to the data given in the comment token.

A DOCTYPE token

Parse error. Ignore the token.

A start tag whose tag name is "html"

Process the token using the rules for the "in body" insertion mode.

An end tag whose tag name is "html"

If the parser was originally created as part of the HTML fragment parsing algorithm, this is a parse error; ignore the token. (fragment case)

Otherwise, switch the insertion mode to "after after body".

An end-of-file token

Stop parsing.

Anything else

Parse error. Switch the insertion mode to "in body" and reprocess the token.

8.2.5.23 The "in frameset" insertion mode

Status: Last call for comments

When the insertion mode is "in frameset", tokens must be handled as follows:

A character token that is one of U+0009 CHARACTER TABULATION, U+000A LINE FEED (LF), U+000C FORM FEED (FF), or U+0020 SPACE

Insert the character into the current node.

A comment token

Append a Comment node to the current node with the data attribute set to the data given in the comment token.

A DOCTYPE token

Parse error. Ignore the token.

A start tag whose tag name is "html"

Process the token using the rules for the "in body" insertion mode.

A start tag whose tag name is "frameset"

Insert an HTML element for the token.

An end tag whose tag name is "frameset"

If the current node is the root html element, then this is a parse error; ignore the token. (fragment case)

Otherwise, pop the current node from the stack of open elements.

If the parser was not originally created as part of the HTML fragment parsing algorithm (fragment case), and the current node is no longer a frameset element, then switch the insertion mode to "after frameset".

A start tag whose tag name is "frame"

Insert an HTML element for the token. Immediately pop the current node off the stack of open elements.

Acknowledge the token's self-closing flag, if it is set.

A start tag whose tag name is "noframes"

Process the token using the rules for the "in head" insertion mode.

An end-of-file token

If the current node is not the root html element, then this is a parse error.

It can only be the current node in the fragment case.

Stop parsing.

Anything else

Parse error. Ignore the token.

8.2.5.24 The "after frameset" insertion mode

Status: Last call for comments

When the insertion mode is "after frameset", tokens must be handled as follows:

A character token that is one of U+0009 CHARACTER TABULATION, U+000A LINE FEED (LF), U+000C FORM FEED (FF), or U+0020 SPACE

Insert the character into the current node.

A comment token

Append a Comment node to the current node with the data attribute set to the data given in the comment token.

A DOCTYPE token

Parse error. Ignore the token.

A start tag whose tag name is "html"

Process the token using the rules for the "in body" insertion mode.

An end tag whose tag name is "html"

Switch the insertion mode to "after after frameset".

A start tag whose tag name is "noframes"

Process the token using the rules for the "in head" insertion mode.

An end-of-file token

Stop parsing.

Anything else

Parse error. Ignore the token.

8.2.5.25 The "after after body" insertion mode

Status: Last call for comments

When the insertion mode is "after after body", tokens must be handled as follows:

A comment token

Append a Comment node to the Document object with the data attribute set to the data given in the comment token.

A DOCTYPE token
A character token that is one of U+0009 CHARACTER TABULATION, U+000A LINE FEED (LF), U+000C FORM FEED (FF), or U+0020 SPACE
A start tag whose tag name is "html"

Process the token using the rules for the "in body" insertion mode.

An end-of-file token

Stop parsing.

Anything else

Parse error. Switch the insertion mode to "in body" and reprocess the token.

8.2.5.26 The "after after frameset" insertion mode

Status: Last call for comments

When the insertion mode is "after after frameset", tokens must be handled as follows:

A comment token

Append a Comment node to the Document object with the data attribute set to the data given in the comment token.

A DOCTYPE token
A character token that is one of U+0009 CHARACTER TABULATION, U+000A LINE FEED (LF), U+000C FORM FEED (FF), or U+0020 SPACE
A start tag whose tag name is "html"

Process the token using the rules for the "in body" insertion mode.

An end-of-file token

Stop parsing.

A start tag whose tag name is "noframes"

Process the token using the rules for the "in head" insertion mode.

Anything else

Parse error. Ignore the token.

8.2.6 The end

Status: Last call for comments

Once the user agent stops parsing the document, the user agent must run the following steps:

  1. Set the current document readiness to "interactive" and the insertion point to undefined.

  2. Pop all the nodes off the stack of open elements.

  3. If the list of scripts that will execute when the document has finished parsing is not empty, run these substeps:

    1. Spin the event loop until the first script in the list of scripts that will execute when the document has finished parsing has its "ready to be parser-executed" flag set and there is no style sheet blocking scripts.

    2. Execute the first script in the list of scripts that will execute when the document has finished parsing.

    3. Remove the first script element from the list of scripts that will execute when the document has finished parsing (i.e. shift out the first entry in the list).

    4. If the list of scripts that will execute when the document has finished parsing is still not empty, repeat these substeps again from substep 1.

  4. Spin the event loop until the list of scripts that will execute as soon as possible is empty.

  5. Queue a task to fire a simple event named DOMContentLoaded at the Document.

  6. Spin the event loop until there is nothing that delays the load event in the Document.

  7. Queue a task to set the current document readiness to "complete".

  8. If the Document is in a browsing context, then queue a task to fire a simple event named load at the Document's Window object, but with its target set to the Document object (and the currentTarget set to the Window object).

  9. If the Document is in a browsing context, then queue a task to fire a pageshow event at the Window object of the Document, but with its target set to the Document object (and the currentTarget set to the Window object), using the PageTransitionEvent interface, with the persisted attribute set to false. This event must not bubble, must not be cancelable, and has no default action.

  10. If the Document has a pending state object, then queue a task to fire a popstate event at the Document's Window object using the PopStateEvent interface, with the state attribute set to the current value of the pending state object. This event must bubble but not be cancelable and has no default action.

  11. If the Document has any pending application cache download process tasks, then queue each such task in the order they were added to the list of pending application cache download process tasks, and then empty the list of pending application cache download process tasks. The task source for these tasks is the networking task source.

  12. The Document is now completely loaded.

When the user agent is to abort an HTML parser, it must run the following steps:

  1. Throw away any pending content in the input stream, and discard any future content that would have been added to it.

  2. Pop all the nodes off the stack of open elements.

Except where otherwise specified, the task source for the tasks mentioned in this section is the DOM manipulation task source.

8.2.7 Coercing an HTML DOM into an infoset

Status: Last call for comments

When an application uses an HTML parser in conjunction with an XML pipeline, it is possible that the constructed DOM is not compatible with the XML tool chain in certain subtle ways. For example, an XML toolchain might not be able to represent attributes with the name xmlns, since they conflict with the Namespaces in XML syntax. There is also some data that the HTML parser generates that isn't included in the DOM itself. This section specifies some rules for handling these issues.

If the XML API being used doesn't support DOCTYPEs, the tool may drop DOCTYPEs altogether.

If the XML API doesn't support attributes in no namespace that are named "xmlns", attributes whose names start with "xmlns:", or attributes in the XMLNS namespace, then the tool may drop such attributes.

The tool may annotate the output with any namespace declarations required for proper operation.

If the XML API being used restricts the allowable characters in the local names of elements and attributes, then the tool may map all element and attribute local names that the API wouldn't support to a set of names that are allowed, by replacing any character that isn't supported with the uppercase letter U and the six digits of the character's Unicode code point when expressed in hexadecimal, using digits 0-9 and capital letters A-F as the symbols, in increasing numeric order.

For example, the element name foo<bar, which can be output by the HTML parser, though it is neither a legal HTML element name nor a well-formed XML element name, would be converted into fooU00003Cbar, which is a well-formed XML element name (though it's still not legal in HTML by any means).

As another example, consider the attribute xlink:href. Used on a MathML element, it becomes, after being adjusted, an attribute with a prefix "xlink" and a local name "href". However, used on an HTML element, it becomes an attribute with no prefix and the local name "xlink:href", which is not a valid NCName, and thus might not be accepted by an XML API. It could thus get converted, becoming "xlinkU00003Ahref".

The resulting names from this conversion conveniently can't clash with any attribute generated by the HTML parser, since those are all either lowercase or those listed in the adjust foreign attributes algorithm's table.

If the XML API restricts comments from having two consecutive U+002D HYPHEN-MINUS characters (--), the tool may insert a single U+0020 SPACE character between any such offending characters.

If the XML API restricts comments from ending in a U+002D HYPHEN-MINUS character (-), the tool may insert a single U+0020 SPACE character at the end of such comments.

If the XML API restricts allowed characters in character data, attribute values, or comments, the tool may replace any U+000C FORM FEED (FF) character with a U+0020 SPACE character, and any other literal non-XML character with a U+FFFD REPLACEMENT CHARACTER.

If the tool has no way to convey out-of-band information, then the tool may drop the following information:

The mutations allowed by this section apply after the HTML parser's rules have been applied. For example, a <a::> start tag will be closed by a </a::> end tag, and never by a </aU00003AU00003A> end tag, even if the user agent is using the rules above to then generate an actual element in the DOM with the name aU00003AU00003A for that start tag.

8.2.8 An introduction to error handling and strange cases in the parser

Status: Last call for comments

This section is non-normative.

This section examines some erroneous markup and discusses how the HTML parser handles these cases.

8.2.8.1 Misnested tags: <b><i></b></i>

This section is non-normative.

The most-often discussed example of erroneous markup is as follows:

<p>1<b>2<i>3</b>4</i>5</p>

The parsing of this markup is straightforward up to the "3". At this point, the DOM looks like this:

Here, the stack of open elements has five elements on it: html, body, p, b, and i. The list of active formatting elements just has two: b and i. The insertion mode is "in body".

Upon receiving the end tag token with the tag name "b", the "adoption agency algorithm" is invoked. This is a simple case, in that the formatting element is the b element, and there is no furthest block. Thus, the stack of open elements ends up with just three elements: html, body, and p, while the list of active formatting elements has just one: i. The DOM tree is unmodified at this point.

The next token is a character ("4"), triggers the reconstruction of the active formatting elements, in this case just the i element. A new i element is thus created for the "4" text node. After the end tag token for the "i" is also received, and the "5" text node is inserted, the DOM looks as follows:

8.2.8.2 Misnested tags: <b><p></b></p>

This section is non-normative.

A case similar to the previous one is the following:

<b>1<p>2</b>3</p>

Up to the "2" the parsing here is straightforward:

The interesting part is when the end tag token with the tag name "b" is parsed.

Before that token is seen, the stack of open elements has four elements on it: html, body, b, and p. The list of active formatting elements just has the one: b. The insertion mode is "in body".

Upon receiving the end tag token with the tag name "b", the "adoption agency algorithm" is invoked, as in the previous example. However, in this case, there is a furthest block, namely the p element. Thus, this time the adoption agency algorithm isn't skipped over.

The common ancestor is the body element. A conceptual "bookmark" marks the position of the b in the list of active formatting elements, but since that list has only one element in it, it won't have much effect.

As the algorithm progresses, node ends up set to the formatting element (b), and last node ends up set to the furthest block (p).

The last node gets appended (moved) to the common ancestor, so that the DOM looks like:

A new b element is created, and the children of the p element are moved to it:

Finally, the new b element is appended to the p element, so that the DOM looks like:

The b element is removed from the list of active formatting elements and the stack of open elements, so that when the "3" is parsed, it is appended to the p element:

8.2.8.3 Unexpected markup in tables

Status: Last call for comments

This section is non-normative.

Error handling in tables is, for historical reasons, especially strange. For example, consider the following markup:

<table><b><tr><td>aaa</td></tr>bbb</table>ccc

The highlighted b element start tag is not allowed directly inside a table like that, and the parser handles this case by placing the element before the table. (This is called foster parenting.) This can be seen by examining the DOM tree as it stands just after the table element's start tag has been seen:

...and then immediately after the b element start tag has been seen:

At this point, the stack of open elements has on it the elements html, body, table, and b (in that order, despite the resulting DOM tree); the list of active formatting elements just has the b element in it; and the insertion mode is "in table".

The tr start tag causes the b element to be popped off the stack and a tbody start tag to be implied; the tbody and tr elements are then handled in a rather straight-forward manner, taking the parser through the "in table body" and "in row" insertion modes, after which the DOM looks as follows:

Here, the stack of open elements has on it the elements html, body, table, tbody, and tr; the list of active formatting elements still has the b element in it; and the insertion mode is "in row".

The td element start tag token, after putting a td element on the tree, puts a marker on the list of active formatting elements (it also switches to the "in cell" insertion mode).

The marker means that when the "aaa" character tokens are seen, no b element is created to hold the resulting text node:

The end tags are handled in a straight-forward manner; after handling them, the stack of open elements has on it the elements html, body, table, and tbody; the list of active formatting elements still has the b element in it (the marker having been removed by the "td" end tag token); and the insertion mode is "in table body".

Thus it is that the "bbb" character tokens are found. These trigger the "in table text" insertion mode to be used (with the original insertion mode set to "in table body"). The character tokens are collected, and when the next token (the table element end tag) is seen, they are processed as a group. Since they are not all spaces, they are handled as per the "anything else" rules in the "in table" insertion mode, which defer to the "in body" insertion mode but with foster parenting.

When the active formatting elements are reconstructed, a b element is created and foster parented, and then the "bbb" text node is appended to it:

The stack of open elements has on it the elements html, body, table, tbody, and the new b (again, note that this doesn't match the resulting tree!); the list of active formatting elements has the new b element in it; and the insertion mode is still "in table body".

Had the character tokens been only space characters instead of "bbb", then those space characters would just be appended to the tbody element.

Finally, the table is closed by a "table" end tag. This pops all the nodes from the stack of open elements up to and including the table element, but it doesn't affect the list of active formatting elements, so the "ccc" character tokens after the table result in yet another b element being created, this time after the table:

8.2.8.4 Scripts that modify the page as it is being parsed

Status: Last call for comments

This section is non-normative.

Consider the following markup, which for this example we will assume is the document with URL http://example.com/inner, being rendered as the content of an iframe in another document with the URL http://example.com/outer:

<div id=a>
 <script>
  var div = document.getElementById('a');
  parent.document.body.appendChild(div);
 </script>
 <script>
  alert(document.URL);
 </script>
</div>
<script>
 alert(document.URL);
</script>

Up to the first "script" end tag, before the script is parsed, the result is relatively straightforward:

After the script is parsed, though, the div element and its child script element are gone:

They are, at this point, in the Document of the aforementioned outer browsing context. However, the stack of open elements still contains the div element.

Thus, when the second script element is parsed, it is inserted into the outer Document object.

This also means that the script's global object is the outer browsing context's Window object, not the Window object inside the iframe.

This isn't a security problem since the script that moves the div into the outer Document can only do so because the two Document object have the same origin.

Thus, the first alert says "http://example.com/outer".

Once the div element's end tag is parsed, the div element is popped off the stack, and so the next script element is in the inner Document:

This second alert will say "http://example.com/inner".

8.3 Serializing HTML fragments

Status: Last call for comments

The following steps form the HTML fragment serialization algorithm. The algorithm takes as input a DOM Element or Document, referred to as the node, and either returns a string or raises an exception.

This algorithm serializes the children of the node being serialized, not the node itself.

  1. Let s be a string, and initialize it to the empty string.

  2. For each child node of the node, in tree order, run the following steps:

    1. Let current node be the child node being processed.

    2. Append the appropriate string from the following list to s:

      If current node is an Element

      Append a U+003C LESS-THAN SIGN character character (<), followed by the element's tag name. (For nodes created by the HTML parser or Document.createElement(), the tag name will be lowercase.)

      For each attribute that the element has, append a U+0020 SPACE character, the attribute's name (which, for attributes set by the HTML parser or by Element.setAttributeNode() or Element.setAttribute(), will be lowercase), a U+003D EQUALS SIGN character (=), a U+0022 QUOTATION MARK character ("), the attribute's value, escaped as described below in attribute mode, and a second U+0022 QUOTATION MARK character (").

      While the exact order of attributes is UA-defined, and may depend on factors such as the order that the attributes were given in the original markup, the sort order must be stable, such that consecutive invocations of this algorithm serialize an element's attributes in the same order.

      Append a U+003E GREATER-THAN SIGN character (>).

      If current node is an area, base, basefont, bgsound, br, col, embed, frame, hr, img, input, keygen, link, meta, param, or wbr element, then continue on to the next child node at this point.

      If current node is a pre, textarea, or listing element, append a U+000A LINE FEED (LF) character.

      Append the value of running the HTML fragment serialization algorithm on the current node element (thus recursing into this algorithm for that element), followed by a U+003C LESS-THAN SIGN character (<), a U+002F SOLIDUS character (/), the element's tag name again, and finally a U+003E GREATER-THAN SIGN character (>).

      If current node is a Text or CDATASection node

      If the parent of current node is a style, script, xmp, iframe, noembed, noframes, or plaintext element, or if the parent of current node is noscript element and scripting is enabled for the node, then append the value of current node's data IDL attribute literally.

      Otherwise, append the value of current node's data IDL attribute, escaped as described below.

      If current node is a Comment

      Append the literal string <!-- (U+003C LESS-THAN SIGN, U+0021 EXCLAMATION MARK, U+002D HYPHEN-MINUS, U+002D HYPHEN-MINUS), followed by the value of current node's data IDL attribute, followed by the literal string --> (U+002D HYPHEN-MINUS, U+002D HYPHEN-MINUS, U+003E GREATER-THAN SIGN).

      If current node is a ProcessingInstruction

      Append the literal string <? (U+003C LESS-THAN SIGN, U+003F QUESTION MARK), followed by the value of current node's target IDL attribute, followed by a single U+0020 SPACE character, followed by the value of current node's data IDL attribute, followed by a single U+003E GREATER-THAN SIGN character (>).

      If current node is a DocumentType

      Append the literal string <!DOCTYPE (U+003C LESS-THAN SIGN, U+0021 EXCLAMATION MARK, U+0044 LATIN CAPITAL LETTER D, U+004F LATIN CAPITAL LETTER O, U+0043 LATIN CAPITAL LETTER C, U+0054 LATIN CAPITAL LETTER T, U+0059 LATIN CAPITAL LETTER Y, U+0050 LATIN CAPITAL LETTER P, U+0045 LATIN CAPITAL LETTER E), followed by a space (U+0020 SPACE), followed by the value of current node's name IDL attribute, followed by the literal string > (U+003E GREATER-THAN SIGN).

      Other node types (e.g. Attr) cannot occur as children of elements. If, despite this, they somehow do occur, this algorithm must raise an INVALID_STATE_ERR exception.

  3. The result of the algorithm is the string s.

Escaping a string (for the purposes of the algorithm above) consists of replacing any occurrences of the "&" character by the string "&amp;", any occurrences of the U+00A0 NO-BREAK SPACE character by the string "&nbsp;", and, if the algorithm was invoked in the attribute mode, any occurrences of the """ character by the string "&quot;", or if it was not, any occurrences of the "<" character by the string "&lt;", any occurrences of the ">" character by the string "&gt;".

Entity reference nodes are assumed to be expanded by the user agent, and are therefore not covered in the algorithm above.

It is possible that the output of this algorithm, if parsed with an HTML parser, will not return the original tree structure. For instance, if a textarea element to which a Comment node has been appended is serialized and the output is then reparsed, the comment will end up being displayed in the text field. Similarly, if, as a result of DOM manipulation, an element contains a comment that contains the literal string "-->", then when the result of serializing the element is parsed, the comment will be truncated at that point and the rest of the comment will be interpreted as markup. More examples would be making a script element contain a text node with the text string "</script>", or having a p element that contains a ul element (as the ul element's start tag would imply the end tag for the p).

8.4 Parsing HTML fragments

Status: Last call for comments

The following steps form the HTML fragment parsing algorithm. The algorithm optionally takes as input an Element node, referred to as the context element, which gives the context for the parser, as well as input, a string to parse, and returns a list of zero or more nodes.

Parts marked fragment case in algorithms in the parser section are parts that only occur if the parser was created for the purposes of this algorithm (and with a context element). The algorithms have been annotated with such markings for informational purposes only; such markings have no normative weight. If it is possible for a condition described as a fragment case to occur even when the parser wasn't created for the purposes of handling this algorithm, then that is an error in the specification.

  1. Create a new Document node, and mark it as being an HTML document.

  2. If there is a context element, and the Document of the context element is in quirks mode, then let the Document be in quirks mode. Otherwise, if there is a context element, and the Document of the context element is in limited quirks mode, then let the Document be in limited quirks mode. Otherwise, leave the Document in no quirks mode.

  3. Create a new HTML parser, and associate it with the just created Document node.

  4. If there is a context element, run these substeps:

    1. Set the state of the HTML parser's tokenization stage as follows:

      If it is a title or textarea element
      Switch the tokenizer to the RCDATA state.
      If it is a style, xmp, iframe, noembed, or noframes element
      Switch the tokenizer to the RAWTEXT state.
      If it is a script element
      Switch the tokenizer to the script data state.
      If it is a noscript element
      If the scripting flag is enabled, switch the tokenizer to the RAWTEXT state. Otherwise, leave the tokenizer in the data state.
      If it is a plaintext element
      Switch the tokenizer to the PLAINTEXT state.
      Otherwise
      Leave the tokenizer in the data state.

      For performance reasons, an implementation that does not report errors and that uses the actual state machine described in this specification directly could use the PLAINTEXT state instead of the RAWTEXT and script data states where those are mentioned in the list above. Except for rules regarding parse errors, they are equivalent, since there is no appropriate end tag token in the fragment case, yet they involve far fewer state transitions.

    2. Let root be a new html element with no attributes.

    3. Append the element root to the Document node created above.

    4. Set up the parser's stack of open elements so that it contains just the single element root.

    5. Reset the parser's insertion mode appropriately.

      The parser will reference the context element as part of that algorithm.

    6. Set the parser's form element pointer to the nearest node to the context element that is a form element (going straight up the ancestor chain, and including the element itself, if it is a form element), or, if there is no such form element, to null.

  5. Place into the input stream for the HTML parser just created the input. The encoding confidence is irrelevant.

  6. Start the parser and let it run until it has consumed all the characters just inserted into the input stream.

  7. If there is a context element, return the child nodes of root, in tree order.

    Otherwise, return the children of the Document object, in tree order.