Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow more characters in element/attribute names and prefixes #1079

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
136 changes: 98 additions & 38 deletions dom.bs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ Indent: 1

<pre class=anchors>
urlPrefix: https://www.w3.org/TR/xml/#NT-
type: type
text: Name; url: Name
type: dfn
text: Name; url: Name; for: XML
text: Char; url: Char
text: PubidChar; url: PubidChar
urlPrefix: https://www.w3.org/TR/xml-names/#NT-
type: type
type: dfn
text: QName; url: QName
url: https://w3c.github.io/DOM-Parsing/#dfn-createcontextualfragment-fragment
type: method; text: createContextualFragment(); for: Range
Expand Down Expand Up @@ -209,19 +209,59 @@ against a <var>set</var>, run these steps:
added.


<h3 id=namespaces>Namespaces</h3>
<h3 id=name-validation oldids=namespaces>Name validation</h3>

<p>To <dfn export>validate</dfn> a <var>qualifiedName</var>, <a>throw</a> an
"{{InvalidCharacterError!!exception}}" {{DOMException}} if <var>qualifiedName</var> does not match
the <code><a type>QName</a></code> production.
<p>A [=string=] is a <dfn>valid namespace prefix</dfn> if its [=string/length=] is at least 1 and it
does not contain [=ASCII whitespace=], U+0000 NULL, U+002F (/), or U+003E (>).

<p>To <dfn export>validate and extract</dfn> a <var>namespace</var> and <var>qualifiedName</var>,
run these steps:
<p>A [=string=] is a <dfn>valid attribute local name</dfn> if its [=string/length=] is at least 1
and it does not contain [=ASCII whitespace=], U+0000 NULL, U+002F (/), U+003D (=), or U+003E (>).

<p>A [=string=] |name| is a <dfn>valid element local name</dfn> if the following steps return true:

<ol>
<li><p>If <var>namespace</var> is the empty string, then set it to null.
<li><p>If |name|'s [=string/length=] is 0, then return false.

<li><p><a>Validate</a> <var>qualifiedName</var>.
<li>
<p>If |name|'s 0th [=code point=] is an [=ASCII alpha=], then:

<ol>
<li><p>If |name| contains [=ASCII whitespace=], U+0000 NULL, U+002F (/), or U+003E (>), then
return false.

<li><p>Return true.
</ol>

<li><p>If |name|'s 0th [=code point=] is not U+003A (:), U+005F (_), or in the range U+0080
to U+10FFFF, inclusive, then return false.

<li><p>If |name|'s subsequent [=code points=], if any, are not [=ASCII alphas=], [=ASCII digits=],
U+002D (-), U+002E (.), U+003A (:), U+005F (_), or in the range U+0080 to U+10FFFF, inclusive, then
return false.

<li><p>Return true.
</ol>

<p class=note>This concept is used to validate [=/element=] [=Element/local names=], when
constructed by DOM APIs. The intention is to allow any name that is possible to construct using the
HTML parser (the branch where the first [=code point=] is an [=ASCII alpha=]), plus some additional
possibilities. For those additional possibilities, the ASCII range is restricted for historical
reasons, but beyond ASCII anything is allowed.

<div class=note>
<p>The following JavaScript-compatible regular expression is an implementation of the above
definition:

<pre class=lang-javascript>
/^(?:[A-Za-z][^\0\t\n\f\r\u0020/>]*)|(?:[:_\u0080-\u{10FFFF}][A-Za-z0-9-.:_\u0080-\u{10FFFF}]*)$/u
</pre>
</div>

<p>To <dfn>validate and extract</dfn> a <var>namespace</var> and <var>qualifiedName</var>, given a
<var>context</var>:

<ol>
<li><p>If <var>namespace</var> is the empty string, then set it to null.

<li><p>Let <var>prefix</var> be null.

Expand All @@ -230,6 +270,15 @@ run these steps:
<li><p>If <var>qualifiedName</var> contains a U+003A (:), then <a>strictly split</a> the string on
it and set <var>prefix</var> to the part before and <var>localName</var> to the part after.

<li><p>If <var>prefix</var> is not a [=valid namespace prefix=], then [=throw=] an
"{{InvalidCharacterError}}" {{DOMException}}.

<li><p>If <var>context</var> is "<code>attribute</code>" and <var>localName</var> is not a
[=valid attribute local name=], then [=throw=] an "{{InvalidCharacterError}}" {{DOMException}}.

<li><p>If <var>context</var> is "<code>element</code>" and <var>localName</var> is not a
[=valid element local name=], then [=throw=] an "{{InvalidCharacterError}}" {{DOMException}}.

<li><p>If <var>prefix</var> is non-null and <var>namespace</var> is null, then <a>throw</a> a
"{{NamespaceError!!exception}}" {{DOMException}}.

Expand Down Expand Up @@ -5076,8 +5125,8 @@ method steps are to return the <a>list of elements with class names <var>classNa
<var>document</var> is an <a>HTML document</a> or <var>document</var>'s
<a for=Document>content type</a> is "<code>application/xhtml+xml</code>"; otherwise null.

