@@ -7,14 +7,16 @@ var codes = require('micromark/lib/character/codes')
7
7
var constants = require ( 'micromark/lib/constant/constants' )
8
8
var types = require ( 'micromark/lib/constant/types' )
9
9
10
- var decode = require ( 'parse-entities/decode-entity' )
11
10
var toString = require ( 'mdast-util-to-string' )
11
+ var assign = require ( 'micromark/dist/constant/assign' )
12
12
var own = require ( 'micromark/dist/constant/has-own-property' )
13
13
var normalizeIdentifier = require ( 'micromark/dist/util/normalize-identifier' )
14
14
var safeFromInt = require ( 'micromark/dist/util/safe-from-int' )
15
15
var parser = require ( 'micromark/dist/parse' )
16
16
var preprocessor = require ( 'micromark/dist/preprocess' )
17
17
var postprocess = require ( 'micromark/dist/postprocess' )
18
+ var decode = require ( 'parse-entities/decode-entity' )
19
+ var stringifyPosition = require ( 'unist-util-stringify-position' )
18
20
19
21
function fromMarkdown ( value , encoding , options ) {
20
22
if ( typeof encoding !== 'string' ) {
@@ -144,13 +146,26 @@ function compiler(options) {
144
146
145
147
function compile ( events ) {
146
148
var stack = [ { type : 'root' , children : [ ] } ]
149
+ var tokenStack = [ ]
147
150
var index = - 1
148
151
var listStack = [ ]
149
152
var length
150
153
var handler
151
154
var listStart
152
155
var event
153
156
157
+ var context = {
158
+ stack : stack ,
159
+ tokenStack : tokenStack ,
160
+ config : config ,
161
+ enter : enter ,
162
+ exit : exit ,
163
+ buffer : buffer ,
164
+ resume : resume ,
165
+ setData : setData ,
166
+ getData : getData
167
+ }
168
+
154
169
while ( ++ index < events . length ) {
155
170
event = events [ index ]
156
171
@@ -177,22 +192,25 @@ function compiler(options) {
177
192
178
193
if ( own . call ( handler , events [ index ] [ 1 ] . type ) ) {
179
194
handler [ events [ index ] [ 1 ] . type ] . call (
180
- {
181
- stack : stack ,
182
- config : config ,
183
- enter : enter ,
184
- exit : exit ,
185
- buffer : buffer ,
186
- resume : resume ,
187
- sliceSerialize : events [ index ] [ 2 ] . sliceSerialize ,
188
- setData : setData ,
189
- getData : getData
190
- } ,
195
+ assign ( { sliceSerialize : events [ index ] [ 2 ] . sliceSerialize } , context ) ,
191
196
events [ index ] [ 1 ]
192
197
)
193
198
}
194
199
}
195
200
201
+ if ( tokenStack . length > 0 ) {
202
+ throw new Error (
203
+ 'Cannot close document, a token (`' +
204
+ tokenStack [ tokenStack . length - 1 ] . type +
205
+ '`, ' +
206
+ stringifyPosition ( {
207
+ start : tokenStack [ tokenStack . length - 1 ] . start ,
208
+ end : tokenStack [ tokenStack . length - 1 ] . end
209
+ } ) +
210
+ ') is still open'
211
+ )
212
+ }
213
+
196
214
// Figure out `root` position.
197
215
stack [ 0 ] . position = {
198
216
start : point (
@@ -367,6 +385,7 @@ function compiler(options) {
367
385
function enter ( node , token ) {
368
386
this . stack [ this . stack . length - 1 ] . children . push ( node )
369
387
this . stack . push ( node )
388
+ this . tokenStack . push ( token )
370
389
node . position = { start : point ( token . start ) }
371
390
return node
372
391
}
@@ -382,6 +401,30 @@ function compiler(options) {
382
401
383
402
function exit ( token ) {
384
403
var node = this . stack . pop ( )
404
+ var open = this . tokenStack . pop ( )
405
+
406
+ if ( ! open ) {
407
+ throw new Error (
408
+ 'Cannot close `' +
409
+ token . type +
410
+ '` (' +
411
+ stringifyPosition ( { start : token . start , end : token . end } ) +
412
+ '): it’s not open'
413
+ )
414
+ } else if ( open . type !== token . type ) {
415
+ throw new Error (
416
+ 'Cannot close `' +
417
+ token . type +
418
+ '` (' +
419
+ stringifyPosition ( { start : token . start , end : token . end } ) +
420
+ '): a different token (`' +
421
+ open . type +
422
+ '`, ' +
423
+ stringifyPosition ( { start : open . start , end : open . end } ) +
424
+ ') is open'
425
+ )
426
+ }
427
+
385
428
node . position . end = point ( token . end )
386
429
return node
387
430
}
0 commit comments