Skip to content
New issue

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

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

Already on GitHub? # 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