@@ -7,14 +7,16 @@ var codes = require('micromark/lib/character/codes')
77var constants = require ( 'micromark/lib/constant/constants' )
88var types = require ( 'micromark/lib/constant/types' )
99
10- var decode = require ( 'parse-entities/decode-entity' )
1110var toString = require ( 'mdast-util-to-string' )
11+ var assign = require ( 'micromark/dist/constant/assign' )
1212var own = require ( 'micromark/dist/constant/has-own-property' )
1313var normalizeIdentifier = require ( 'micromark/dist/util/normalize-identifier' )
1414var safeFromInt = require ( 'micromark/dist/util/safe-from-int' )
1515var parser = require ( 'micromark/dist/parse' )
1616var preprocessor = require ( 'micromark/dist/preprocess' )
1717var postprocess = require ( 'micromark/dist/postprocess' )
18+ var decode = require ( 'parse-entities/decode-entity' )
19+ var stringifyPosition = require ( 'unist-util-stringify-position' )
1820
1921function fromMarkdown ( value , encoding , options ) {
2022 if ( typeof encoding !== 'string' ) {
@@ -144,13 +146,26 @@ function compiler(options) {
144146
145147 function compile ( events ) {
146148 var stack = [ { type : 'root' , children : [ ] } ]
149+ var tokenStack = [ ]
147150 var index = - 1
148151 var listStack = [ ]
149152 var length
150153 var handler
151154 var listStart
152155 var event
153156
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+
154169 while ( ++ index < events . length ) {
155170 event = events [ index ]
156171
@@ -177,22 +192,25 @@ function compiler(options) {
177192
178193 if ( own . call ( handler , events [ index ] [ 1 ] . type ) ) {
179194 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 ) ,
191196 events [ index ] [ 1 ]
192197 )
193198 }
194199 }
195200
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+
196214 // Figure out `root` position.
197215 stack [ 0 ] . position = {
198216 start : point (
@@ -367,6 +385,7 @@ function compiler(options) {
367385 function enter ( node , token ) {
368386 this . stack [ this . stack . length - 1 ] . children . push ( node )
369387 this . stack . push ( node )
388+ this . tokenStack . push ( token )
370389 node . position = { start : point ( token . start ) }
371390 return node
372391 }
@@ -382,6 +401,30 @@ function compiler(options) {
382401
383402 function exit ( token ) {
384403 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+
385428 node . position . end = point ( token . end )
386429 return node
387430 }
0 commit comments