github.com/jancarloviray/community@v0.41.1-0.20170124221257-33a66c87cf2f/app/public/codemirror/mode/rst/rst.js (about)

     1  // CodeMirror, copyright (c) by Marijn Haverbeke and others
     2  // Distributed under an MIT license: http://codemirror.net/LICENSE
     3  
     4  (function(mod) {
     5    if (typeof exports == "object" && typeof module == "object") // CommonJS
     6      mod(require("../../lib/codemirror"), require("../python/python"), require("../stex/stex"), require("../../addon/mode/overlay"));
     7    else if (typeof define == "function" && define.amd) // AMD
     8      define(["../../lib/codemirror", "../python/python", "../stex/stex", "../../addon/mode/overlay"], mod);
     9    else // Plain browser env
    10      mod(CodeMirror);
    11  })(function(CodeMirror) {
    12  "use strict";
    13  
    14  CodeMirror.defineMode('rst', function (config, options) {
    15  
    16    var rx_strong = /^\*\*[^\*\s](?:[^\*]*[^\*\s])?\*\*/;
    17    var rx_emphasis = /^\*[^\*\s](?:[^\*]*[^\*\s])?\*/;
    18    var rx_literal = /^``[^`\s](?:[^`]*[^`\s])``/;
    19  
    20    var rx_number = /^(?:[\d]+(?:[\.,]\d+)*)/;
    21    var rx_positive = /^(?:\s\+[\d]+(?:[\.,]\d+)*)/;
    22    var rx_negative = /^(?:\s\-[\d]+(?:[\.,]\d+)*)/;
    23  
    24    var rx_uri_protocol = "[Hh][Tt][Tt][Pp][Ss]?://";
    25    var rx_uri_domain = "(?:[\\d\\w.-]+)\\.(?:\\w{2,6})";
    26    var rx_uri_path = "(?:/[\\d\\w\\#\\%\\&\\-\\.\\,\\/\\:\\=\\?\\~]+)*";
    27    var rx_uri = new RegExp("^" + rx_uri_protocol + rx_uri_domain + rx_uri_path);
    28  
    29    var overlay = {
    30      token: function (stream) {
    31  
    32        if (stream.match(rx_strong) && stream.match (/\W+|$/, false))
    33          return 'strong';
    34        if (stream.match(rx_emphasis) && stream.match (/\W+|$/, false))
    35          return 'em';
    36        if (stream.match(rx_literal) && stream.match (/\W+|$/, false))
    37          return 'string-2';
    38        if (stream.match(rx_number))
    39          return 'number';
    40        if (stream.match(rx_positive))
    41          return 'positive';
    42        if (stream.match(rx_negative))
    43          return 'negative';
    44        if (stream.match(rx_uri))
    45          return 'link';
    46  
    47        while (stream.next() != null) {
    48          if (stream.match(rx_strong, false)) break;
    49          if (stream.match(rx_emphasis, false)) break;
    50          if (stream.match(rx_literal, false)) break;
    51          if (stream.match(rx_number, false)) break;
    52          if (stream.match(rx_positive, false)) break;
    53          if (stream.match(rx_negative, false)) break;
    54          if (stream.match(rx_uri, false)) break;
    55        }
    56  
    57        return null;
    58      }
    59    };
    60  
    61    var mode = CodeMirror.getMode(
    62      config, options.backdrop || 'rst-base'
    63    );
    64  
    65    return CodeMirror.overlayMode(mode, overlay, true); // combine
    66  }, 'python', 'stex');
    67  
    68  ///////////////////////////////////////////////////////////////////////////////
    69  ///////////////////////////////////////////////////////////////////////////////
    70  
    71  CodeMirror.defineMode('rst-base', function (config) {
    72  
    73    ///////////////////////////////////////////////////////////////////////////
    74    ///////////////////////////////////////////////////////////////////////////
    75  
    76    function format(string) {
    77      var args = Array.prototype.slice.call(arguments, 1);
    78      return string.replace(/{(\d+)}/g, function (match, n) {
    79        return typeof args[n] != 'undefined' ? args[n] : match;
    80      });
    81    }
    82  
    83    ///////////////////////////////////////////////////////////////////////////
    84    ///////////////////////////////////////////////////////////////////////////
    85  
    86    var mode_python = CodeMirror.getMode(config, 'python');
    87    var mode_stex = CodeMirror.getMode(config, 'stex');
    88  
    89    ///////////////////////////////////////////////////////////////////////////
    90    ///////////////////////////////////////////////////////////////////////////
    91  
    92    var SEPA = "\\s+";
    93    var TAIL = "(?:\\s*|\\W|$)",
    94    rx_TAIL = new RegExp(format('^{0}', TAIL));
    95  
    96    var NAME =
    97      "(?:[^\\W\\d_](?:[\\w!\"#$%&'()\\*\\+,\\-\\.\/:;<=>\\?]*[^\\W_])?)",
    98    rx_NAME = new RegExp(format('^{0}', NAME));
    99    var NAME_WWS =
   100      "(?:[^\\W\\d_](?:[\\w\\s!\"#$%&'()\\*\\+,\\-\\.\/:;<=>\\?]*[^\\W_])?)";
   101    var REF_NAME = format('(?:{0}|`{1}`)', NAME, NAME_WWS);
   102  
   103    var TEXT1 = "(?:[^\\s\\|](?:[^\\|]*[^\\s\\|])?)";
   104    var TEXT2 = "(?:[^\\`]+)",
   105    rx_TEXT2 = new RegExp(format('^{0}', TEXT2));
   106  
   107    var rx_section = new RegExp(
   108      "^([!'#$%&\"()*+,-./:;<=>?@\\[\\\\\\]^_`{|}~])\\1{3,}\\s*$");
   109    var rx_explicit = new RegExp(
   110      format('^\\.\\.{0}', SEPA));
   111    var rx_link = new RegExp(
   112      format('^_{0}:{1}|^__:{1}', REF_NAME, TAIL));
   113    var rx_directive = new RegExp(
   114      format('^{0}::{1}', REF_NAME, TAIL));
   115    var rx_substitution = new RegExp(
   116      format('^\\|{0}\\|{1}{2}::{3}', TEXT1, SEPA, REF_NAME, TAIL));
   117    var rx_footnote = new RegExp(
   118      format('^\\[(?:\\d+|#{0}?|\\*)]{1}', REF_NAME, TAIL));
   119    var rx_citation = new RegExp(
   120      format('^\\[{0}\\]{1}', REF_NAME, TAIL));
   121  
   122    var rx_substitution_ref = new RegExp(
   123      format('^\\|{0}\\|', TEXT1));
   124    var rx_footnote_ref = new RegExp(
   125      format('^\\[(?:\\d+|#{0}?|\\*)]_', REF_NAME));
   126    var rx_citation_ref = new RegExp(
   127      format('^\\[{0}\\]_', REF_NAME));
   128    var rx_link_ref1 = new RegExp(
   129      format('^{0}__?', REF_NAME));
   130    var rx_link_ref2 = new RegExp(
   131      format('^`{0}`_', TEXT2));
   132  
   133    var rx_role_pre = new RegExp(
   134      format('^:{0}:`{1}`{2}', NAME, TEXT2, TAIL));
   135    var rx_role_suf = new RegExp(
   136      format('^`{1}`:{0}:{2}', NAME, TEXT2, TAIL));
   137    var rx_role = new RegExp(
   138      format('^:{0}:{1}', NAME, TAIL));
   139  
   140    var rx_directive_name = new RegExp(format('^{0}', REF_NAME));
   141    var rx_directive_tail = new RegExp(format('^::{0}', TAIL));
   142    var rx_substitution_text = new RegExp(format('^\\|{0}\\|', TEXT1));
   143    var rx_substitution_sepa = new RegExp(format('^{0}', SEPA));
   144    var rx_substitution_name = new RegExp(format('^{0}', REF_NAME));
   145    var rx_substitution_tail = new RegExp(format('^::{0}', TAIL));
   146    var rx_link_head = new RegExp("^_");
   147    var rx_link_name = new RegExp(format('^{0}|_', REF_NAME));
   148    var rx_link_tail = new RegExp(format('^:{0}', TAIL));
   149  
   150    var rx_verbatim = new RegExp('^::\\s*$');
   151    var rx_examples = new RegExp('^\\s+(?:>>>|In \\[\\d+\\]:)\\s');
   152  
   153    ///////////////////////////////////////////////////////////////////////////
   154    ///////////////////////////////////////////////////////////////////////////
   155  
   156    function to_normal(stream, state) {
   157      var token = null;
   158  
   159      if (stream.sol() && stream.match(rx_examples, false)) {
   160        change(state, to_mode, {
   161          mode: mode_python, local: CodeMirror.startState(mode_python)
   162        });
   163      } else if (stream.sol() && stream.match(rx_explicit)) {
   164        change(state, to_explicit);
   165        token = 'meta';
   166      } else if (stream.sol() && stream.match(rx_section)) {
   167        change(state, to_normal);
   168        token = 'header';
   169      } else if (phase(state) == rx_role_pre ||
   170                 stream.match(rx_role_pre, false)) {
   171  
   172        switch (stage(state)) {
   173        case 0:
   174          change(state, to_normal, context(rx_role_pre, 1));
   175          stream.match(/^:/);
   176          token = 'meta';
   177          break;
   178        case 1:
   179          change(state, to_normal, context(rx_role_pre, 2));
   180          stream.match(rx_NAME);
   181          token = 'keyword';
   182  
   183          if (stream.current().match(/^(?:math|latex)/)) {
   184            state.tmp_stex = true;
   185          }
   186          break;
   187        case 2:
   188          change(state, to_normal, context(rx_role_pre, 3));
   189          stream.match(/^:`/);
   190          token = 'meta';
   191          break;
   192        case 3:
   193          if (state.tmp_stex) {
   194            state.tmp_stex = undefined; state.tmp = {
   195              mode: mode_stex, local: CodeMirror.startState(mode_stex)
   196            };
   197          }
   198  
   199          if (state.tmp) {
   200            if (stream.peek() == '`') {
   201              change(state, to_normal, context(rx_role_pre, 4));
   202              state.tmp = undefined;
   203              break;
   204            }
   205  
   206            token = state.tmp.mode.token(stream, state.tmp.local);
   207            break;
   208          }
   209  
   210          change(state, to_normal, context(rx_role_pre, 4));
   211          stream.match(rx_TEXT2);
   212          token = 'string';
   213          break;
   214        case 4:
   215          change(state, to_normal, context(rx_role_pre, 5));
   216          stream.match(/^`/);
   217          token = 'meta';
   218          break;
   219        case 5:
   220          change(state, to_normal, context(rx_role_pre, 6));
   221          stream.match(rx_TAIL);
   222          break;
   223        default:
   224          change(state, to_normal);
   225        }
   226      } else if (phase(state) == rx_role_suf ||
   227                 stream.match(rx_role_suf, false)) {
   228  
   229        switch (stage(state)) {
   230        case 0:
   231          change(state, to_normal, context(rx_role_suf, 1));
   232          stream.match(/^`/);
   233          token = 'meta';
   234          break;
   235        case 1:
   236          change(state, to_normal, context(rx_role_suf, 2));
   237          stream.match(rx_TEXT2);
   238          token = 'string';
   239          break;
   240        case 2:
   241          change(state, to_normal, context(rx_role_suf, 3));
   242          stream.match(/^`:/);
   243          token = 'meta';
   244          break;
   245        case 3:
   246          change(state, to_normal, context(rx_role_suf, 4));
   247          stream.match(rx_NAME);
   248          token = 'keyword';
   249          break;
   250        case 4:
   251          change(state, to_normal, context(rx_role_suf, 5));
   252          stream.match(/^:/);
   253          token = 'meta';
   254          break;
   255        case 5:
   256          change(state, to_normal, context(rx_role_suf, 6));
   257          stream.match(rx_TAIL);
   258          break;
   259        default:
   260          change(state, to_normal);
   261        }
   262      } else if (phase(state) == rx_role || stream.match(rx_role, false)) {
   263  
   264        switch (stage(state)) {
   265        case 0:
   266          change(state, to_normal, context(rx_role, 1));
   267          stream.match(/^:/);
   268          token = 'meta';
   269          break;
   270        case 1:
   271          change(state, to_normal, context(rx_role, 2));
   272          stream.match(rx_NAME);
   273          token = 'keyword';
   274          break;
   275        case 2:
   276          change(state, to_normal, context(rx_role, 3));
   277          stream.match(/^:/);
   278          token = 'meta';
   279          break;
   280        case 3:
   281          change(state, to_normal, context(rx_role, 4));
   282          stream.match(rx_TAIL);
   283          break;
   284        default:
   285          change(state, to_normal);
   286        }
   287      } else if (phase(state) == rx_substitution_ref ||
   288                 stream.match(rx_substitution_ref, false)) {
   289  
   290        switch (stage(state)) {
   291        case 0:
   292          change(state, to_normal, context(rx_substitution_ref, 1));
   293          stream.match(rx_substitution_text);
   294          token = 'variable-2';
   295          break;
   296        case 1:
   297          change(state, to_normal, context(rx_substitution_ref, 2));
   298          if (stream.match(/^_?_?/)) token = 'link';
   299          break;
   300        default:
   301          change(state, to_normal);
   302        }
   303      } else if (stream.match(rx_footnote_ref)) {
   304        change(state, to_normal);
   305        token = 'quote';
   306      } else if (stream.match(rx_citation_ref)) {
   307        change(state, to_normal);
   308        token = 'quote';
   309      } else if (stream.match(rx_link_ref1)) {
   310        change(state, to_normal);
   311        if (!stream.peek() || stream.peek().match(/^\W$/)) {
   312          token = 'link';
   313        }
   314      } else if (phase(state) == rx_link_ref2 ||
   315                 stream.match(rx_link_ref2, false)) {
   316  
   317        switch (stage(state)) {
   318        case 0:
   319          if (!stream.peek() || stream.peek().match(/^\W$/)) {
   320            change(state, to_normal, context(rx_link_ref2, 1));
   321          } else {
   322            stream.match(rx_link_ref2);
   323          }
   324          break;
   325        case 1:
   326          change(state, to_normal, context(rx_link_ref2, 2));
   327          stream.match(/^`/);
   328          token = 'link';
   329          break;
   330        case 2:
   331          change(state, to_normal, context(rx_link_ref2, 3));
   332          stream.match(rx_TEXT2);
   333          break;
   334        case 3:
   335          change(state, to_normal, context(rx_link_ref2, 4));
   336          stream.match(/^`_/);
   337          token = 'link';
   338          break;
   339        default:
   340          change(state, to_normal);
   341        }
   342      } else if (stream.match(rx_verbatim)) {
   343        change(state, to_verbatim);
   344      }
   345  
   346      else {
   347        if (stream.next()) change(state, to_normal);
   348      }
   349  
   350      return token;
   351    }
   352  
   353    ///////////////////////////////////////////////////////////////////////////
   354    ///////////////////////////////////////////////////////////////////////////
   355  
   356    function to_explicit(stream, state) {
   357      var token = null;
   358  
   359      if (phase(state) == rx_substitution ||
   360          stream.match(rx_substitution, false)) {
   361  
   362        switch (stage(state)) {
   363        case 0:
   364          change(state, to_explicit, context(rx_substitution, 1));
   365          stream.match(rx_substitution_text);
   366          token = 'variable-2';
   367          break;
   368        case 1:
   369          change(state, to_explicit, context(rx_substitution, 2));
   370          stream.match(rx_substitution_sepa);
   371          break;
   372        case 2:
   373          change(state, to_explicit, context(rx_substitution, 3));
   374          stream.match(rx_substitution_name);
   375          token = 'keyword';
   376          break;
   377        case 3:
   378          change(state, to_explicit, context(rx_substitution, 4));
   379          stream.match(rx_substitution_tail);
   380          token = 'meta';
   381          break;
   382        default:
   383          change(state, to_normal);
   384        }
   385      } else if (phase(state) == rx_directive ||
   386                 stream.match(rx_directive, false)) {
   387  
   388        switch (stage(state)) {
   389        case 0:
   390          change(state, to_explicit, context(rx_directive, 1));
   391          stream.match(rx_directive_name);
   392          token = 'keyword';
   393  
   394          if (stream.current().match(/^(?:math|latex)/))
   395            state.tmp_stex = true;
   396          else if (stream.current().match(/^python/))
   397            state.tmp_py = true;
   398          break;
   399        case 1:
   400          change(state, to_explicit, context(rx_directive, 2));
   401          stream.match(rx_directive_tail);
   402          token = 'meta';
   403  
   404          if (stream.match(/^latex\s*$/) || state.tmp_stex) {
   405            state.tmp_stex = undefined; change(state, to_mode, {
   406              mode: mode_stex, local: CodeMirror.startState(mode_stex)
   407            });
   408          }
   409          break;
   410        case 2:
   411          change(state, to_explicit, context(rx_directive, 3));
   412          if (stream.match(/^python\s*$/) || state.tmp_py) {
   413            state.tmp_py = undefined; change(state, to_mode, {
   414              mode: mode_python, local: CodeMirror.startState(mode_python)
   415            });
   416          }
   417          break;
   418        default:
   419          change(state, to_normal);
   420        }
   421      } else if (phase(state) == rx_link || stream.match(rx_link, false)) {
   422  
   423        switch (stage(state)) {
   424        case 0:
   425          change(state, to_explicit, context(rx_link, 1));
   426          stream.match(rx_link_head);
   427          stream.match(rx_link_name);
   428          token = 'link';
   429          break;
   430        case 1:
   431          change(state, to_explicit, context(rx_link, 2));
   432          stream.match(rx_link_tail);
   433          token = 'meta';
   434          break;
   435        default:
   436          change(state, to_normal);
   437        }
   438      } else if (stream.match(rx_footnote)) {
   439        change(state, to_normal);
   440        token = 'quote';
   441      } else if (stream.match(rx_citation)) {
   442        change(state, to_normal);
   443        token = 'quote';
   444      }
   445  
   446      else {
   447        stream.eatSpace();
   448        if (stream.eol()) {
   449          change(state, to_normal);
   450        } else {
   451          stream.skipToEnd();
   452          change(state, to_comment);
   453          token = 'comment';
   454        }
   455      }
   456  
   457      return token;
   458    }
   459  
   460    ///////////////////////////////////////////////////////////////////////////
   461    ///////////////////////////////////////////////////////////////////////////
   462  
   463    function to_comment(stream, state) {
   464      return as_block(stream, state, 'comment');
   465    }
   466  
   467    function to_verbatim(stream, state) {
   468      return as_block(stream, state, 'meta');
   469    }
   470  
   471    function as_block(stream, state, token) {
   472      if (stream.eol() || stream.eatSpace()) {
   473        stream.skipToEnd();
   474        return token;
   475      } else {
   476        change(state, to_normal);
   477        return null;
   478      }
   479    }
   480  
   481    ///////////////////////////////////////////////////////////////////////////
   482    ///////////////////////////////////////////////////////////////////////////
   483  
   484    function to_mode(stream, state) {
   485  
   486      if (state.ctx.mode && state.ctx.local) {
   487  
   488        if (stream.sol()) {
   489          if (!stream.eatSpace()) change(state, to_normal);
   490          return null;
   491        }
   492  
   493        return state.ctx.mode.token(stream, state.ctx.local);
   494      }
   495  
   496      change(state, to_normal);
   497      return null;
   498    }
   499  
   500    ///////////////////////////////////////////////////////////////////////////
   501    ///////////////////////////////////////////////////////////////////////////
   502  
   503    function context(phase, stage, mode, local) {
   504      return {phase: phase, stage: stage, mode: mode, local: local};
   505    }
   506  
   507    function change(state, tok, ctx) {
   508      state.tok = tok;
   509      state.ctx = ctx || {};
   510    }
   511  
   512    function stage(state) {
   513      return state.ctx.stage || 0;
   514    }
   515  
   516    function phase(state) {
   517      return state.ctx.phase;
   518    }
   519  
   520    ///////////////////////////////////////////////////////////////////////////
   521    ///////////////////////////////////////////////////////////////////////////
   522  
   523    return {
   524      startState: function () {
   525        return {tok: to_normal, ctx: context(undefined, 0)};
   526      },
   527  
   528      copyState: function (state) {
   529        var ctx = state.ctx, tmp = state.tmp;
   530        if (ctx.local)
   531          ctx = {mode: ctx.mode, local: CodeMirror.copyState(ctx.mode, ctx.local)};
   532        if (tmp)
   533          tmp = {mode: tmp.mode, local: CodeMirror.copyState(tmp.mode, tmp.local)};
   534        return {tok: state.tok, ctx: ctx, tmp: tmp};
   535      },
   536  
   537      innerMode: function (state) {
   538        return state.tmp      ? {state: state.tmp.local, mode: state.tmp.mode}
   539        : state.ctx.mode ? {state: state.ctx.local, mode: state.ctx.mode}
   540        : null;
   541      },
   542  
   543      token: function (stream, state) {
   544        return state.tok(stream, state);
   545      }
   546    };
   547  }, 'python', 'stex');
   548  
   549  ///////////////////////////////////////////////////////////////////////////////
   550  ///////////////////////////////////////////////////////////////////////////////
   551  
   552  CodeMirror.defineMIME('text/x-rst', 'rst');
   553  
   554  ///////////////////////////////////////////////////////////////////////////////
   555  ///////////////////////////////////////////////////////////////////////////////
   556  
   557  });