Skip to content

Commit 725bcb3

Browse files
authored
feat: expose position / location / line internal apis (#125)
1 parent 18a377a commit 725bcb3

File tree

4 files changed

+66
-31
lines changed

4 files changed

+66
-31
lines changed

.changeset/proud-worms-unite.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"htmljs-parser": minor
3+
---
4+
5+
Expose some apis for generating position and location information.

src/core/Parser.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import {
66
Range,
77
ParserOptions as Options,
88
getLines,
9-
getLoc,
10-
getPos,
9+
getLocation,
10+
getPosition,
1111
ErrorCode,
1212
} from "../internal";
1313

@@ -53,12 +53,19 @@ export class Parser {
5353
return this.data.slice(range.start, range.end);
5454
}
5555

56-
positionAt(index: number) {
57-
return getPos(this.lines || (this.lines = getLines(this.data)), 0, index);
56+
positionAt(offset: number) {
57+
return getPosition(
58+
this.lines || (this.lines = getLines(this.data)),
59+
offset
60+
);
5861
}
5962

6063
locationAt(range: Range) {
61-
return getLoc(this.lines || (this.lines = getLines(this.data)), range);
64+
return getLocation(
65+
this.lines || (this.lines = getLines(this.data)),
66+
range.start,
67+
range.end
68+
);
6269
}
6370

6471
enterState<P extends Meta>(state: StateDefinition<P>): P {

src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import { type ParserOptions, type Range, Parser } from "./internal";
22
export {
33
TagType,
44
ErrorCode,
5+
getLines,
6+
getLocation,
7+
getPosition,
58
type ParserOptions as Handlers,
69
type Position,
710
type Location,

src/util/util.ts

Lines changed: 46 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { CODE, type Parser } from "../internal";
2-
import { ErrorCode, Location, Position, Range } from "./constants";
2+
import { ErrorCode, Location, Position } from "./constants";
33

44
export function isWhitespaceCode(code: number) {
55
// For all practical purposes, the space character (32) and all the
@@ -9,37 +9,33 @@ export function isWhitespaceCode(code: number) {
99
return code <= CODE.SPACE;
1010
}
1111

12-
export function getLoc(lines: number[], range: Range): Location {
13-
const start = getPos(lines, 0, range.start);
12+
/**
13+
* Given a source code line offsets, a start offset and an end offset, returns a Location object with line & character information for the start and end offsets.
14+
*/
15+
export function getLocation(
16+
lines: number[],
17+
startOffset: number,
18+
endOffset: number
19+
): Location {
20+
const start = getPosition(lines, startOffset);
1421
const end =
15-
range.start === range.end ? start : getPos(lines, start.line, range.end);
22+
startOffset === endOffset
23+
? start
24+
: getPosAfterLine(lines, start.line, endOffset);
1625
return { start, end };
1726
}
1827

19-
export function getPos(
20-
lines: number[],
21-
startLine: number,
22-
index: number
23-
): Position {
24-
let max = lines.length - 1;
25-
let line = startLine;
26-
27-
while (line < max) {
28-
const mid = (1 + line + max) >>> 1;
29-
30-
if (lines[mid] <= index) {
31-
line = mid;
32-
} else {
33-
max = mid - 1;
34-
}
35-
}
36-
37-
return {
38-
line,
39-
character: index - lines[line],
40-
};
28+
/**
29+
* Given a source code line offsets and an offset, returns a Position object with line & character information.
30+
*/
31+
export function getPosition(lines: number[], offset: number): Position {
32+
return getPosAfterLine(lines, 0, offset);
4133
}
4234

35+
/**
36+
* Scan through some source code and generate an array of offsets for each newline.
37+
* Useful for generating line/column information for source code.
38+
*/
4339
export function getLines(src: string) {
4440
const lines = [0];
4541
for (let i = 0; i < src.length; i++) {
@@ -71,3 +67,27 @@ export function htmlEOF(this: Parser) {
7167
}
7268
}
7369
}
70+
71+
function getPosAfterLine(
72+
lines: number[],
73+
startLine: number,
74+
index: number
75+
): Position {
76+
let max = lines.length - 1;
77+
let line = startLine;
78+
79+
while (line < max) {
80+
const mid = (1 + line + max) >>> 1;
81+
82+
if (lines[mid] <= index) {
83+
line = mid;
84+
} else {
85+
max = mid - 1;
86+
}
87+
}
88+
89+
return {
90+
line,
91+
character: index - lines[line],
92+
};
93+
}

0 commit comments

Comments
 (0)