<p>If <var>localName</var> does not match the <code><a type>Name</a></code> production an
"{{InvalidCharacterError!!exception}}" {{DOMException}} will be thrown.
<p>If <var>localName</var> is not a <a>valid element local name</a> an
"{{InvalidCharacterError}}" {{DOMException}} will be thrown.

<p>When supplied, <var>options</var>'s {{ElementCreationOptions/is}} can be used to create a
<a>customized built-in element</a>.
Expand All @@ -5090,8 +5139,9 @@ method steps are to return the <a>list of elements with class names <var>classNa
<var>qualifiedName</var> or null. Its <a for=Element>local name</a> will be everything after
U+003A (:) in <var>qualifiedName</var> or <var>qualifiedName</var>.

<p>If <var>qualifiedName</var> does not match the <code><a type>QName</a></code> production an
"{{InvalidCharacterError!!exception}}" {{DOMException}} will be thrown.
<p>If <var>qualifiedName</var> is not a (possibly-prefixed)
<a>valid element local name</a> an "{{InvalidCharacterError}}" {{DOMException}} will be
thrown.

<p>If one of the following conditions is true a "{{NamespaceError!!exception}}" {{DOMException}}
will be thrown:
Expand Down Expand Up @@ -5135,8 +5185,7 @@ method steps are to return the <a>list of elements with class names <var>classNa
<a for=/>node</a> whose
<a for=ProcessingInstruction>target</a> is <var>target</var> and
<a for=CharacterData>data</a> is <var>data</var>.
If <var>target</var> does not match the
<code><a type>Name</a></code> production an
If <var>target</var> does not match the <code>[=XML/Name=]</code> production an
"{{InvalidCharacterError!!exception}}" {{DOMException}} will be thrown.
If <var>data</var> contains "<code>?></code>" an
"{{InvalidCharacterError!!exception}}" {{DOMException}} will be thrown.
Expand All @@ -5153,7 +5202,7 @@ method steps are to return the <a>list of elements with class names <var>classNa
method steps are:

<ol>
<li><p>If <var>localName</var> does not match the <code><a type>Name</a></code> production, then
<li><p>If <var>localName</var> is not a <a>valid element local name</a>, then
<a>throw</a> an "{{InvalidCharacterError!!exception}}" {{DOMException}}.

<li><p>If <a>this</a> is an <a>HTML document</a>, then set <var>localName</var> to
Expand All @@ -5179,7 +5228,8 @@ method steps are:

<ol>
<li><p>Let <var>namespace</var>, <var>prefix</var>, and <var>localName</var> be the result of
passing <var>namespace</var> and <var>qualifiedName</var> to <a>validate and extract</a>.
[=validate and extract|validating and extracting=] <var>namespace</var> and
<var>qualifiedName</var> given "<code>element</code>".

<li><p>Let <var>is</var> be null.

Expand Down Expand Up @@ -5210,7 +5260,7 @@ to return a new {{Text}} <a for=/>node</a> whose <a for=CharacterData>data</a> i
and <a for=Node>node document</a> is <a>this</a>.

<p class=note>No check is performed that <var>data</var> consists of
characters that match the <code><a type>Char</a></code> production.
characters that match the <code><a>Char</a></code> production.

<p>The <dfn method for=Document><code>createCDATASection(<var>data</var>)</code></dfn> method steps
are:
Expand All @@ -5231,7 +5281,7 @@ to return a new {{Comment}} <a for=/>node</a> whose <a for=CharacterData>data</a
and <a for=Node>node document</a> is <a>this</a>.

<p class=note>No check is performed that <var>data</var> consists of
characters that match the <code><a type>Char</a></code> production
characters that match the <code><a>Char</a></code> production
or that it contains two adjacent hyphens or ends with a hyphen.

<p>The
Expand All @@ -5240,8 +5290,7 @@ method steps are:

<ol>
<li>If <var>target</var> does not match the
<!--<code data-anolis-type>PITarget</code>-->
<code><a type>Name</a></code> production,
<code>[=XML/Name=]</code> production,
then <a>throw</a> an "{{InvalidCharacterError!!exception}}" {{DOMException}}. <!-- DOM3 does not check for "xml" -->

<li>If <var>data</var> contains the string
Expand All @@ -5258,7 +5307,7 @@ method steps are:
<p class=note>No check is performed that <var>target</var> contains
"<code>xml</code>" or "<code>:</code>", or that
<var>data</var> contains characters that match the
<code><a type>Char</a></code> production.
<code><a>Char</a></code> production.

<hr>

Expand Down Expand Up @@ -5359,8 +5408,8 @@ these steps:
steps are:

<ol>
<li><p>If <var>localName</var> does not match the <code><a type>Name</a></code> production in XML,
then <a>throw</a> an "{{InvalidCharacterError!!exception}}" {{DOMException}}.
<li><p>If <var>localName</var> is not a <a>valid attribute local name</a>, then
<a>throw</a> an "{{InvalidCharacterError!!exception}}" {{DOMException}}.

