diff --git a/common/changes/@microsoft/tsdoc/octogonz-fix-html-name-regexp_2020-03-27-05-15.json b/common/changes/@microsoft/tsdoc/octogonz-fix-html-name-regexp_2020-03-27-05-15.json
new file mode 100644
index 00000000..6dc935cc
--- /dev/null
+++ b/common/changes/@microsoft/tsdoc/octogonz-fix-html-name-regexp_2020-03-27-05-15.json
@@ -0,0 +1,11 @@
+{
+ "changes": [
+ {
+ "packageName": "@microsoft/tsdoc",
+ "comment": "Fix an issue where \"h1\" was not allowed as an HTML element name",
+ "type": "patch"
+ }
+ ],
+ "packageName": "@microsoft/tsdoc",
+ "email": "4673363+octogonz@users.noreply.github.com"
+}
\ No newline at end of file
diff --git a/tsdoc/src/parser/NodeParser.ts b/tsdoc/src/parser/NodeParser.ts
index cd9e0fef..764611c1 100644
--- a/tsdoc/src/parser/NodeParser.ts
+++ b/tsdoc/src/parser/NodeParser.ts
@@ -1813,8 +1813,9 @@ export class NodeParser {
let done: boolean = false;
while (!done) {
switch (tokenReader.peekTokenKind()) {
- case TokenKind.AsciiWord:
case TokenKind.Hyphen:
+ case TokenKind.Period:
+ case TokenKind.AsciiWord:
tokenReader.readToken();
break;
default:
diff --git a/tsdoc/src/parser/StringChecks.ts b/tsdoc/src/parser/StringChecks.ts
index e55e8357..a0cc0419 100644
--- a/tsdoc/src/parser/StringChecks.ts
+++ b/tsdoc/src/parser/StringChecks.ts
@@ -7,9 +7,14 @@ export class StringChecks {
private static readonly _urlSchemeRegExp: RegExp = /^[a-z][a-z0-9]*\:\/\//i;
private static readonly _urlSchemeAfterRegExp: RegExp = /^[a-z][a-z0-9]*\:\/\/./i;
+ // HTML element definitions:
+ // https://spec.commonmark.org/0.29/#tag-name
// https://www.w3.org/TR/html5/syntax.html#tag-name
// https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
- private static readonly _htmlNameRegExp: RegExp = /^[a-z]+(\-[a-z]+)*$/i;
+ //
+ // We use the CommonMark spec:
+ // "A tag name consists of an ASCII letter followed by zero or more ASCII letters, digits, or hyphens (-)."
+ private static readonly _htmlNameRegExp: RegExp = /^[a-z]+[a-z0-9\-]*$/i;
// Note: In addition to letters, numbers, underscores, and dollar signs, modern ECMAScript
// also allows Unicode categories such as letters, combining marks, digits, and connector punctuation.
@@ -86,7 +91,7 @@ export class StringChecks {
*/
public static explainIfInvalidHtmlName(htmlName: string): string | undefined {
if (!StringChecks._htmlNameRegExp.test(htmlName)) {
- return 'An HTML name must be a sequence of letters separated by hyphens';
+ return 'An HTML name must be an ASCII letter followed by zero or more letters, digits, or hyphens';
}
return undefined;
diff --git a/tsdoc/src/parser/__tests__/NodeParserHtml.test.ts b/tsdoc/src/parser/__tests__/NodeParserHtml.test.ts
index 8a6cd276..e1e5fdf8 100644
--- a/tsdoc/src/parser/__tests__/NodeParserHtml.test.ts
+++ b/tsdoc/src/parser/__tests__/NodeParserHtml.test.ts
@@ -107,3 +107,23 @@ test('07 Closing tags, negative', () => {
' */'
].join('\n'));
});
+
+test('08 Unusual HTML names, positive', () => {
+ TestHelpers.parseAndMatchNodeParserSnapshot([
+ '/**',
+ ' * ',
+ ' * ',
+ ' * ',
+ ' */'
+ ].join('\n'));
+});
+
+test('09 Unusual HTML names, negative', () => {
+ TestHelpers.parseAndMatchNodeParserSnapshot([
+ '/**',
+ ' * <1a/>',
+ ' * ',
+ ' * <_a>',
+ ' */'
+ ].join('\n'));
+});
diff --git a/tsdoc/src/parser/__tests__/__snapshots__/NodeParserHtml.test.ts.snap b/tsdoc/src/parser/__tests__/__snapshots__/NodeParserHtml.test.ts.snap
index aa7a15a9..0c01fd32 100644
--- a/tsdoc/src/parser/__tests__/__snapshots__/NodeParserHtml.test.ts.snap
+++ b/tsdoc/src/parser/__tests__/__snapshots__/NodeParserHtml.test.ts.snap
@@ -946,7 +946,7 @@ Object {
"logMessages": Array [
"(2,4): The HTML element has an invalid attribute: Expecting \\"=\\" after HTML attribute name",
"(2,28): The \\">\\" character should be escaped using a backslash to avoid confusion with an HTML tag",
- "(3,4): The HTML element has an invalid attribute: An HTML name must be a sequence of letters separated by hyphens",
+ "(3,4): The HTML element has an invalid attribute: Expecting \\"=\\" after HTML attribute name",
"(3,28): The \\">\\" character should be escaped using a backslash to avoid confusion with an HTML tag",
"(4,4): The HTML element has an invalid attribute: The HTML string is missing its closing quote",
"(4,31): The \\">\\" character should be escaped using a backslash to avoid confusion with an HTML tag",
@@ -1011,9 +1011,9 @@ Object {
],
},
Object {
- "errorLocation": "attr-",
+ "errorLocation": "two",
"errorLocationPrecedingToken": " ",
- "errorMessage": "The HTML element has an invalid attribute: An HTML name must be a sequence of letters separated by hyphens",
+ "errorMessage": "The HTML element has an invalid attribute: Expecting [q]=[q] after HTML attribute name",
"kind": "ErrorText",
"nodes": Array [
Object {
@@ -1701,3 +1701,270 @@ Object {
},
}
`;
+
+exports[`08 Unusual HTML names, positive 1`] = `
+Object {
+ "buffer": "/**[n] * [<]a1/[>][n] * [<]a-a[>][n] * [<]a--9-[>][n] */",
+ "gaps": Array [],
+ "lines": Array [
+ "[<]a1/[>]",
+ "[<]a-a[>]",
+ "[<]a--9-[>]",
+ ],
+ "logMessages": Array [],
+ "nodes": Object {
+ "kind": "Comment",
+ "nodes": Array [
+ Object {
+ "kind": "Section",
+ "nodes": Array [
+ Object {
+ "kind": "Paragraph",
+ "nodes": Array [
+ Object {
+ "kind": "HtmlStartTag",
+ "nodes": Array [
+ Object {
+ "kind": "Excerpt: HtmlStartTag_OpeningDelimiter",
+ "nodeExcerpt": "[<]",
+ },
+ Object {
+ "kind": "Excerpt: HtmlStartTag_Name",
+ "nodeExcerpt": "a1",
+ },
+ Object {
+ "kind": "Excerpt: HtmlStartTag_ClosingDelimiter",
+ "nodeExcerpt": "/[>]",
+ },
+ ],
+ },
+ Object {
+ "kind": "SoftBreak",
+ "nodes": Array [
+ Object {
+ "kind": "Excerpt: SoftBreak",
+ "nodeExcerpt": "[n]",
+ },
+ ],
+ },
+ Object {
+ "kind": "HtmlStartTag",
+ "nodes": Array [
+ Object {
+ "kind": "Excerpt: HtmlStartTag_OpeningDelimiter",
+ "nodeExcerpt": "[<]",
+ },
+ Object {
+ "kind": "Excerpt: HtmlStartTag_Name",
+ "nodeExcerpt": "a-a",
+ },
+ Object {
+ "kind": "Excerpt: HtmlStartTag_ClosingDelimiter",
+ "nodeExcerpt": "[>]",
+ },
+ ],
+ },
+ Object {
+ "kind": "SoftBreak",
+ "nodes": Array [
+ Object {
+ "kind": "Excerpt: SoftBreak",
+ "nodeExcerpt": "[n]",
+ },
+ ],
+ },
+ Object {
+ "kind": "HtmlStartTag",
+ "nodes": Array [
+ Object {
+ "kind": "Excerpt: HtmlStartTag_OpeningDelimiter",
+ "nodeExcerpt": "[<]",
+ },
+ Object {
+ "kind": "Excerpt: HtmlStartTag_Name",
+ "nodeExcerpt": "a--9-",
+ },
+ Object {
+ "kind": "Excerpt: HtmlStartTag_ClosingDelimiter",
+ "nodeExcerpt": "[>]",
+ },
+ ],
+ },
+ Object {
+ "kind": "SoftBreak",
+ "nodes": Array [
+ Object {
+ "kind": "Excerpt: SoftBreak",
+ "nodeExcerpt": "[n]",
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+}
+`;
+
+exports[`09 Unusual HTML names, negative 1`] = `
+Object {
+ "buffer": "/**[n] * [<]1a/[>][n] * [<]a.a[>][n] * [<]_a[>][n] */",
+ "gaps": Array [],
+ "lines": Array [
+ "[<]1a/[>]",
+ "[<]a.a[>]",
+ "[<]_a[>]",
+ ],
+ "logMessages": Array [
+ "(2,4): Invalid HTML element: An HTML name must be an ASCII letter followed by zero or more letters, digits, or hyphens",
+ "(2,8): The \\">\\" character should be escaped using a backslash to avoid confusion with an HTML tag",
+ "(3,4): Invalid HTML element: An HTML name must be an ASCII letter followed by zero or more letters, digits, or hyphens",
+ "(3,8): The \\">\\" character should be escaped using a backslash to avoid confusion with an HTML tag",
+ "(4,4): Invalid HTML element: An HTML name must be an ASCII letter followed by zero or more letters, digits, or hyphens",
+ "(4,7): The \\">\\" character should be escaped using a backslash to avoid confusion with an HTML tag",
+ ],
+ "nodes": Object {
+ "kind": "Comment",
+ "nodes": Array [
+ Object {
+ "kind": "Section",
+ "nodes": Array [
+ Object {
+ "kind": "Paragraph",
+ "nodes": Array [
+ Object {
+ "errorLocation": "1a",
+ "errorLocationPrecedingToken": "<",
+ "errorMessage": "Invalid HTML element: An HTML name must be an ASCII letter followed by zero or more letters, digits, or hyphens",
+ "kind": "ErrorText",
+ "nodes": Array [
+ Object {
+ "kind": "Excerpt: ErrorText",
+ "nodeExcerpt": "[<]",
+ },
+ ],
+ },
+ Object {
+ "kind": "PlainText",
+ "nodes": Array [
+ Object {
+ "kind": "Excerpt: PlainText",
+ "nodeExcerpt": "1a/",
+ },
+ ],
+ },
+ Object {
+ "errorLocation": "[>]",
+ "errorLocationPrecedingToken": "/",
+ "errorMessage": "The [q][>][q] character should be escaped using a backslash to avoid confusion with an HTML tag",
+ "kind": "ErrorText",
+ "nodes": Array [
+ Object {
+ "kind": "Excerpt: ErrorText",
+ "nodeExcerpt": "[>]",
+ },
+ ],
+ },
+ Object {
+ "kind": "SoftBreak",
+ "nodes": Array [
+ Object {
+ "kind": "Excerpt: SoftBreak",
+ "nodeExcerpt": "[n]",
+ },
+ ],
+ },
+ Object {
+ "errorLocation": "a.a",
+ "errorLocationPrecedingToken": "<",
+ "errorMessage": "Invalid HTML element: An HTML name must be an ASCII letter followed by zero or more letters, digits, or hyphens",
+ "kind": "ErrorText",
+ "nodes": Array [
+ Object {
+ "kind": "Excerpt: ErrorText",
+ "nodeExcerpt": "[<]",
+ },
+ ],
+ },
+ Object {
+ "kind": "PlainText",
+ "nodes": Array [
+ Object {
+ "kind": "Excerpt: PlainText",
+ "nodeExcerpt": "a.a",
+ },
+ ],
+ },
+ Object {
+ "errorLocation": "[>]",
+ "errorLocationPrecedingToken": "a",
+ "errorMessage": "The [q][>][q] character should be escaped using a backslash to avoid confusion with an HTML tag",
+ "kind": "ErrorText",
+ "nodes": Array [
+ Object {
+ "kind": "Excerpt: ErrorText",
+ "nodeExcerpt": "[>]",
+ },
+ ],
+ },
+ Object {
+ "kind": "SoftBreak",
+ "nodes": Array [
+ Object {
+ "kind": "Excerpt: SoftBreak",
+ "nodeExcerpt": "[n]",
+ },
+ ],
+ },
+ Object {
+ "errorLocation": "_a",
+ "errorLocationPrecedingToken": "<",
+ "errorMessage": "Invalid HTML element: An HTML name must be an ASCII letter followed by zero or more letters, digits, or hyphens",
+ "kind": "ErrorText",
+ "nodes": Array [
+ Object {
+ "kind": "Excerpt: ErrorText",
+ "nodeExcerpt": "[<]",
+ },
+ ],
+ },
+ Object {
+ "kind": "PlainText",
+ "nodes": Array [
+ Object {
+ "kind": "Excerpt: PlainText",
+ "nodeExcerpt": "_a",
+ },
+ ],
+ },
+ Object {
+ "errorLocation": "[>]",
+ "errorLocationPrecedingToken": "_a",
+ "errorMessage": "The [q][>][q] character should be escaped using a backslash to avoid confusion with an HTML tag",
+ "kind": "ErrorText",
+ "nodes": Array [
+ Object {
+ "kind": "Excerpt: ErrorText",
+ "nodeExcerpt": "[>]",
+ },
+ ],
+ },
+ Object {
+ "kind": "SoftBreak",
+ "nodes": Array [
+ Object {
+ "kind": "Excerpt: SoftBreak",
+ "nodeExcerpt": "[n]",
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+}
+`;