openrat-cms

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

tiki.js (8462B)


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