: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
* Author: Constantin Jucovschi (c.jucovschi@jacobs-university.de)
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
})(function(CodeMirror) {
CodeMirror.defineMode("stex", function() {
function pushCommand(state, command) {
state.cmdState.push(command);
function peekCommand(state) {
if (state.cmdState.length > 0) {
return state.cmdState[state.cmdState.length - 1];
function popCommand(state) {
var plug = state.cmdState.pop();
// returns the non-default plugin closest to the end of the list
function getMostPowerful(state) {
var context = state.cmdState;
for (var i = context.length - 1; i >= 0; i--) {
if (plug.name == "DEFAULT") {
return { styleIdentifier: function() { return null; } };
function addPluginPattern(pluginName, cmdStyle, styles) {
this.argument = null; // \begin and \end have arguments that follow. These are stored in the plugin
this.styleIdentifier = function() {
return this.styles[this.bracketNo - 1] || null;
this.openBracket = function() {
this.closeBracket = function() {};
plugins["importmodule"] = addPluginPattern("importmodule", "tag", ["string", "builtin"]);
plugins["documentclass"] = addPluginPattern("documentclass", "tag", ["", "atom"]);
plugins["usepackage"] = addPluginPattern("usepackage", "tag", ["atom"]);
plugins["begin"] = addPluginPattern("begin", "tag", ["atom"]);
plugins["end"] = addPluginPattern("end", "tag", ["atom"]);
plugins["DEFAULT"] = function () {
this.styleIdentifier = this.openBracket = this.closeBracket = function() {};
function setState(state, f) {
// called when in a normal (no environment) context
function normal(source, state) {
// Do we look like '\command' ? If so, attempt to apply the plugin 'command'
if (source.match(/^\\[a-zA-Z@]+/)) {
var cmdName = source.current().slice(1);
plug = plugins[cmdName] || plugins["DEFAULT"];
pushCommand(state, plug);
setState(state, beginParams);
if (source.match(/^\\[$&%#{}_]/)) {
// white space control characters
if (source.match(/^\\[,;!\/\\]/)) {
// find if we're starting various math modes
if (source.match("\\[")) {
setState(state, function(source, state){ return inMathMode(source, state, "\\]"); });
if (source.match("$$")) {
setState(state, function(source, state){ return inMathMode(source, state, "$$"); });
setState(state, function(source, state){ return inMathMode(source, state, "$"); });
} else if (ch == '}' || ch == ']') {
plug = peekCommand(state);
setState(state, beginParams);
} else if (ch == '{' || ch == '[') {
plug = plugins["DEFAULT"];
pushCommand(state, plug);
} else if (/\d/.test(ch)) {
source.eatWhile(/[\w.%]/);
source.eatWhile(/[\w\-_]/);
plug = getMostPowerful(state);
if (plug.name == 'begin') {
plug.argument = source.current();
return plug.styleIdentifier();
function inMathMode(source, state, endModeSeq) {
if (source.match(endModeSeq)) {
if (source.match(/^\\[a-zA-Z@]+/)) {
if (source.match(/^[a-zA-Z]+/)) {
if (source.match(/^\\[$&%#{}_]/)) {
// white space control characters
if (source.match(/^\\[,;!\/]/)) {
// special math-mode characters
if (source.match(/^[\^_&]/)) {
// non-special characters
if (source.match(/^[+\-<>|=,\/@!*:;'"`~#?]/)) {
if (source.match(/^(\d+\.\d*|\d*\.\d+|\d+)/)) {
if (ch == "{" || ch == "}" || ch == "[" || ch == "]" || ch == "(" || ch == ")") {
function beginParams(source, state) {
var ch = source.peek(), lastPlug;
if (ch == '{' || ch == '[') {
lastPlug = peekCommand(state);
lastPlug.openBracket(ch);
if (/[ \t\r]/.test(ch)) {
return normal(source, state);
cmdState: s.cmdState.slice(),
token: function(stream, state) {
return state.f(stream, state);
blankLine: function(state) {
state.cmdState.length = 0;
CodeMirror.defineMIME("text/x-stex", "stex");
CodeMirror.defineMIME("text/x-latex", "stex");