Skip to content

Commit a9de039

Browse files
authored
feat: raise error for missing closing token (#31)
1 parent 7d1dd41 commit a9de039

File tree

5 files changed

+47
-1
lines changed

5 files changed

+47
-1
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<html
2+
<head>
3+
</head>
4+
</html>

src/tokenizer/__tests__/tokenize.spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,4 +193,16 @@ describe("tokenize", () => {
193193
expect(tokens).toEqual(output);
194194
}
195195
);
196+
197+
it("parsing error", () => {
198+
const html = fs.readFileSync(
199+
path.join(__dirname, "__input__", "parsing-error-no-open-end.html"),
200+
"utf-8"
201+
);
202+
expect(() =>
203+
tokenize(html, defaultTokenAdapter)
204+
).toThrowErrorMatchingInlineSnapshot(
205+
`"Unexpected end of tag. Expected '>' to close the opening tag. (2:2)"`
206+
);
207+
});
196208
});

src/tokenizer/handlers/attributes.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { TokenizerContextTypes, TokenTypes } from "../../constants";
2-
import { calculateTokenPosition, isWhitespace } from "../../utils";
2+
import { calculateTokenPosition, isWhitespace, raise } from "../../utils";
33
import type { TokenizerState } from "../../types";
44
import { CharsBuffer } from "../chars-buffer";
55

@@ -33,6 +33,12 @@ function parseTagEnd(state: TokenizerState) {
3333
}
3434

3535
function parseNoneWhitespace(chars: CharsBuffer, state: TokenizerState) {
36+
if (chars.value() === "<") {
37+
raise(
38+
calculateTokenPosition(state, { keepBuffer: true }),
39+
"Unexpected end of tag. Expected '>' to close the opening tag."
40+
);
41+
}
3642
state.accumulatedContent.replace(state.decisionBuffer);
3743
state.currentContext = TokenizerContextTypes.AttributeKey;
3844
state.sourceCode.next();

src/utils/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ export * from "./first";
1414
export * from "./clone-location";
1515
export * from "./init-if-none";
1616
export * from "./templates";
17+
export * from "./raise";

src/utils/raise.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Range } from "../types";
2+
import { SourceLocation } from "../types/source-location";
3+
4+
export function raise(
5+
position: {
6+
loc: SourceLocation;
7+
range: Range;
8+
},
9+
message: string
10+
): never {
11+
const errorMessage =
12+
message +
13+
" (" +
14+
position.loc.start.line +
15+
":" +
16+
position.loc.start.column +
17+
")";
18+
const error: any = new SyntaxError(errorMessage);
19+
error.pos = position.range[0];
20+
error.loc = position.loc;
21+
error.raiseAt = position.range[0];
22+
throw error;
23+
}

0 commit comments

Comments
 (0)