Skip to content

Commit 7d6f76b

Browse files
committed
Move location tracker to a separate file and refactor into class
1 parent 6faf50d commit 7d6f76b

File tree

4 files changed

+49
-36
lines changed

4 files changed

+49
-36
lines changed

Diff for: src/index.ts

+6-32
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {Parser, ParserOptions} from 'htmlparser2';
22
import {Directive, Node, NodeTag, Options, Attributes} from '../types/index.d';
3+
import {LocationTracker} from './location-tracker';
34

45
const defaultOptions: ParserOptions = {
56
lowerCaseTags: false,
@@ -16,6 +17,7 @@ const defaultDirectives: Directive[] = [
1617
];
1718

1819
const parser = (html: string, options: Options = {}): Node[] => {
20+
const locationTracker = new LocationTracker(html);
1921
const bufArray: Node[] = [];
2022
const results: Node[] = [];
2123

@@ -49,34 +51,6 @@ const parser = (html: string, options: Options = {}): Node[] => {
4951
return result;
5052
}
5153

52-
const lastLoc = {
53-
line: 1,
54-
column: 1
55-
};
56-
57-
let lastIndex = 0;
58-
function getLoc(index: number) {
59-
if (index < lastIndex) {
60-
throw new Error('Source indices must be monotonic');
61-
}
62-
63-
while (lastIndex < index) {
64-
if (html.charCodeAt(lastIndex) === /* \n */ 10) {
65-
lastLoc.line++;
66-
lastLoc.column = 1;
67-
} else {
68-
lastLoc.column++;
69-
}
70-
71-
lastIndex++;
72-
}
73-
74-
return {
75-
line: lastLoc.line,
76-
column: lastLoc.column
77-
};
78-
}
79-
8054
function onprocessinginstruction(name: string, data: string) {
8155
const directives = defaultDirectives.concat(options.directives ?? []);
8256
const last: Node = bufferArrayLast();
@@ -120,11 +94,11 @@ const parser = (html: string, options: Options = {}): Node[] => {
12094
}
12195

12296
function onopentag(tag: string, attrs: Attributes) {
123-
const start = getLoc(parser.startIndex);
97+
const start = locationTracker.getPosition(parser.startIndex);
12498
const buf: NodeTag = {tag};
12599

126100
if (options.sourceLocations) {
127-
buf.loc = {
101+
buf.location = {
128102
start,
129103
end: start
130104
};
@@ -140,8 +114,8 @@ const parser = (html: string, options: Options = {}): Node[] => {
140114
function onclosetag() {
141115
const buf: Node | undefined = bufArray.pop();
142116

143-
if (buf && typeof buf === 'object' && buf.loc && parser.endIndex !== null) {
144-
buf.loc.end = getLoc(parser.endIndex);
117+
if (buf && typeof buf === 'object' && buf.location && parser.endIndex !== null) {
118+
buf.location.end = locationTracker.getPosition(parser.endIndex);
145119
}
146120

147121
if (buf) {

Diff for: src/location-tracker.ts

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import {Position} from '../types/index.d';
2+
3+
export class LocationTracker {
4+
private readonly source: string;
5+
private lastPosition: Position;
6+
private lastIndex: number;
7+
8+
constructor(source: string) {
9+
this.source = source;
10+
this.lastPosition = {
11+
line: 1,
12+
column: 1
13+
};
14+
15+
this.lastIndex = 0;
16+
}
17+
18+
getPosition(index: number): Position {
19+
if (index < this.lastIndex) {
20+
throw new Error('Source indices must be monotonic');
21+
}
22+
23+
while (this.lastIndex < index) {
24+
if (this.source.charCodeAt(this.lastIndex) === /* \n */ 10) {
25+
this.lastPosition.line++;
26+
this.lastPosition.column = 1;
27+
} else {
28+
this.lastPosition.column++;
29+
}
30+
31+
this.lastIndex++;
32+
}
33+
34+
return {
35+
line: this.lastPosition.line,
36+
column: this.lastPosition.column
37+
};
38+
}
39+
}

Diff for: test/test-core.spec.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ test('should parse with source locations', t => {
248248
{
249249
tag: 'h1',
250250
content: ['Test'],
251-
loc: {
251+
location: {
252252
start: {
253253
line: 1,
254254
column: 1
@@ -266,7 +266,7 @@ test('should parse with source locations', t => {
266266
{
267267
tag: 'b',
268268
content: ['Foo'],
269-
loc: {
269+
location: {
270270
start: {
271271
line: 2,
272272
column: 4
@@ -278,7 +278,7 @@ test('should parse with source locations', t => {
278278
}
279279
}
280280
],
281-
loc: {
281+
location: {
282282
start: {
283283
line: 2,
284284
column: 1

Diff for: types/index.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export type NodeTag = {
2121
tag?: string | boolean;
2222
attrs?: Attributes;
2323
content?: Node[];
24-
loc?: SourceLocation;
24+
location?: SourceLocation;
2525
};
2626

2727
export type Attributes = Record<string, string>;

0 commit comments

Comments
 (0)