text: module.exports = create
  
  var classifyCharacter = require('micromark/dist/util/classify-character')
  var chunkedSplice = require('micromark/dist/util/chunked-splice')
  var resolveAll = require('micromark/dist/util/resolve-all')
  var shallow = require('micromark/dist/util/shallow')
  
  function create(options) {
    var settings = options || {}
    var single = settings.singleTilde
    var tokenizer = {
      tokenize: tokenizeStrikethrough,
      resolveAll: resolveAllStrikethrough
    }
  
    if (single === null || single === undefined) {
      single = true
    }
  
    return {text: {126: tokenizer}, insideSpan: {null: tokenizer}}
  
    // Take events and resolve strikethrough.
    function resolveAllStrikethrough(events, context) {
      var index = -1
      var strikethrough
      var text
      var open
      var nextEvents
  
      // Walk through all events.
      while (++index < events.length) {
        // Find a token that can close.
        if (
          events[index][0] === 'enter' &&
          events[index][1].type === 'strikethroughSequenceTemporary' &&
          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 === 'strikethroughSequenceTemporary' &&
              events[open][1]._open &&
              // If the sizes are the same:
              events[index][1].end.offset - events[index][1].start.offset ===
                events[open][1].end.offset - events[open][1].start.offset
            ) {
              events[index][1].type = 'strikethroughSequence'
              events[open][1].type = 'strikethroughSequence'
  
              strikethrough = {
                type: 'strikethrough',
                start: shallow(events[open][1].start),
                end: shallow(events[index][1].end)
              }
  
              text = {
                type: 'strikethroughText',
                start: shallow(events[open][1].end),
                end: shallow(events[index][1].start)
              }
  
              // Opening.
              nextEvents = [
                ['enter', strikethrough, context],
                ['enter', events[open][1], context],
                ['exit', events[open][1], context],
                ['enter', text, context]
              ]
  
              // Between.
              chunkedSplice(
                nextEvents,
                nextEvents.length,
                0,
                resolveAll(
                  context.parser.constructs.insideSpan.null,
                  events.slice(open + 1, index),
                  context
                )
              )
  
              // Closing.
              chunkedSplice(nextEvents, nextEvents.length, 0, [
                ['exit', text, context],
                ['enter', events[index][1], context],
                ['exit', events[index][1], context],
                ['exit', strikethrough, context]
              ])
  
              chunkedSplice(events, open - 1, index - open + 3, nextEvents)
  
              index = open + nextEvents.length - 2
              break
            }
          }
        }
      }
  
      return removeRemainingSequences(events)
    }
  
    function removeRemainingSequences(events) {
      var index = -1
      var length = events.length
  
      while (++index < length) {
        if (events[index][1].type === 'strikethroughSequenceTemporary') {
          events[index][1].type = 'data'
        }
      }
  
      return events
    }
  
    function tokenizeStrikethrough(effects, ok, nok) {
      var previous = this.previous
      var events = this.events
      var size = 0
  
      return start
  
      function start(code) {
        if (
          code !== 126 ||
          (previous === 126 &&
            events[events.length - 1][1].type !== 'characterEscape')
        ) {
          return nok(code)
        }
  
        effects.enter('strikethroughSequenceTemporary')
        return more(code)
      }
  
      function more(code) {
        var before = classifyCharacter(previous)
        var token
        var after
  
        if (code === 126) {
          // If this is the third marker, exit.
          if (size > 1) return nok(code)
          effects.consume(code)
          size++
          return more
        }
  
        if (size < 2 && !single) return nok(code)
        token = effects.exit('strikethroughSequenceTemporary')
        after = classifyCharacter(code)
        token._open = !after || (after === 2 && before)
        token._close = !before || (before === 2 && after)
        return ok(code)
      }
    }
  }
  