github.com/jancarloviray/community@v0.41.1-0.20170124221257-33a66c87cf2f/app/public/codemirror/mode/tiki/tiki.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"));
     7    else if (typeof define == "function" && define.amd) // AMD
     8      define(["../../lib/codemirror"], mod);
     9    else // Plain browser env
    10      mod(CodeMirror);
    11  })(function(CodeMirror) {
    12  "use strict";
    13  
    14  CodeMirror.defineMode('tiki', function(config) {
    15    function inBlock(style, terminator, returnTokenizer) {
    16      return function(stream, state) {
    17        while (!stream.eol()) {
    18          if (stream.match(terminator)) {
    19            state.tokenize = inText;
    20            break;
    21          }
    22          stream.next();
    23        }
    24  
    25        if (returnTokenizer) state.tokenize = returnTokenizer;
    26  
    27        return style;
    28      };
    29    }
    30  
    31    function inLine(style) {
    32      return function(stream, state) {
    33        while(!stream.eol()) {
    34          stream.next();
    35        }
    36        state.tokenize = inText;
    37        return style;
    38      };
    39    }
    40  
    41    function inText(stream, state) {
    42      function chain(parser) {
    43        state.tokenize = parser;
    44        return parser(stream, state);
    45      }
    46  
    47      var sol = stream.sol();
    48      var ch = stream.next();
    49  
    50      //non start of line
    51      switch (ch) { //switch is generally much faster than if, so it is used here
    52      case "{": //plugin
    53        stream.eat("/");
    54        stream.eatSpace();
    55        stream.eatWhile(/[^\s\u00a0=\"\'\/?(}]/);
    56        state.tokenize = inPlugin;
    57        return "tag";
    58      case "_": //bold
    59        if (stream.eat("_"))
    60          return chain(inBlock("strong", "__", inText));
    61        break;
    62      case "'": //italics
    63        if (stream.eat("'"))
    64          return chain(inBlock("em", "''", inText));
    65        break;
    66      case "(":// Wiki Link
    67        if (stream.eat("("))
    68          return chain(inBlock("variable-2", "))", inText));
    69        break;
    70      case "[":// Weblink
    71        return chain(inBlock("variable-3", "]", inText));
    72        break;
    73      case "|": //table
    74        if (stream.eat("|"))
    75          return chain(inBlock("comment", "||"));
    76        break;
    77      case "-":
    78        if (stream.eat("=")) {//titleBar
    79          return chain(inBlock("header string", "=-", inText));
    80        } else if (stream.eat("-")) {//deleted
    81          return chain(inBlock("error tw-deleted", "--", inText));
    82        }
    83        break;
    84      case "=": //underline
    85        if (stream.match("=="))
    86          return chain(inBlock("tw-underline", "===", inText));
    87        break;
    88      case ":":
    89        if (stream.eat(":"))
    90          return chain(inBlock("comment", "::"));
    91        break;
    92      case "^": //box
    93        return chain(inBlock("tw-box", "^"));
    94        break;
    95      case "~": //np
    96        if (stream.match("np~"))
    97          return chain(inBlock("meta", "~/np~"));
    98        break;
    99      }
   100  
   101      //start of line types
   102      if (sol) {
   103        switch (ch) {
   104        case "!": //header at start of line
   105          if (stream.match('!!!!!')) {
   106            return chain(inLine("header string"));
   107          } else if (stream.match('!!!!')) {
   108            return chain(inLine("header string"));
   109          } else if (stream.match('!!!')) {
   110            return chain(inLine("header string"));
   111          } else if (stream.match('!!')) {
   112            return chain(inLine("header string"));
   113          } else {
   114            return chain(inLine("header string"));
   115          }
   116          break;
   117        case "*": //unordered list line item, or <li /> at start of line
   118        case "#": //ordered list line item, or <li /> at start of line
   119        case "+": //ordered list line item, or <li /> at start of line
   120          return chain(inLine("tw-listitem bracket"));
   121          break;
   122        }
   123      }
   124  
   125      //stream.eatWhile(/[&{]/); was eating up plugins, turned off to act less like html and more like tiki
   126      return null;
   127    }
   128  
   129    var indentUnit = config.indentUnit;
   130  
   131    // Return variables for tokenizers
   132    var pluginName, type;
   133    function inPlugin(stream, state) {
   134      var ch = stream.next();
   135      var peek = stream.peek();
   136  
   137      if (ch == "}") {
   138        state.tokenize = inText;
   139        //type = ch == ")" ? "endPlugin" : "selfclosePlugin"; inPlugin
   140        return "tag";
   141      } else if (ch == "(" || ch == ")") {
   142        return "bracket";
   143      } else if (ch == "=") {
   144        type = "equals";
   145  
   146        if (peek == ">") {
   147          ch = stream.next();
   148          peek = stream.peek();
   149        }
   150  
   151        //here we detect values directly after equal character with no quotes
   152        if (!/[\'\"]/.test(peek)) {
   153          state.tokenize = inAttributeNoQuote();
   154        }
   155        //end detect values
   156  
   157        return "operator";
   158      } else if (/[\'\"]/.test(ch)) {
   159        state.tokenize = inAttribute(ch);
   160        return state.tokenize(stream, state);
   161      } else {
   162        stream.eatWhile(/[^\s\u00a0=\"\'\/?]/);
   163        return "keyword";
   164      }
   165    }
   166  
   167    function inAttribute(quote) {
   168      return function(stream, state) {
   169        while (!stream.eol()) {
   170          if (stream.next() == quote) {
   171            state.tokenize = inPlugin;
   172            break;
   173          }
   174        }
   175        return "string";
   176      };
   177    }
   178  
   179    function inAttributeNoQuote() {
   180      return function(stream, state) {
   181        while (!stream.eol()) {
   182          var ch = stream.next();
   183          var peek = stream.peek();
   184          if (ch == " " || ch == "," || /[ )}]/.test(peek)) {
   185        state.tokenize = inPlugin;
   186        break;
   187      }
   188    }
   189    return "string";
   190  };
   191                       }
   192  
   193  var curState, setStyle;
   194  function pass() {
   195    for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);
   196  }
   197  
   198  function cont() {
   199    pass.apply(null, arguments);
   200    return true;
   201  }
   202  
   203  function pushContext(pluginName, startOfLine) {
   204    var noIndent = curState.context && curState.context.noIndent;
   205    curState.context = {
   206      prev: curState.context,
   207      pluginName: pluginName,
   208      indent: curState.indented,
   209      startOfLine: startOfLine,
   210      noIndent: noIndent
   211    };
   212  }
   213  
   214  function popContext() {
   215    if (curState.context) curState.context = curState.context.prev;
   216  }
   217  
   218  function element(type) {
   219    if (type == "openPlugin") {curState.pluginName = pluginName; return cont(attributes, endplugin(curState.startOfLine));}
   220    else if (type == "closePlugin") {
   221      var err = false;
   222      if (curState.context) {
   223        err = curState.context.pluginName != pluginName;
   224        popContext();
   225      } else {
   226        err = true;
   227      }
   228      if (err) setStyle = "error";
   229      return cont(endcloseplugin(err));
   230    }
   231    else if (type == "string") {
   232      if (!curState.context || curState.context.name != "!cdata") pushContext("!cdata");
   233      if (curState.tokenize == inText) popContext();
   234      return cont();
   235    }
   236    else return cont();
   237  }
   238  
   239  function endplugin(startOfLine) {
   240    return function(type) {
   241      if (
   242        type == "selfclosePlugin" ||
   243          type == "endPlugin"
   244      )
   245        return cont();
   246      if (type == "endPlugin") {pushContext(curState.pluginName, startOfLine); return cont();}
   247      return cont();
   248    };
   249  }
   250  
   251  function endcloseplugin(err) {
   252    return function(type) {
   253      if (err) setStyle = "error";
   254      if (type == "endPlugin") return cont();
   255      return pass();
   256    };
   257  }
   258  
   259  function attributes(type) {
   260    if (type == "keyword") {setStyle = "attribute"; return cont(attributes);}
   261    if (type == "equals") return cont(attvalue, attributes);
   262    return pass();
   263  }
   264  function attvalue(type) {
   265    if (type == "keyword") {setStyle = "string"; return cont();}
   266    if (type == "string") return cont(attvaluemaybe);
   267    return pass();
   268  }
   269  function attvaluemaybe(type) {
   270    if (type == "string") return cont(attvaluemaybe);
   271    else return pass();
   272  }
   273  return {
   274    startState: function() {
   275      return {tokenize: inText, cc: [], indented: 0, startOfLine: true, pluginName: null, context: null};
   276    },
   277    token: function(stream, state) {
   278      if (stream.sol()) {
   279        state.startOfLine = true;
   280        state.indented = stream.indentation();
   281      }
   282      if (stream.eatSpace()) return null;
   283  
   284      setStyle = type = pluginName = null;
   285      var style = state.tokenize(stream, state);
   286      if ((style || type) && style != "comment") {
   287        curState = state;
   288        while (true) {
   289          var comb = state.cc.pop() || element;
   290          if (comb(type || style)) break;
   291        }
   292      }
   293      state.startOfLine = false;
   294      return setStyle || style;
   295    },
   296    indent: function(state, textAfter) {
   297      var context = state.context;
   298      if (context && context.noIndent) return 0;
   299      if (context && /^{\//.test(textAfter))
   300          context = context.prev;
   301          while (context && !context.startOfLine)
   302            context = context.prev;
   303          if (context) return context.indent + indentUnit;
   304          else return 0;
   305         },
   306      electricChars: "/"
   307    };
   308  });
   309  
   310  CodeMirror.defineMIME("text/tiki", "tiki");
   311  
   312  });