<li>If <a>this</a> is an <a>HTML document</a>, then set <var>localName</var> to
<var>localName</var> in <a>ASCII lowercase</a>.
Expand All @@ -5375,7 +5424,8 @@ method steps are:

<ol>
<li><p>Let <var>namespace</var>, <var>prefix</var>, and <var>localName</var> be the result of
passing <var>namespace</var> and <var>qualifiedName</var> to <a>validate and extract</a>.
[=validate and extract|validating and extracting=] <var>namespace</var> and
<var>qualifiedName</var> given "<code>attribute</code>".

<li><p>Return a new <a>attribute</a> whose <a for=Attr>namespace</a> is <var>namespace</var>,
<a for=Attr>namespace prefix</a> is <var>prefix</var>, <a for=Attr>local name</a> is
Expand Down Expand Up @@ -5521,10 +5571,8 @@ interface DOMImplementation {
Returns a <a>doctype</a>, with the given
<var>qualifiedName</var>, <var>publicId</var>, and
<var>systemId</var>. If <var>qualifiedName</var> does not
match the <code><a type>Name</a></code> production, an
"{{InvalidCharacterError!!exception}}" {{DOMException}} is thrown, and if it does not match the
<code><a type>QName</a></code> production, a
"{{NamespaceError!!exception}}" {{DOMException}} is thrown.
match the <code><a>QName</a></code> production, an
"{{InvalidCharacterError!!exception}}" {{DOMException}} is thrown.

<dt><code><var>doc</var> = <var>document</var> . {{Document/implementation}} . <a method for=DOMImplementation lt=createDocument()>createDocument(<var>namespace</var>, <var>qualifiedName</var> [, <var>doctype</var> = null])</a></code>

Expand Down Expand Up @@ -5557,7 +5605,8 @@ interface DOMImplementation {
method steps are:

<ol>
<li><p><a>Validate</a> <var>qualifiedName</var>.
<li><p>If <var>qualifiedName</var> does not match the <code><a>QName</a></code> production,
then throw an "{{InvalidCharacterError}}" {{DOMException}}.

<li><p>Return a new <a>doctype</a>, with <var>qualifiedName</var> as its
<a for=DocumentType>name</a>, <var>publicId</var> as its <a>public ID</a>, and <var>systemId</var>
Expand All @@ -5566,7 +5615,7 @@ method steps are:
</ol>

<p class=note>No check is performed that <var>publicId</var> code points match the
<code><a type>PubidChar</a></code> production or that <var>systemId</var> does not contain both a
<code><a>PubidChar</a></code> production or that <var>systemId</var> does not contain both a
'<code>"</code>' and a "<code>'</code>".

<p>The
Expand Down Expand Up @@ -6573,8 +6622,14 @@ method steps are:
method steps are:

<ol>
<li><p>If <var>qualifiedName</var> does not match the <code><a type>Name</a></code> production in
XML, then <a>throw</a> an "{{InvalidCharacterError!!exception}}" {{DOMException}}.
<li>
<p>If <var>qualifiedName</var> is not a <a>valid attribute local name</a>, then <a>throw</a> an
"{{InvalidCharacterError!!exception}}" {{DOMException}}.

<p class="note" id="node-setAttribute-qualifiedName">Despite the parameter naming,
<var>qualifiedName</var> is only used as a [=Attr/qualified name=] if an [=attribute=] already
exists with that qualified name. Otherwise, it is used as the [=Attr/local name=] of the new
attribute. We only need to validate it for the latter case.

<li><p>If <a>this</a> is in the <a>HTML namespace</a> and its <a for=Node>node document</a> is an
<a>HTML document</a>, then set <var>qualifiedName</var> to <var>qualifiedName</var> in
Expand All @@ -6599,7 +6654,8 @@ method steps are:

<ol>
<li><p>Let <var>namespace</var>, <var>prefix</var>, and <var>localName</var> be the result of
passing <var>namespace</var> and <var>qualifiedName</var> to <a>validate and extract</a>.
[=validate and extract|validating and extracting=] <var>namespace</var> and
<var>qualifiedName</var> given "<code>element</code>".

<li><p><a>Set an attribute value</a> for <a>this</a> using <var>localName</var>, <var>value</var>,
and also <var>prefix</var> and <var>namespace</var>.
Expand Down Expand Up @@ -6632,8 +6688,12 @@ steps are:
method steps are:

<ol>
<li><p>If <var>qualifiedName</var> does not match the <code><a type>Name</a></code> production in
XML, then <a>throw</a> an "{{InvalidCharacterError!!exception}}" {{DOMException}}.
<li>
<p>If <var>qualifiedName</var> is not a <a>valid attribute local name</a>, then <a>throw</a> an
"{{InvalidCharacterError!!exception}}" {{DOMException}}.

<p class="note">See <a href="#node-setAttribute-qualifiedName">the discussion above</a> about why
we validate it as a local name, instead of a qualified name.

<li><p>If <a>this</a> is in the <a>HTML namespace</a> and its <a for=Node>node document</a> is an
<a>HTML document</a>, then set <var>qualifiedName</var> to <var>qualifiedName</var> in
Expand Down