chore: more restructuring
This commit is contained in:
parent
16fa44bd57
commit
ca387afeea
@ -77,11 +77,6 @@ function createParserContext(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCursor(context: ParserContext): Position {
|
|
||||||
const { column, line, offset } = context
|
|
||||||
return { column, line, offset }
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseChildren(
|
function parseChildren(
|
||||||
context: ParserContext,
|
context: ParserContext,
|
||||||
mode: TextModes,
|
mode: TextModes,
|
||||||
@ -172,134 +167,6 @@ function parseChildren(
|
|||||||
return nodes
|
return nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSelection(
|
|
||||||
context: ParserContext,
|
|
||||||
start: Position,
|
|
||||||
end?: Position
|
|
||||||
): SourceLocation {
|
|
||||||
end = end || getCursor(context)
|
|
||||||
return {
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
source: context.originalSource.slice(start.offset, end.offset)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function last<T>(xs: T[]): T | undefined {
|
|
||||||
return xs[xs.length - 1]
|
|
||||||
}
|
|
||||||
|
|
||||||
function startsWith(source: string, searchString: string): boolean {
|
|
||||||
return source.startsWith(searchString)
|
|
||||||
}
|
|
||||||
|
|
||||||
function advanceBy(context: ParserContext, numberOfCharacters: number): void {
|
|
||||||
__DEV__ && assert(numberOfCharacters <= context.source.length)
|
|
||||||
|
|
||||||
const { column, source } = context
|
|
||||||
const str = source.slice(0, numberOfCharacters)
|
|
||||||
const lines = str.split(/\r?\n/)
|
|
||||||
|
|
||||||
context.source = source.slice(numberOfCharacters)
|
|
||||||
context.offset += numberOfCharacters
|
|
||||||
context.line += lines.length - 1
|
|
||||||
context.column =
|
|
||||||
lines.length === 1
|
|
||||||
? column + numberOfCharacters
|
|
||||||
: Math.max(1, lines.pop()!.length)
|
|
||||||
}
|
|
||||||
|
|
||||||
function advanceSpaces(context: ParserContext): void {
|
|
||||||
const match = /^[\t\r\n\f ]+/.exec(context.source)
|
|
||||||
if (match) {
|
|
||||||
advanceBy(context, match[0].length)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNewPosition(
|
|
||||||
context: ParserContext,
|
|
||||||
start: Position,
|
|
||||||
numberOfCharacters: number
|
|
||||||
): Position {
|
|
||||||
const { originalSource } = context
|
|
||||||
const str = originalSource.slice(start.offset, numberOfCharacters)
|
|
||||||
const lines = str.split(/\r?\n/)
|
|
||||||
|
|
||||||
const newPosition = {
|
|
||||||
column: start.column,
|
|
||||||
line: start.line,
|
|
||||||
offset: start.offset
|
|
||||||
}
|
|
||||||
|
|
||||||
newPosition.offset += numberOfCharacters
|
|
||||||
newPosition.line += lines.length - 1
|
|
||||||
newPosition.column =
|
|
||||||
lines.length === 1
|
|
||||||
? start.column + numberOfCharacters
|
|
||||||
: Math.max(1, lines.pop()!.length)
|
|
||||||
|
|
||||||
return newPosition
|
|
||||||
}
|
|
||||||
|
|
||||||
function emitError(
|
|
||||||
context: ParserContext,
|
|
||||||
type: ParserErrorTypes,
|
|
||||||
offset?: number
|
|
||||||
): void {
|
|
||||||
const loc = getCursor(context)
|
|
||||||
if (offset) {
|
|
||||||
loc.offset += offset
|
|
||||||
loc.column += offset
|
|
||||||
}
|
|
||||||
context.onError(type, loc)
|
|
||||||
}
|
|
||||||
|
|
||||||
function isEnd(
|
|
||||||
context: ParserContext,
|
|
||||||
mode: TextModes,
|
|
||||||
ancestors: ElementNode[]
|
|
||||||
): boolean {
|
|
||||||
const s = context.source
|
|
||||||
|
|
||||||
switch (mode) {
|
|
||||||
case TextModes.DATA:
|
|
||||||
if (startsWith(s, '</')) {
|
|
||||||
//TODO: probably bad performance
|
|
||||||
for (let i = ancestors.length - 1; i >= 0; --i) {
|
|
||||||
if (startsWithEndTagOpen(s, ancestors[i].tag)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
|
|
||||||
case TextModes.RCDATA:
|
|
||||||
case TextModes.RAWTEXT: {
|
|
||||||
const parent = last(ancestors)
|
|
||||||
if (parent && startsWithEndTagOpen(s, parent.tag)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
case TextModes.CDATA:
|
|
||||||
if (startsWith(s, ']]>')) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
return !s
|
|
||||||
}
|
|
||||||
|
|
||||||
function startsWithEndTagOpen(source: string, tag: string): boolean {
|
|
||||||
return (
|
|
||||||
startsWith(source, '</') &&
|
|
||||||
source.substr(2, tag.length).toLowerCase() === tag.toLowerCase() &&
|
|
||||||
/[\t\n\f />]/.test(source[2 + tag.length] || '>')
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function pushNode(
|
function pushNode(
|
||||||
context: ParserContext,
|
context: ParserContext,
|
||||||
nodes: RootNode['children'],
|
nodes: RootNode['children'],
|
||||||
@ -887,6 +754,145 @@ function parseTextData(
|
|||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getCursor(context: ParserContext): Position {
|
||||||
|
const { column, line, offset } = context
|
||||||
|
return { column, line, offset }
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSelection(
|
||||||
|
context: ParserContext,
|
||||||
|
start: Position,
|
||||||
|
end?: Position
|
||||||
|
): SourceLocation {
|
||||||
|
end = end || getCursor(context)
|
||||||
|
return {
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
source: context.originalSource.slice(start.offset, end.offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function last<T>(xs: T[]): T | undefined {
|
||||||
|
return xs[xs.length - 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
function startsWith(source: string, searchString: string): boolean {
|
||||||
|
return source.startsWith(searchString)
|
||||||
|
}
|
||||||
|
|
||||||
|
function advanceBy(context: ParserContext, numberOfCharacters: number): void {
|
||||||
|
__DEV__ && assert(numberOfCharacters <= context.source.length)
|
||||||
|
|
||||||
|
const { column, source } = context
|
||||||
|
const str = source.slice(0, numberOfCharacters)
|
||||||
|
const lines = str.split(/\r?\n/)
|
||||||
|
|
||||||
|
context.source = source.slice(numberOfCharacters)
|
||||||
|
context.offset += numberOfCharacters
|
||||||
|
context.line += lines.length - 1
|
||||||
|
context.column =
|
||||||
|
lines.length === 1
|
||||||
|
? column + numberOfCharacters
|
||||||
|
: Math.max(1, lines.pop()!.length)
|
||||||
|
}
|
||||||
|
|
||||||
|
function advanceSpaces(context: ParserContext): void {
|
||||||
|
const match = /^[\t\r\n\f ]+/.exec(context.source)
|
||||||
|
if (match) {
|
||||||
|
advanceBy(context, match[0].length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNewPosition(
|
||||||
|
context: ParserContext,
|
||||||
|
start: Position,
|
||||||
|
numberOfCharacters: number
|
||||||
|
): Position {
|
||||||
|
const { originalSource } = context
|
||||||
|
const str = originalSource.slice(start.offset, numberOfCharacters)
|
||||||
|
const lines = str.split(/\r?\n/)
|
||||||
|
|
||||||
|
const newPosition = {
|
||||||
|
column: start.column,
|
||||||
|
line: start.line,
|
||||||
|
offset: start.offset
|
||||||
|
}
|
||||||
|
|
||||||
|
newPosition.offset += numberOfCharacters
|
||||||
|
newPosition.line += lines.length - 1
|
||||||
|
newPosition.column =
|
||||||
|
lines.length === 1
|
||||||
|
? start.column + numberOfCharacters
|
||||||
|
: Math.max(1, lines.pop()!.length)
|
||||||
|
|
||||||
|
return newPosition
|
||||||
|
}
|
||||||
|
|
||||||
|
function emitError(
|
||||||
|
context: ParserContext,
|
||||||
|
type: ParserErrorTypes,
|
||||||
|
offset?: number
|
||||||
|
): void {
|
||||||
|
const loc = getCursor(context)
|
||||||
|
if (offset) {
|
||||||
|
loc.offset += offset
|
||||||
|
loc.column += offset
|
||||||
|
}
|
||||||
|
context.onError(type, loc)
|
||||||
|
}
|
||||||
|
|
||||||
|
function isEnd(
|
||||||
|
context: ParserContext,
|
||||||
|
mode: TextModes,
|
||||||
|
ancestors: ElementNode[]
|
||||||
|
): boolean {
|
||||||
|
const s = context.source
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case TextModes.DATA:
|
||||||
|
if (startsWith(s, '</')) {
|
||||||
|
//TODO: probably bad performance
|
||||||
|
for (let i = ancestors.length - 1; i >= 0; --i) {
|
||||||
|
if (startsWithEndTagOpen(s, ancestors[i].tag)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
|
||||||
|
case TextModes.RCDATA:
|
||||||
|
case TextModes.RAWTEXT: {
|
||||||
|
const parent = last(ancestors)
|
||||||
|
if (parent && startsWithEndTagOpen(s, parent.tag)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
case TextModes.CDATA:
|
||||||
|
if (startsWith(s, ']]>')) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return !s
|
||||||
|
}
|
||||||
|
|
||||||
|
function startsWithEndTagOpen(source: string, tag: string): boolean {
|
||||||
|
return (
|
||||||
|
startsWith(source, '</') &&
|
||||||
|
source.substr(2, tag.length).toLowerCase() === tag.toLowerCase() &&
|
||||||
|
/[\t\n\f />]/.test(source[2 + tag.length] || '>')
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function assert(condition: boolean, msg?: string) {
|
||||||
|
if (!condition) {
|
||||||
|
throw new Error(msg || `unexpected parser condition`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state
|
// https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state
|
||||||
const CCR_REPLACEMENTS: { [key: number]: number | undefined } = {
|
const CCR_REPLACEMENTS: { [key: number]: number | undefined } = {
|
||||||
0x80: 0x20ac,
|
0x80: 0x20ac,
|
||||||
@ -917,9 +923,3 @@ const CCR_REPLACEMENTS: { [key: number]: number | undefined } = {
|
|||||||
0x9e: 0x017e,
|
0x9e: 0x017e,
|
||||||
0x9f: 0x0178
|
0x9f: 0x0178
|
||||||
}
|
}
|
||||||
|
|
||||||
function assert(condition: boolean, msg?: string) {
|
|
||||||
if (!condition) {
|
|
||||||
throw new Error(msg || `unexpected parser condition`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -35,3 +35,55 @@ export const enum ParserErrorTypes {
|
|||||||
X_MISSING_INTERPOLATION_END,
|
X_MISSING_INTERPOLATION_END,
|
||||||
X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END
|
X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const errorMessages: { [code: number]: string } = {
|
||||||
|
[ParserErrorTypes.ABRUPT_CLOSING_OF_EMPTY_COMMENT]: 'Illegal comment.',
|
||||||
|
[ParserErrorTypes.ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE]:
|
||||||
|
'Illegal numeric character reference: invalid character.',
|
||||||
|
[ParserErrorTypes.CDATA_IN_HTML_CONTENT]:
|
||||||
|
'CDATA section is allowed only in XML context.',
|
||||||
|
[ParserErrorTypes.CHARACTER_REFERENCE_OUTSIDE_UNICODE_RANGE]:
|
||||||
|
'Illegal numeric character reference: too big.',
|
||||||
|
[ParserErrorTypes.CONTROL_CHARACTER_REFERENCE]:
|
||||||
|
'Illegal numeric character reference: control character.',
|
||||||
|
[ParserErrorTypes.DUPLICATE_ATTRIBUTE]: 'Duplicate attribute.',
|
||||||
|
[ParserErrorTypes.END_TAG_WITH_ATTRIBUTES]: 'End tag cannot have attributes.',
|
||||||
|
[ParserErrorTypes.END_TAG_WITH_TRAILING_SOLIDUS]: "Illegal '/' in tags.",
|
||||||
|
[ParserErrorTypes.EOF_BEFORE_TAG_NAME]: 'Unexpected EOF in tag.',
|
||||||
|
[ParserErrorTypes.EOF_IN_CDATA]: 'Unexpected EOF in CDATA section.',
|
||||||
|
[ParserErrorTypes.EOF_IN_COMMENT]: 'Unexpected EOF in comment.',
|
||||||
|
[ParserErrorTypes.EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT]:
|
||||||
|
'Unexpected EOF in script.',
|
||||||
|
[ParserErrorTypes.EOF_IN_TAG]: 'Unexpected EOF in tag.',
|
||||||
|
[ParserErrorTypes.INCORRECTLY_CLOSED_COMMENT]: 'Incorrectly closed comment.',
|
||||||
|
[ParserErrorTypes.INCORRECTLY_OPENED_COMMENT]: 'Incorrectly opened comment.',
|
||||||
|
[ParserErrorTypes.INVALID_FIRST_CHARACTER_OF_TAG_NAME]:
|
||||||
|
"Illegal tag name. Use '<' to print '<'.",
|
||||||
|
[ParserErrorTypes.MISSING_ATTRIBUTE_VALUE]: 'Attribute value was expected.',
|
||||||
|
[ParserErrorTypes.MISSING_END_TAG_NAME]: 'End tag name was expected.',
|
||||||
|
[ParserErrorTypes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE]:
|
||||||
|
'Semicolon was expected.',
|
||||||
|
[ParserErrorTypes.MISSING_WHITESPACE_BETWEEN_ATTRIBUTES]:
|
||||||
|
'Whitespace was expected.',
|
||||||
|
[ParserErrorTypes.NESTED_COMMENT]: "Unexpected '<!--' in comment.",
|
||||||
|
[ParserErrorTypes.NONCHARACTER_CHARACTER_REFERENCE]:
|
||||||
|
'Illegal numeric character reference: non character.',
|
||||||
|
[ParserErrorTypes.NULL_CHARACTER_REFERENCE]:
|
||||||
|
'Illegal numeric character reference: null character.',
|
||||||
|
[ParserErrorTypes.SURROGATE_CHARACTER_REFERENCE]:
|
||||||
|
'Illegal numeric character reference: non-pair surrogate.',
|
||||||
|
[ParserErrorTypes.UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME]:
|
||||||
|
'Attribute name cannot contain U+0022 ("), U+0027 (\'), and U+003C (<).',
|
||||||
|
[ParserErrorTypes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE]:
|
||||||
|
'Unquoted attribute value cannot contain U+0022 ("), U+0027 (\'), U+003C (<), U+003D (=), and U+0060 (`).',
|
||||||
|
[ParserErrorTypes.UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME]:
|
||||||
|
"Attribute name cannot start with '='.",
|
||||||
|
[ParserErrorTypes.UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME]:
|
||||||
|
"'<?' is allowed only in XML context.",
|
||||||
|
[ParserErrorTypes.UNEXPECTED_SOLIDUS_IN_TAG]: "Illegal '/' in tags.",
|
||||||
|
[ParserErrorTypes.UNKNOWN_NAMED_CHARACTER_REFERENCE]: 'Unknown entity name.',
|
||||||
|
[ParserErrorTypes.X_INVALID_END_TAG]: 'Invalid end tag.',
|
||||||
|
[ParserErrorTypes.X_MISSING_END_TAG]: 'End tag was not found.',
|
||||||
|
[ParserErrorTypes.X_MISSING_INTERPOLATION_END]:
|
||||||
|
'Interpolation end sign was not found.'
|
||||||
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { TextModes, ParserOptions } from './parser'
|
import { TextModes, ParserOptions } from './parser'
|
||||||
import { ElementNode, Namespaces, Position, Node } from './ast'
|
import { ElementNode, Namespaces, Position, Node } from './ast'
|
||||||
import { ParserErrorTypes } from './parserErrorTypes'
|
import { ParserErrorTypes, errorMessages } from './parserErrorTypes'
|
||||||
|
|
||||||
export const parserOptionsMinimal: ParserOptions = {
|
export const parserOptionsMinimal: ParserOptions = {
|
||||||
delimiters: [`{{`, `}}`],
|
delimiters: [`{{`, `}}`],
|
||||||
@ -47,7 +47,7 @@ export const parserOptionsMinimal: ParserOptions = {
|
|||||||
|
|
||||||
onError(code: ParserErrorTypes, loc: Position): void {
|
onError(code: ParserErrorTypes, loc: Position): void {
|
||||||
const error: any = new SyntaxError(
|
const error: any = new SyntaxError(
|
||||||
`${messages[code]} (${loc.line}:${loc.column})`
|
`${errorMessages[code]} (${loc.line}:${loc.column})`
|
||||||
)
|
)
|
||||||
error.code = code
|
error.code = code
|
||||||
error.loc = loc
|
error.loc = loc
|
||||||
@ -58,55 +58,3 @@ export const parserOptionsMinimal: ParserOptions = {
|
|||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const messages: { [code: number]: string } = {
|
|
||||||
[ParserErrorTypes.ABRUPT_CLOSING_OF_EMPTY_COMMENT]: 'Illegal comment.',
|
|
||||||
[ParserErrorTypes.ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE]:
|
|
||||||
'Illegal numeric character reference: invalid character.',
|
|
||||||
[ParserErrorTypes.CDATA_IN_HTML_CONTENT]:
|
|
||||||
'CDATA section is allowed only in XML context.',
|
|
||||||
[ParserErrorTypes.CHARACTER_REFERENCE_OUTSIDE_UNICODE_RANGE]:
|
|
||||||
'Illegal numeric character reference: too big.',
|
|
||||||
[ParserErrorTypes.CONTROL_CHARACTER_REFERENCE]:
|
|
||||||
'Illegal numeric character reference: control character.',
|
|
||||||
[ParserErrorTypes.DUPLICATE_ATTRIBUTE]: 'Duplicate attribute.',
|
|
||||||
[ParserErrorTypes.END_TAG_WITH_ATTRIBUTES]: 'End tag cannot have attributes.',
|
|
||||||
[ParserErrorTypes.END_TAG_WITH_TRAILING_SOLIDUS]: "Illegal '/' in tags.",
|
|
||||||
[ParserErrorTypes.EOF_BEFORE_TAG_NAME]: 'Unexpected EOF in tag.',
|
|
||||||
[ParserErrorTypes.EOF_IN_CDATA]: 'Unexpected EOF in CDATA section.',
|
|
||||||
[ParserErrorTypes.EOF_IN_COMMENT]: 'Unexpected EOF in comment.',
|
|
||||||
[ParserErrorTypes.EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT]:
|
|
||||||
'Unexpected EOF in script.',
|
|
||||||
[ParserErrorTypes.EOF_IN_TAG]: 'Unexpected EOF in tag.',
|
|
||||||
[ParserErrorTypes.INCORRECTLY_CLOSED_COMMENT]: 'Incorrectly closed comment.',
|
|
||||||
[ParserErrorTypes.INCORRECTLY_OPENED_COMMENT]: 'Incorrectly opened comment.',
|
|
||||||
[ParserErrorTypes.INVALID_FIRST_CHARACTER_OF_TAG_NAME]:
|
|
||||||
"Illegal tag name. Use '<' to print '<'.",
|
|
||||||
[ParserErrorTypes.MISSING_ATTRIBUTE_VALUE]: 'Attribute value was expected.',
|
|
||||||
[ParserErrorTypes.MISSING_END_TAG_NAME]: 'End tag name was expected.',
|
|
||||||
[ParserErrorTypes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE]:
|
|
||||||
'Semicolon was expected.',
|
|
||||||
[ParserErrorTypes.MISSING_WHITESPACE_BETWEEN_ATTRIBUTES]:
|
|
||||||
'Whitespace was expected.',
|
|
||||||
[ParserErrorTypes.NESTED_COMMENT]: "Unexpected '<!--' in comment.",
|
|
||||||
[ParserErrorTypes.NONCHARACTER_CHARACTER_REFERENCE]:
|
|
||||||
'Illegal numeric character reference: non character.',
|
|
||||||
[ParserErrorTypes.NULL_CHARACTER_REFERENCE]:
|
|
||||||
'Illegal numeric character reference: null character.',
|
|
||||||
[ParserErrorTypes.SURROGATE_CHARACTER_REFERENCE]:
|
|
||||||
'Illegal numeric character reference: non-pair surrogate.',
|
|
||||||
[ParserErrorTypes.UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME]:
|
|
||||||
'Attribute name cannot contain U+0022 ("), U+0027 (\'), and U+003C (<).',
|
|
||||||
[ParserErrorTypes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE]:
|
|
||||||
'Unquoted attribute value cannot contain U+0022 ("), U+0027 (\'), U+003C (<), U+003D (=), and U+0060 (`).',
|
|
||||||
[ParserErrorTypes.UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME]:
|
|
||||||
"Attribute name cannot start with '='.",
|
|
||||||
[ParserErrorTypes.UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME]:
|
|
||||||
"'<?' is allowed only in XML context.",
|
|
||||||
[ParserErrorTypes.UNEXPECTED_SOLIDUS_IN_TAG]: "Illegal '/' in tags.",
|
|
||||||
[ParserErrorTypes.UNKNOWN_NAMED_CHARACTER_REFERENCE]: 'Unknown entity name.',
|
|
||||||
[ParserErrorTypes.X_INVALID_END_TAG]: 'Invalid end tag.',
|
|
||||||
[ParserErrorTypes.X_MISSING_END_TAG]: 'End tag was not found.',
|
|
||||||
[ParserErrorTypes.X_MISSING_INTERPOLATION_END]:
|
|
||||||
'Interpolation end sign was not found.'
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user