openrat-cms

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

rst.js (17547B)


      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 });