File modules/editor/codemirror/mode/rst/rst.js

Last commit: Sun Dec 17 01:14:09 2017 +0100	Jan Dankert	Integration eines weiteren Code-Editors: Codemirror. Demnächst müssen wir hier mal aufräumen und andere Editoren rauswerfen.
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 });
Download modules/editor/codemirror/mode/rst/rst.js
History Sun, 17 Dec 2017 01:14:09 +0100 Jan Dankert Integration eines weiteren Code-Editors: Codemirror. Demnächst müssen wir hier mal aufräumen und andere Editoren rauswerfen.