@@ -73,7 +73,9 @@ export default class RunestoneBase {
7373 }
7474 this . is_toggle = true ? opts . is_toggle : false ;
7575 this . is_select = true ? opts . is_select : false ;
76+
7677 }
78+ this . mjelements = [ ] ;
7779 this . jsonHeaders = new Headers ( {
7880 "Content-type" : "application/json; charset=utf-8" ,
7981 Accept : "application/json" ,
@@ -444,17 +446,79 @@ export default class RunestoneBase {
444446
445447 queueMathJax ( component ) {
446448 if ( typeof ( MathJax ) === "undefined" ) {
449+ console . log ( "Error -- MathJax is not loaded" )
447450 return Promise . resolve ( null ) ;
448- }
449- if ( MathJax . version . substring ( 0 , 1 ) === "2" ) {
450- MathJax . Hub . Queue ( [ "Typeset" , MathJax . Hub , component ] ) ;
451451 } else {
452452 // See - https://docs.mathjax.org/en/latest/advanced/typeset.html
453453 // Per the above we should keep track of the promises and only call this
454454 // a second time if all previous promises have resolved.
455- return MathJax . typesetPromise ( [ component ] ) ;
455+ // Create a queue of components
456+ // should wait until defaultPageReady is defined
457+ // If defaultPageReady is not defined then just enqueue the components.
458+ // Once defaultPageReady is defined
459+ if ( MathJax . startup && MathJax . startup . defaultPageReady ) {
460+ return MathJax . startup . defaultPageReady ( ) . then (
461+ async function ( ) {
462+ console . log ( `MathJax Ready -- promising a typesetting run for ${ component . id } ` )
463+ return await MathJax . typesetPromise ( [ component ] )
464+ }
465+ ) ;
466+ }
456467 }
457468 }
469+
470+ }
471+
472+
473+ // Inspiration and lots of code for this solution come from
474+ // https://stackoverflow.com/questions/53540348/js-async-await-tasks-queue
475+ // The idea here is that until MathJax is ready we can just enqueue things
476+ // once mathjax becomes ready then we can drain the queue and continue as usual.
477+
478+ class Queue {
479+ constructor ( ) { this . _items = [ ] ; }
480+ enqueue ( item ) { this . _items . push ( item ) ; }
481+ dequeue ( ) { return this . _items . shift ( ) ; }
482+ get size ( ) { return this . _items . length ; }
483+ }
484+
485+ class AutoQueue extends Queue {
486+ constructor ( ) {
487+ super ( ) ;
488+ this . _pendingPromise = false ;
489+ }
490+
491+ enqueue ( action ) {
492+ return new Promise ( ( resolve , reject ) => {
493+ super . enqueue ( { action, resolve, reject } ) ;
494+ this . dequeue ( ) ;
495+ } ) ;
496+ }
497+
498+ async dequeue ( ) {
499+ if ( this . _pendingPromise ) return false ;
500+
501+ let item = super . dequeue ( ) ;
502+
503+ if ( ! item ) return false ;
504+
505+ try {
506+ this . _pendingPromise = true ;
507+
508+ let payload = await item . action ( this ) ;
509+
510+ this . _pendingPromise = false ;
511+ item . resolve ( payload ) ;
512+ } catch ( e ) {
513+ this . _pendingPromise = false ;
514+ item . reject ( e ) ;
515+ } finally {
516+ this . dequeue ( ) ;
517+ }
518+
519+ return true ;
520+ }
458521}
459522
523+
460524window . RunestoneBase = RunestoneBase ;
0 commit comments