Improve _htmlNameRegExp() to follow the CommonMark spec
This commit is contained in:
Родитель
e774c713a3
Коммит
eba7fa9d3a
|
@ -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]",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
|
Загрузка…
Ссылка в новой задаче