all repos — NoPaste @ 3e3c433f026c49e04d0efa0f0f39fc688ed32bb1

Resurrected - The PussTheCat.org fork of NoPaste

scripts/CodeMirror/mode/rst/rst.js (view raw)

  1// CodeMirror, copyright (c) by Marijn Haverbeke and others
  2// Distributed under an MIT license: https://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
 14CodeMirror.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
 71CodeMirror.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
552CodeMirror.defineMIME('text/x-rst', 'rst');
553
554///////////////////////////////////////////////////////////////////////////////
555///////////////////////////////////////////////////////////////////////////////
556
557});