Passed
Push — master ( 3324e2...2ba76b )
by Ralf
13:44
created

tiki.js ➔ inText   F

Complexity

Conditions 19

Size

Total Lines 98
Code Lines 76

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 76
c 0
b 0
f 0
dl 0
loc 98
rs 0.5999
cc 19

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like tiki.js ➔ inText often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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
0 ignored issues
show
Bug introduced by
The variable define seems to be never declared. If this is a global, consider adding a /** global: define */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
8
    define(["../../lib/codemirror"], mod);
9
  else // Plain browser env
10
    mod(CodeMirror);
0 ignored issues
show
Bug introduced by
The variable CodeMirror seems to be never declared. If this is a global, consider adding a /** global: CodeMirror */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
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
      var tagName = "";
56
      var c;
57
      while ((c = stream.eat(/[^\s\u00a0=\"\'\/?(}]/))) tagName += c;
58
      state.tokenize = inPlugin;
59
      return "tag";
60
      break;
0 ignored issues
show
Unused Code introduced by
This break statement is unnecessary and may be removed.
Loading history...
61
    case "_": //bold
62
      if (stream.eat("_")) {
63
        return chain(inBlock("strong", "__", inText));
64
      }
65
      break;
66
    case "'": //italics
67
      if (stream.eat("'")) {
68
        // Italic text
69
        return chain(inBlock("em", "''", inText));
70
      }
71
      break;
72
    case "(":// Wiki Link
73
      if (stream.eat("(")) {
74
        return chain(inBlock("variable-2", "))", inText));
75
      }
76
      break;
77
    case "[":// Weblink
78
      return chain(inBlock("variable-3", "]", inText));
79
      break;
0 ignored issues
show
Unused Code introduced by
This break statement is unnecessary and may be removed.
Loading history...
80
    case "|": //table
81
      if (stream.eat("|")) {
82
        return chain(inBlock("comment", "||"));
83
      }
84
      break;
85
    case "-":
86
      if (stream.eat("=")) {//titleBar
87
        return chain(inBlock("header string", "=-", inText));
88
      } else if (stream.eat("-")) {//deleted
89
        return chain(inBlock("error tw-deleted", "--", inText));
90
      }
91
      break;
92
    case "=": //underline
93
      if (stream.match("==")) {
94
        return chain(inBlock("tw-underline", "===", inText));
95
      }
96
      break;
97
    case ":":
98
      if (stream.eat(":")) {
99
        return chain(inBlock("comment", "::"));
100
      }
101
      break;
102
    case "^": //box
103
      return chain(inBlock("tw-box", "^"));
104
      break;
0 ignored issues
show
Unused Code introduced by
This break statement is unnecessary and may be removed.
Loading history...
105
    case "~": //np
106
      if (stream.match("np~")) {
107
        return chain(inBlock("meta", "~/np~"));
108
      }
109
      break;
110
    }
111
112
    //start of line types
113
    if (sol) {
114
      switch (ch) {
115
      case "!": //header at start of line
116
        if (stream.match('!!!!!')) {
117
          return chain(inLine("header string"));
118
        } else if (stream.match('!!!!')) {
119
          return chain(inLine("header string"));
120
        } else if (stream.match('!!!')) {
121
          return chain(inLine("header string"));
122
        } else if (stream.match('!!')) {
123
          return chain(inLine("header string"));
124
        } else {
125
          return chain(inLine("header string"));
126
        }
127
        break;
0 ignored issues
show
Unused Code introduced by
This break statement is unnecessary and may be removed.
Loading history...
128
      case "*": //unordered list line item, or <li /> at start of line
129
      case "#": //ordered list line item, or <li /> at start of line
130
      case "+": //ordered list line item, or <li /> at start of line
131
        return chain(inLine("tw-listitem bracket"));
132
        break;
0 ignored issues
show
Unused Code introduced by
This break statement is unnecessary and may be removed.
Loading history...
133
      }
134
    }
135
136
    //stream.eatWhile(/[&{]/); was eating up plugins, turned off to act less like html and more like tiki
137
    return null;
138
  }
139
140
  var indentUnit = config.indentUnit;
141
142
  // Return variables for tokenizers
143
  var pluginName, type;
144
  function inPlugin(stream, state) {
145
    var ch = stream.next();
146
    var peek = stream.peek();
147
148
    if (ch == "}") {
149
      state.tokenize = inText;
150
      //type = ch == ")" ? "endPlugin" : "selfclosePlugin"; inPlugin
151
      return "tag";
152
    } else if (ch == "(" || ch == ")") {
153
      return "bracket";
154
    } else if (ch == "=") {
155
      type = "equals";
156
157
      if (peek == ">") {
158
        ch = stream.next();
0 ignored issues
show
Unused Code introduced by
The assignment to variable ch seems to be never used. Consider removing it.
Loading history...
159
        peek = stream.peek();
160
      }
161
162
      //here we detect values directly after equal character with no quotes
163
      if (!/[\'\"]/.test(peek)) {
164
        state.tokenize = inAttributeNoQuote();
165
      }
166
      //end detect values
167
168
      return "operator";
169
    } else if (/[\'\"]/.test(ch)) {
170
      state.tokenize = inAttribute(ch);
171
      return state.tokenize(stream, state);
172
    } else {
173
      stream.eatWhile(/[^\s\u00a0=\"\'\/?]/);
174
      return "keyword";
175
    }
176
  }
177
178
  function inAttribute(quote) {
179
    return function(stream, state) {
180
      while (!stream.eol()) {
181
        if (stream.next() == quote) {
182
          state.tokenize = inPlugin;
183
          break;
184
        }
185
      }
186
      return "string";
187
    };
188
  }
189
190
  function inAttributeNoQuote() {
191
    return function(stream, state) {
192
      while (!stream.eol()) {
193
        var ch = stream.next();
194
        var peek = stream.peek();
195
        if (ch == " " || ch == "," || /[ )}]/.test(peek)) {
196
      state.tokenize = inPlugin;
197
      break;
198
    }
199
  }
200
  return "string";
201
};
202
                     }
203
204
var curState, setStyle;
205
function pass() {
206
  for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);
207
}
208
209
function cont() {
210
  pass.apply(null, arguments);
211
  return true;
212
}
213
214
function pushContext(pluginName, startOfLine) {
215
  var noIndent = curState.context && curState.context.noIndent;
216
  curState.context = {
217
    prev: curState.context,
218
    pluginName: pluginName,
219
    indent: curState.indented,
220
    startOfLine: startOfLine,
221
    noIndent: noIndent
222
  };
223
}
224
225
function popContext() {
226
  if (curState.context) curState.context = curState.context.prev;
227
}
228
229
function element(type) {
230
  if (type == "openPlugin") {curState.pluginName = pluginName; return cont(attributes, endplugin(curState.startOfLine));}
231
  else if (type == "closePlugin") {
232
    var err = false;
0 ignored issues
show
Unused Code introduced by
The assignment to variable err seems to be never used. Consider removing it.
Loading history...
233
    if (curState.context) {
234
      err = curState.context.pluginName != pluginName;
235
      popContext();
236
    } else {
237
      err = true;
238
    }
239
    if (err) setStyle = "error";
240
    return cont(endcloseplugin(err));
241
  }
242
  else if (type == "string") {
243
    if (!curState.context || curState.context.name != "!cdata") pushContext("!cdata");
244
    if (curState.tokenize == inText) popContext();
245
    return cont();
246
  }
247
  else return cont();
248
}
249
250
function endplugin(startOfLine) {
251
  return function(type) {
252
    if (
253
      type == "selfclosePlugin" ||
254
        type == "endPlugin"
255
    )
256
      return cont();
257
    if (type == "endPlugin") {pushContext(curState.pluginName, startOfLine); return cont();}
258
    return cont();
259
  };
260
}
261
262
function endcloseplugin(err) {
263
  return function(type) {
264
    if (err) setStyle = "error";
265
    if (type == "endPlugin") return cont();
266
    return pass();
267
  };
268
}
269
270
function attributes(type) {
271
  if (type == "keyword") {setStyle = "attribute"; return cont(attributes);}
272
  if (type == "equals") return cont(attvalue, attributes);
273
  return pass();
274
}
275
function attvalue(type) {
276
  if (type == "keyword") {setStyle = "string"; return cont();}
277
  if (type == "string") return cont(attvaluemaybe);
278
  return pass();
279
}
280
function attvaluemaybe(type) {
281
  if (type == "string") return cont(attvaluemaybe);
282
  else return pass();
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
283
}
284
return {
285
  startState: function() {
286
    return {tokenize: inText, cc: [], indented: 0, startOfLine: true, pluginName: null, context: null};
287
  },
288
  token: function(stream, state) {
289
    if (stream.sol()) {
290
      state.startOfLine = true;
291
      state.indented = stream.indentation();
292
    }
293
    if (stream.eatSpace()) return null;
294
295
    setStyle = type = pluginName = null;
296
    var style = state.tokenize(stream, state);
297
    if ((style || type) && style != "comment") {
298
      curState = state;
299
      while (true) {
300
        var comb = state.cc.pop() || element;
301
        if (comb(type || style)) break;
302
      }
303
    }
304
    state.startOfLine = false;
305
    return setStyle || style;
306
  },
307
  indent: function(state, textAfter) {
308
    var context = state.context;
309
    if (context && context.noIndent) return 0;
310
    if (context && /^{\//.test(textAfter))
311
        context = context.prev;
312
        while (context && !context.startOfLine)
313
          context = context.prev;
314
        if (context) return context.indent + indentUnit;
315
        else return 0;
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
316
       },
317
    electricChars: "/"
318
  };
319
});
320
321
CodeMirror.defineMIME("text/tiki", "tiki");
322
323
});
324