github.com/elliott5/community@v0.14.1-0.20160709191136-823126fb026a/app/public/codemirror/addon/runmode/runmode.node.js (about)

     1  // CodeMirror, copyright (c) by Marijn Haverbeke and others
     2  // Distributed under an MIT license: http://codemirror.net/LICENSE
     3  
     4  /* Just enough of CodeMirror to run runMode under node.js */
     5  
     6  function splitLines(string){return string.split(/\r\n?|\n/);};
     7  
     8  // Counts the column offset in a string, taking tabs into account.
     9  // Used mostly to find indentation.
    10  var countColumn = function(string, end, tabSize, startIndex, startValue) {
    11    if (end == null) {
    12      end = string.search(/[^\s\u00a0]/);
    13      if (end == -1) end = string.length;
    14    }
    15    for (var i = startIndex || 0, n = startValue || 0;;) {
    16      var nextTab = string.indexOf("\t", i);
    17      if (nextTab < 0 || nextTab >= end)
    18        return n + (end - i);
    19      n += nextTab - i;
    20      n += tabSize - (n % tabSize);
    21      i = nextTab + 1;
    22    }
    23  };
    24  
    25  function StringStream(string, tabSize) {
    26    this.pos = this.start = 0;
    27    this.string = string;
    28    this.tabSize = tabSize || 8;
    29    this.lastColumnPos = this.lastColumnValue = 0;
    30    this.lineStart = 0;
    31  };
    32  
    33  StringStream.prototype = {
    34    eol: function() {return this.pos >= this.string.length;},
    35    sol: function() {return this.pos == this.lineStart;},
    36    peek: function() {return this.string.charAt(this.pos) || undefined;},
    37    next: function() {
    38      if (this.pos < this.string.length)
    39        return this.string.charAt(this.pos++);
    40    },
    41    eat: function(match) {
    42      var ch = this.string.charAt(this.pos);
    43      if (typeof match == "string") var ok = ch == match;
    44      else var ok = ch && (match.test ? match.test(ch) : match(ch));
    45      if (ok) {++this.pos; return ch;}
    46    },
    47    eatWhile: function(match) {
    48      var start = this.pos;
    49      while (this.eat(match)){}
    50      return this.pos > start;
    51    },
    52    eatSpace: function() {
    53      var start = this.pos;
    54      while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
    55      return this.pos > start;
    56    },
    57    skipToEnd: function() {this.pos = this.string.length;},
    58    skipTo: function(ch) {
    59      var found = this.string.indexOf(ch, this.pos);
    60      if (found > -1) {this.pos = found; return true;}
    61    },
    62    backUp: function(n) {this.pos -= n;},
    63    column: function() {
    64      if (this.lastColumnPos < this.start) {
    65        this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
    66        this.lastColumnPos = this.start;
    67      }
    68      return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
    69    },
    70    indentation: function() {
    71      return countColumn(this.string, null, this.tabSize) -
    72        (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
    73    },
    74    match: function(pattern, consume, caseInsensitive) {
    75      if (typeof pattern == "string") {
    76        var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
    77        var substr = this.string.substr(this.pos, pattern.length);
    78        if (cased(substr) == cased(pattern)) {
    79          if (consume !== false) this.pos += pattern.length;
    80          return true;
    81        }
    82      } else {
    83        var match = this.string.slice(this.pos).match(pattern);
    84        if (match && match.index > 0) return null;
    85        if (match && consume !== false) this.pos += match[0].length;
    86        return match;
    87      }
    88    },
    89    current: function(){return this.string.slice(this.start, this.pos);},
    90    hideFirstChars: function(n, inner) {
    91      this.lineStart += n;
    92      try { return inner(); }
    93      finally { this.lineStart -= n; }
    94    }
    95  };
    96  exports.StringStream = StringStream;
    97  
    98  exports.startState = function(mode, a1, a2) {
    99    return mode.startState ? mode.startState(a1, a2) : true;
   100  };
   101  
   102  var modes = exports.modes = {}, mimeModes = exports.mimeModes = {};
   103  exports.defineMode = function(name, mode) {
   104    if (arguments.length > 2)
   105      mode.dependencies = Array.prototype.slice.call(arguments, 2);
   106    modes[name] = mode;
   107  };
   108  exports.defineMIME = function(mime, spec) { mimeModes[mime] = spec; };
   109  
   110  exports.defineMode("null", function() {
   111    return {token: function(stream) {stream.skipToEnd();}};
   112  });
   113  exports.defineMIME("text/plain", "null");
   114  
   115  exports.resolveMode = function(spec) {
   116    if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
   117      spec = mimeModes[spec];
   118    } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
   119      spec = mimeModes[spec.name];
   120    }
   121    if (typeof spec == "string") return {name: spec};
   122    else return spec || {name: "null"};
   123  };
   124  
   125  function copyObj(obj, target, overwrite) {
   126    if (!target) target = {};
   127    for (var prop in obj)
   128      if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
   129        target[prop] = obj[prop];
   130    return target;
   131  }
   132  
   133  // This can be used to attach properties to mode objects from
   134  // outside the actual mode definition.
   135  var modeExtensions = exports.modeExtensions = {};
   136  exports.extendMode = function(mode, properties) {
   137    var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
   138    copyObj(properties, exts);
   139  };
   140  
   141  exports.getMode = function(options, spec) {
   142    var spec = exports.resolveMode(spec);
   143    var mfactory = modes[spec.name];
   144    if (!mfactory) return exports.getMode(options, "text/plain");
   145    var modeObj = mfactory(options, spec);
   146    if (modeExtensions.hasOwnProperty(spec.name)) {
   147      var exts = modeExtensions[spec.name];
   148      for (var prop in exts) {
   149        if (!exts.hasOwnProperty(prop)) continue;
   150        if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop];
   151        modeObj[prop] = exts[prop];
   152      }
   153    }
   154    modeObj.name = spec.name;
   155    if (spec.helperType) modeObj.helperType = spec.helperType;
   156    if (spec.modeProps) for (var prop in spec.modeProps)
   157      modeObj[prop] = spec.modeProps[prop];
   158  
   159    return modeObj;
   160  };
   161  exports.registerHelper = exports.registerGlobalHelper = Math.min;
   162  
   163  exports.runMode = function(string, modespec, callback, options) {
   164    var mode = exports.getMode({indentUnit: 2}, modespec);
   165    var lines = splitLines(string), state = (options && options.state) || exports.startState(mode);
   166    for (var i = 0, e = lines.length; i < e; ++i) {
   167      if (i) callback("\n");
   168      var stream = new exports.StringStream(lines[i]);
   169      if (!stream.string && mode.blankLine) mode.blankLine(state);
   170      while (!stream.eol()) {
   171        var style = mode.token(stream, state);
   172        callback(stream.current(), style, i, stream.start, state);
   173        stream.start = stream.pos;
   174      }
   175    }
   176  };
   177  
   178  require.cache[require.resolve("../../lib/codemirror")] = require.cache[require.resolve("./runmode.node")];
   179  require.cache[require.resolve("../../addon/runmode/runmode")] = require.cache[require.resolve("./runmode.node")];