function resolveAllAttention(events, context) {
  var index = -1
  var open
  var group
  var text
  var openingSequence
  var closingSequence
  var use
  var nextEvents
  var offset

  // Walk through all events.
  //
  // Note: performance of this is fine on an mb of normal markdown, but it’s
  // a bottleneck for malicious stuff.
  while (++index < events.length) {
    // Find a token that can close.
    if (
      events[index][0] === 'enter' &&
      events[index][1].type === 'attentionSequence' &&
      events[index][1]._close
    ) {
      open = index

      // Now walk back to find an opener.
      while (open--) {
        // Find a token that can open the closer.
        if (
          events[open][0] === 'exit' &&
          events[open][1].type === 'attentionSequence' &&
          events[open][1]._open &&
          // If the markers are the same:
          context.sliceSerialize(events[open][1]).charCodeAt(0) ===
            context.sliceSerialize(events[index][1]).charCodeAt(0)
        ) {
          // If the opening can close or the closing can open,
          // and the close size *is not* a multiple of three,
          // but the sum of the opening and closing size *is* multiple of three,
          // then don’t match.
          if (
            (events[open][1]._close || events[index][1]._open) &&
            (events[index][1].end.offset - events[index][1].start.offset) % 3 &&
            !(
              (events[open][1].end.offset -
                events[open][1].start.offset +
                events[index][1].end.offset -
                events[index][1].start.offset) %
              3
            )
          ) {
            continue
          }

          // Number of markers to use from the sequence.
          use =
            events[open][1].end.offset - events[open][1].start.offset > 1 &&
            events[index][1].end.offset - events[index][1].start.offset > 1
              ? 2
              : 1

          openingSequence = {
            type: use > 1 ? types.strongSequence : types.emphasisSequence,
            start: movePoint(shallow(events[open][1].end), -use),
            end: shallow(events[open][1].end)
          }
          closingSequence = {
            type: use > 1 ? types.strongSequence : types.emphasisSequence,
            start: shallow(events[index][1].start),
            end: movePoint(shallow(events[index][1].start), use)
          }
          text = {
            type: use > 1 ? types.strongText : types.emphasisText,
            start: shallow(events[open][1].end),
            end: shallow(events[index][1].start)
          }
          group = {
            type: use > 1 ? types.strong : types.emphasis,
            start: shallow(openingSequence.start),
            end: shallow(closingSequence.end)
          }

          events[open][1].end = shallow(openingSequence.start)
          events[index][1].start = shallow(closingSequence.end)

          nextEvents = []

          // If there are more markers in the opening, add them before.
          if (events[open][1].end.offset - events[open][1].start.offset) {
            nextEvents = chunkedPush(nextEvents, [
              ['enter', events[open][1], context],
              ['exit', events[open][1], context]
            ])
          }

          // Opening.
          nextEvents = chunkedPush(nextEvents, [
            ['enter', group, context],
            ['enter', openingSequence, context],
            ['exit', openingSequence, context],
            ['enter', text, context]
          ])

          // Between.
          nextEvents = chunkedPush(
            nextEvents,
            resolveAll(
              context.parser.constructs.insideSpan.null,
              events.slice(open + 1, index),
              context
            )
          )

          // Closing.
          nextEvents = chunkedPush(nextEvents, [
            ['exit', text, context],
            ['enter', closingSequence, context],
            ['exit', closingSequence, context],
            ['exit', group, context]
          ])

          // If there are more markers in the closing, add them after.
          if (events[index][1].end.offset - events[index][1].start.offset) {
            offset = 2
            nextEvents = chunkedPush(nextEvents, [
              ['enter', events[index][1], context],
              ['exit', events[index][1], context]
            ])
          } else {
            offset = 0
          }

          chunkedSplice(events, open - 1, index - open + 3, nextEvents)

          index = open + nextEvents.length - offset - 2
          break
        }
      }
    }
  }

  // Remove remaining sequences.
  index = -1

  while (++index < events.length) {
    if (events[index][1].type === 'attentionSequence') {
      events[index][1].type = 'data'
    }
  }

  return events
}
// Take all events and resolve attention to emphasis or strong.
Take all events and resolve attention to emphasis or strong.
Take all events and resolve attention to emphasis or strong .
function resolveAllAttention(events, context) {
  var index = -1
  var open
  var group
  var text
  var openingSequence
  var closingSequence
  var use
  var nextEvents
  var offset
   Note: performance of this is fine on an mb of normal markdown, but it’s
   a bottleneck for malicious stuff.
  while (++index < events.length) {
     Find a token that can close.
    if (
      events[index][0] === 'enter' &&
      events[index][1].type === 'attentionSequence' &&
      events[index][1]._close
    ) {
      open = index
       Now walk back to find an opener.
      while (open--) {
         Find a token that can open the closer.
        if (
          events[open][0] === 'exit' &&
          events[open][1].type === 'attentionSequence' &&
          events[open][1]._open &&
           If the markers are the same:
          context.sliceSerialize(events[open][1]).charCodeAt(0) ===
            context.sliceSerialize(events[index][1]).charCodeAt(0)
        ) {
           If the opening can close or the closing can open,
           and the close size *is not* a multiple of three,
           but the sum of the opening and closing size *is* multiple of three,
           then don’t match.
          if (
            (events[open][1]._close || events[index][1]._open) &&
            (events[index][1].end.offset - events[index][1].start.offset) % 3 &&
            !(
              (events[open][1].end.offset -
                events[open][1].start.offset +
                events[index][1].end.offset -
                events[index][1].start.offset) %
              3
            )
          ) {
            continue
          }
           Number of markers to use from the sequence.
          use =
            events[open][1].end.offset - events[open][1].start.offset > 1 &&
            events[index][1].end.offset - events[index][1].start.offset > 1
              ? 2
              : 1
          openingSequence = {
            type: use > 1 ? types.strongSequence : types.emphasisSequence,
            start: movePoint(shallow(events[open][1].end), -use),
            end: shallow(events[open][1].end)
          }
          closingSequence = {
            type: use > 1 ? types.strongSequence : types.emphasisSequence,
            start: shallow(events[index][1].start),
            end: movePoint(shallow(events[index][1].start), use)
          }
          text = {
            type: use > 1 ? types.strongText : types.emphasisText,
            start: shallow(events[open][1].end),
            end: shallow(events[index][1].start)
          }
          group = {
            type: use > 1 ? types.strong : types.emphasis,
            start: shallow(openingSequence.start),
            end: shallow(closingSequence.end)
          }
          events[open][1].end = shallow(openingSequence.start)
          events[index][1].start = shallow(closingSequence.end)
          nextEvents = []
           If there are more markers in the opening, add them before.
          if (events[open][1].end.offset - events[open][1].start.offset) {
            nextEvents = chunkedPush(nextEvents, [
              ['enter', events[open][1], context],
              ['exit', events[open][1], context]
            ])
          }
           Opening.
          nextEvents = chunkedPush(nextEvents, [
            ['enter', group, context],
            ['enter', openingSequence, context],
            ['exit', openingSequence, context],
            ['enter', text, context]
          ])
           Between.
          nextEvents = chunkedPush(
            nextEvents,
            resolveAll(
              context.parser.constructs.insideSpan.null,
              events.slice(open + 1, index),
              context
            )
          )
           Closing.
          nextEvents = chunkedPush(nextEvents, [
            ['exit', text, context],
            ['enter', closingSequence, context],
            ['exit', closingSequence, context],
            ['exit', group, context]
          ])
           If there are more markers in the closing, add them after.
          if (events[index][1].end.offset - events[index][1].start.offset) {
            offset = 2
            nextEvents = chunkedPush(nextEvents, [
              ['enter', events[index][1], context],
              ['exit', events[index][1], context]
            ])
          } else {
            offset = 0
          }
          chunkedSplice(events, open - 1, index - open + 3, nextEvents)
          index = open + nextEvents.length - offset - 2
          break
        }
      }
    }
  }
   Remove remaining sequences.
  index = -1
  while (++index < events.length) {
    if (events[index][1].type === 'attentionSequence') {
      events[index][1].type = 'data'
    }
  }
  return events
}
function resolveAllAttention ( events , context ) { var index = - 1 var open var group var text var openingSequence var closingSequence var use var nextEvents var offset while ( ++ index < events . length ) { if ( events [ index ] [ 0 ] === 'enter' && events [ index ] [ 1 ] . type === 'attentionSequence' && events [ index ] [ 1 ] . _close ) { open = index while ( open -- ) { if ( events [ open ] [ 0 ] === 'exit' && events [ open ] [ 1 ] . type === 'attentionSequence' && events [ open ] [ 1 ] . _open && context . sliceSerialize ( events [ open ] [ 1 ] ) . charCodeAt ( 0 ) === context . sliceSerialize ( events [ index ] [ 1 ] ) . charCodeAt ( 0 ) ) { if ( ( events [ open ] [ 1 ] . _close || events [ index ] [ 1 ] . _open ) && ( events [ index ] [ 1 ] . end . offset - events [ index ] [ 1 ] . start . offset ) % 3 && ! ( ( events [ open ] [ 1 ] . end . offset - events [ open ] [ 1 ] . start . offset + events [ index ] [ 1 ] . end . offset - events [ index ] [ 1 ] . start . offset ) % 3 ) ) { continue } use = events [ open ] [ 1 ] . end . offset - events [ open ] [ 1 ] . start . offset > 1 && events [ index ] [ 1 ] . end . offset - events [ index ] [ 1 ] . start . offset > 1 ? 2 : 1 openingSequence = { type : use > 1 ? types . strongSequence : types . emphasisSequence , start : movePoint ( shallow ( events [ open ] [ 1 ] . end ) , - use ) , end : shallow ( events [ open ] [ 1 ] . end ) } closingSequence = { type : use > 1 ? types . strongSequence : types . emphasisSequence , start : shallow ( events [ index ] [ 1 ] . start ) , end : movePoint ( shallow ( events [ index ] [ 1 ] . start ) , use ) } text = { type : use > 1 ? types . strongText : types . emphasisText , start : shallow ( events [ open ] [ 1 ] . end ) , end : shallow ( events [ index ] [ 1 ] . start ) } group = { type : use > 1 ? types . strong : types . emphasis , start : shallow ( openingSequence . start ) , end : shallow ( closingSequence . end ) } events [ open ] [ 1 ] . end = shallow ( openingSequence . start ) events [ index ] [ 1 ] . start = shallow ( closingSequence . end ) nextEvents = [ ] if ( events [ open ] [ 1 ] . end . offset - events [ open ] [ 1 ] . start . offset ) { nextEvents = chunkedPush ( nextEvents , [ [ 'enter' , events [ open ] [ 1 ] , context ] , [ 'exit' , events [ open ] [ 1 ] , context ] ] ) } nextEvents = chunkedPush ( nextEvents , [ [ 'enter' , group , context ] , [ 'enter' , openingSequence , context ] , [ 'exit' , openingSequence , context ] , [ 'enter' , text , context ] ] ) nextEvents = chunkedPush ( nextEvents , resolveAll ( context . parser . constructs . insideSpan . null , events . slice ( open + 1 , index ) , context ) ) nextEvents = chunkedPush ( nextEvents , [ [ 'exit' , text , context ] , [ 'enter' , closingSequence , context ] , [ 'exit' , closingSequence , context ] , [ 'exit' , group , context ] ] ) if ( events [ index ] [ 1 ] . end . offset - events [ index ] [ 1 ] . start . offset ) { offset = 2 nextEvents = chunkedPush ( nextEvents , [ [ 'enter' , events [ index ] [ 1 ] , context ] , [ 'exit' , events [ index ] [ 1 ] , context ] ] ) } else { offset = 0 } chunkedSplice ( events , open - 1 , index - open + 3 , nextEvents ) index = open + nextEvents . length - offset - 2 break } } } } index = - 1 while ( ++ index < events . length ) { if ( events [ index ] [ 1 ] . type === 'attentionSequence' ) { events [ index ] [ 1 ] . type = 'data' } } return events }
Take all events and resolve attention to emphasis or strong.
Take all events and resolve attention to emphasis or strong .
// Walk through all events. // // Note: performance of this is fine on an mb of normal markdown, but it’s // a bottleneck for malicious stuff. // Find a token that can close. // Now walk back to find an opener. // Find a token that can open the closer. // If the markers are the same: // If the opening can close or the closing can open, // and the close size *is not* a multiple of three, // but the sum of the opening and closing size *is* multiple of three, // then don’t match. // Number of markers to use from the sequence. // If there are more markers in the opening, add them before. // Opening. // Between. // Closing. // If there are more markers in the closing, add them after. // Remove remaining sequences.