public/javascripts/codemirror/js/editor.js
function() {
        var firstLine = cleanText(self.history.textAfter(self.line).slice(self.offset));
        var match = (self.caseFold ? firstLine.toLowerCase() : firstLine).lastIndexOf(target[0]);
        if (match == -1 || match != firstLine.length - target[0].length)
          return false;
        var startOffset = self.offset + match;

        var line = self.history.nodeAfter(self.line);
        for (var i = 1; i < target.length - 1; i++) {
          var line = cleanText(self.history.textAfter(line));
          if ((self.caseFold ? line.toLowerCase() : line) != target[i])
            return false;
          line = self.history.nodeAfter(line);
        }

        var lastLine = cleanText(self.history.textAfter(line));
        if ((self.caseFold ? lastLine.toLowerCase() : lastLine).indexOf(target[target.length - 1]) != 0)
          return false;

        return {from: {node: self.line, offset: startOffset},
                to: {node: line, offset: target[target.length - 1].length}};
      }
function() {
        var firstLine = cleanText(self.history.textAfter(self.line).slice(self.offset));
        var match = (self.caseFold ? firstLine.toLowerCase() : firstLine).lastIndexOf(target[0]);
        if (match == -1 || match != firstLine.length - target[0].length)
          return false;
        var startOffset = self.offset + match;

        var line = self.history.nodeAfter(self.line);
        for (var i = 1; i < target.length - 1; i++) {
          var line = cleanText(self.history.textAfter(line));
          if ((self.caseFold ? line.toLowerCase() : line) != target[i])
            return false;
          line = self.history.nodeAfter(line);
        }

        var lastLine = cleanText(self.history.textAfter(line));
        if ((self.caseFold ? lastLine.toLowerCase() : lastLine).indexOf(target[target.length - 1]) != 0)
          return false;

        return {from: {node: self.line, offset: startOffset},
                to: {node: line, offset: target[target.length - 1].length}};
      }
function ( ) { var firstLine = cleanText ( self . history . textAfter ( self . line ) . slice ( self . offset ) ) ; var match = ( self . caseFold ? firstLine . toLowerCase ( ) : firstLine ) . lastIndexOf ( target [ 0 ] ) ; if ( match == - 1 || match != firstLine . length - target [ 0 ] . length ) return false ; var startOffset = self . offset + match ; var line = self . history . nodeAfter ( self . line ) ; for ( var i = 1 ; i < target . length - 1 ; i ++ ) { var line = cleanText ( self . history . textAfter ( line ) ) ; if ( ( self . caseFold ? line . toLowerCase ( ) : line ) != target [ i ] ) return false ; line = self . history . nodeAfter ( line ) ; } var lastLine = cleanText ( self . history . textAfter ( line ) ) ; if ( ( self . caseFold ? lastLine . toLowerCase ( ) : lastLine ) . indexOf ( target [ target . length - 1 ] ) != 0 ) return false ; return { from : { node : self . line , offset : startOffset } , to : { node : line , offset : target [ target . length - 1 ] . length } } ; }
Multi-line strings require internal iteration over lines, and some clunky checks to make sure the first match ends at the end of the line and the last match starts at the start.
Multi - line strings require internal iteration over lines and some clunky checks to make sure the first match ends at the end of the line and the last match starts at the start .