Improve _htmlNameRegExp() to follow the CommonMark spec

This commit is contained in:
Pete Gonzalez 2020-03-27 14:58:58 -07:00
Родитель e774c713a3
Коммит eba7fa9d3a
3 изменённых файлов: 184 добавлений и 36 удалений

Просмотреть файл

@ -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][\-.0-9_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;

Просмотреть файл

@ -108,13 +108,22 @@ test('07 Closing tags, negative', () => {
].join('\n'));
});
test('08 Unusual element names', () => {
test('08 Unusual HTML names, positive', () => {
TestHelpers.parseAndMatchNodeParserSnapshot([
'/**',
' * <a1/>',
' * <a-a>',
' * <a--a>',
' * <a.2>',
' * <a--9->',
' */'
].join('\n'));
});
test('09 Unusual HTML names, negative', () => {
TestHelpers.parseAndMatchNodeParserSnapshot([
'/**',
' * <1a/>',
' * <a.a>',
' * <_a>',
' */'
].join('\n'));
});

Просмотреть файл

@ -1702,15 +1702,14 @@ Object {
}
`;
exports[`08 Unusual element names 1`] = `
exports[`08 Unusual HTML names, positive 1`] = `
Object {
"buffer": "/**[n] * [<]a1/[>][n] * [<]a-a[>][n] * [<]a--a[>][n] * [<]a.2[>][n] */",
"buffer": "/**[n] * [<]a1/[>][n] * [<]a-a[>][n] * [<]a--9-[>][n] */",
"gaps": Array [],
"lines": Array [
"[<]a1/[>]",
"[<]a-a[>]",
"[<]a--a[>]",
"[<]a.2[>]",
"[<]a--9-[>]",
],
"logMessages": Array [],
"nodes": Object {
@ -1783,33 +1782,7 @@ Object {
},
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.2",
"nodeExcerpt": "a--9-",
},
Object {
"kind": "Excerpt: HtmlStartTag_ClosingDelimiter",
@ -1834,3 +1807,164 @@ Object {
},
}
`;
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]",
},
],
},
],
},
],
},
],
},
}
`;