1
1
import { Parser , ParserOptions } from 'htmlparser2' ;
2
- import { Directive , Node , NodeTag , Options , Attributes } from '../types/index.d' ;
3
2
import { LocationTracker } from './location-tracker' ;
4
3
4
+ export type Directive = {
5
+ name : string | RegExp ;
6
+ start : string ;
7
+ end : string ;
8
+ } ;
9
+
10
+ export type Options = {
11
+ directives ?: Directive [ ] ;
12
+ sourceLocations ?: boolean ;
13
+ } & ParserOptions ;
14
+
15
+ export type Tag = string | boolean ;
16
+ export type Attributes = Record < string , string | number | boolean > ;
17
+ // export type Content = NodeText | Node[] | Node[][];
18
+ export type Content = NodeText | ( Node | Node [ ] ) [ ] ;
19
+
20
+ export type NodeText = string | number ;
21
+ export type NodeTag = {
22
+ tag ?: Tag ;
23
+ attrs ?: Attributes ;
24
+ content ?: Content ;
25
+ location ?: SourceLocation ;
26
+ } ;
27
+
28
+ export type Node = NodeText | NodeTag ;
29
+
30
+ export type SourceLocation = {
31
+ start : Position ;
32
+ end : Position ;
33
+ } ;
34
+
35
+ export type Position = {
36
+ line : number ;
37
+ column : number ;
38
+ } ;
39
+
5
40
const defaultOptions : ParserOptions = {
6
41
lowerCaseTags : false ,
7
42
lowerCaseAttributeNames : false ,
@@ -25,6 +60,25 @@ const parser = (html: string, options: Options = {}): Node[] => {
25
60
return bufArray [ bufArray . length - 1 ] ;
26
61
}
27
62
63
+ function resolveContent ( text : NodeText ) : void {
64
+ const last = bufferArrayLast ( ) ;
65
+
66
+ if ( last === undefined ) {
67
+ results . push ( text ) ;
68
+ return ;
69
+ }
70
+
71
+ if ( typeof last === 'object' ) {
72
+ if ( last . content === undefined ) {
73
+ last . content = [ ] ;
74
+ }
75
+
76
+ if ( Array . isArray ( last . content ) ) {
77
+ last . content . push ( text ) ;
78
+ }
79
+ }
80
+ }
81
+
28
82
function isDirective ( directive : Directive , tag : string ) : boolean {
29
83
if ( directive . name instanceof RegExp ) {
30
84
const regex = new RegExp ( directive . name . source , 'i' ) ;
@@ -53,44 +107,20 @@ const parser = (html: string, options: Options = {}): Node[] => {
53
107
54
108
function onprocessinginstruction ( name : string , data : string ) {
55
109
const directives = defaultDirectives . concat ( options . directives ?? [ ] ) ;
56
- const last : Node = bufferArrayLast ( ) ;
57
110
58
111
for ( const directive of directives ) {
59
112
const directiveText = directive . start + data + directive . end ;
60
113
61
114
if ( isDirective ( directive , name . toLowerCase ( ) ) ) {
62
- if ( last === undefined ) {
63
- results . push ( directiveText ) ;
64
- return ;
65
- }
66
-
67
- if ( typeof last === 'object' ) {
68
- if ( last . content === undefined ) {
69
- last . content = [ ] ;
70
- }
71
-
72
- last . content . push ( directiveText ) ;
73
- }
115
+ resolveContent ( directiveText ) ;
74
116
}
75
117
}
76
118
}
77
119
78
120
function oncomment ( data : string ) {
79
121
const comment = `<!--${ data } -->` ;
80
- const last = bufferArrayLast ( ) ;
81
-
82
- if ( last === undefined ) {
83
- results . push ( comment ) ;
84
- return ;
85
- }
86
122
87
- if ( typeof last === 'object' ) {
88
- if ( last . content === undefined ) {
89
- last . content = [ ] ;
90
- }
91
-
92
- last . content . push ( comment ) ;
93
- }
123
+ resolveContent ( comment ) ;
94
124
}
95
125
96
126
function onopentag ( tag : string , attrs : Attributes ) {
@@ -131,7 +161,9 @@ const parser = (html: string, options: Options = {}): Node[] => {
131
161
last . content = [ ] ;
132
162
}
133
163
134
- last . content . push ( buf ) ;
164
+ if ( Array . isArray ( last . content ) ) {
165
+ last . content . push ( buf ) ;
166
+ }
135
167
}
136
168
}
137
169
}
@@ -145,7 +177,7 @@ const parser = (html: string, options: Options = {}): Node[] => {
145
177
}
146
178
147
179
if ( typeof last === 'object' ) {
148
- if ( last . content && last . content . length > 0 ) {
180
+ if ( last . content && Array . isArray ( last . content ) && last . content . length > 0 ) {
149
181
const lastContentNode = last . content [ last . content . length - 1 ] ;
150
182
if ( typeof lastContentNode === 'string' && ! lastContentNode . startsWith ( '<!--' ) ) {
151
183
last . content [ last . content . length - 1 ] = `${ lastContentNode } ${ text } ` ;
@@ -156,8 +188,9 @@ const parser = (html: string, options: Options = {}): Node[] => {
156
188
if ( last . content === undefined ) {
157
189
last . content = [ ] ;
158
190
}
159
-
160
- last . content . push ( text ) ;
191
+ if ( Array . isArray ( last . content ) ) {
192
+ last . content . push ( text ) ;
193
+ }
161
194
}
162
195
}
163
196
0 commit comments