Completed
Branch master (e8947e)
by Andreas
15:09
created

static/midcom.helper.datamanager2/codemirror-5.7.0/mode/tiddlywiki/tiddlywiki.js   F

Complexity

Total Complexity 93
Complexity/F 5.81

Size

Lines of Code 336
Function Count 16

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 0
nc 1572864
dl 0
loc 336
rs 1.9603
c 0
b 0
f 0
wmc 93
mnd 3
bc 70
fnc 16
bpm 4.375
cpm 5.8125
noi 2

How to fix   Complexity   

Complexity

Complex classes like static/midcom.helper.datamanager2/codemirror-5.7.0/mode/tiddlywiki/tiddlywiki.js 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
/***
5
    |''Name''|tiddlywiki.js|
6
    |''Description''|Enables TiddlyWikiy syntax highlighting using CodeMirror|
7
    |''Author''|PMario|
8
    |''Version''|0.1.7|
9
    |''Status''|''stable''|
10
    |''Source''|[[GitHub|https://github.com/pmario/CodeMirror2/blob/tw-syntax/mode/tiddlywiki]]|
11
    |''Documentation''|http://codemirror.tiddlyspace.com/|
12
    |''License''|[[MIT License|http://www.opensource.org/licenses/mit-license.php]]|
13
    |''CoreVersion''|2.5.0|
14
    |''Requires''|codemirror.js|
15
    |''Keywords''|syntax highlighting color code mirror codemirror|
16
    ! Info
17
    CoreVersion parameter is needed for TiddlyWiki only!
18
***/
19
//{{{
20
21
(function(mod) {
22
  if (typeof exports == "object" && typeof module == "object") // CommonJS
23
    mod(require("../../lib/codemirror"));
24
  else if (typeof define == "function" && define.amd) // AMD
25
    define(["../../lib/codemirror"], mod);
26
  else // Plain browser env
27
    mod(CodeMirror);
28
})(function(CodeMirror) {
29
"use strict";
30
31
CodeMirror.defineMode("tiddlywiki", function () {
32
  // Tokenizer
33
  var textwords = {};
34
35
  var keywords = function () {
36
    function kw(type) {
37
      return { type: type, style: "macro"};
38
    }
39
    return {
40
      "allTags": kw('allTags'), "closeAll": kw('closeAll'), "list": kw('list'),
41
      "newJournal": kw('newJournal'), "newTiddler": kw('newTiddler'),
42
      "permaview": kw('permaview'), "saveChanges": kw('saveChanges'),
43
      "search": kw('search'), "slider": kw('slider'),   "tabs": kw('tabs'),
44
      "tag": kw('tag'), "tagging": kw('tagging'),       "tags": kw('tags'),
45
      "tiddler": kw('tiddler'), "timeline": kw('timeline'),
46
      "today": kw('today'), "version": kw('version'),   "option": kw('option'),
47
48
      "with": kw('with'),
49
      "filter": kw('filter')
50
    };
51
  }();
52
53
  var isSpaceName = /[\w_\-]/i,
54
  reHR = /^\-\-\-\-+$/,                                 // <hr>
55
  reWikiCommentStart = /^\/\*\*\*$/,            // /***
56
  reWikiCommentStop = /^\*\*\*\/$/,             // ***/
57
  reBlockQuote = /^<<<$/,
58
59
  reJsCodeStart = /^\/\/\{\{\{$/,                       // //{{{ js block start
60
  reJsCodeStop = /^\/\/\}\}\}$/,                        // //}}} js stop
61
  reXmlCodeStart = /^<!--\{\{\{-->$/,           // xml block start
62
  reXmlCodeStop = /^<!--\}\}\}-->$/,            // xml stop
63
64
  reCodeBlockStart = /^\{\{\{$/,                        // {{{ TW text div block start
65
  reCodeBlockStop = /^\}\}\}$/,                 // }}} TW text stop
66
67
  reUntilCodeStop = /.*?\}\}\}/;
68
69
  function chain(stream, state, f) {
70
    state.tokenize = f;
71
    return f(stream, state);
72
  }
73
74
  function jsTokenBase(stream, state) {
75
    var sol = stream.sol(), ch;
76
77
    state.block = false;        // indicates the start of a code block.
78
79
    ch = stream.peek();         // don't eat, to make matching simpler
80
81
    // check start of  blocks
82
    if (sol && /[<\/\*{}\-]/.test(ch)) {
83
      if (stream.match(reCodeBlockStart)) {
84
        state.block = true;
85
        return chain(stream, state, twTokenCode);
86
      }
87
      if (stream.match(reBlockQuote)) {
88
        return 'quote';
89
      }
90
      if (stream.match(reWikiCommentStart) || stream.match(reWikiCommentStop)) {
91
        return 'comment';
92
      }
93
      if (stream.match(reJsCodeStart) || stream.match(reJsCodeStop) || stream.match(reXmlCodeStart) || stream.match(reXmlCodeStop)) {
94
        return 'comment';
95
      }
96
      if (stream.match(reHR)) {
97
        return 'hr';
98
      }
99
    } // sol
100
    ch = stream.next();
101
102
    if (sol && /[\/\*!#;:>|]/.test(ch)) {
103
      if (ch == "!") { // tw header
104
        stream.skipToEnd();
105
        return "header";
106
      }
107
      if (ch == "*") { // tw list
108
        stream.eatWhile('*');
109
        return "comment";
110
      }
111
      if (ch == "#") { // tw numbered list
112
        stream.eatWhile('#');
113
        return "comment";
114
      }
115
      if (ch == ";") { // definition list, term
116
        stream.eatWhile(';');
117
        return "comment";
118
      }
119
      if (ch == ":") { // definition list, description
120
        stream.eatWhile(':');
121
        return "comment";
122
      }
123
      if (ch == ">") { // single line quote
124
        stream.eatWhile(">");
125
        return "quote";
126
      }
127
      if (ch == '|') {
128
        return 'header';
129
      }
130
    }
131
132
    if (ch == '{' && stream.match(/\{\{/)) {
133
      return chain(stream, state, twTokenCode);
134
    }
135
136
    // rudimentary html:// file:// link matching. TW knows much more ...
137
    if (/[hf]/i.test(ch)) {
138
      if (/[ti]/i.test(stream.peek()) && stream.match(/\b(ttps?|tp|ile):\/\/[\-A-Z0-9+&@#\/%?=~_|$!:,.;]*[A-Z0-9+&@#\/%=~_|$]/i)) {
139
        return "link";
140
      }
141
    }
142
    // just a little string indicator, don't want to have the whole string covered
143
    if (ch == '"') {
144
      return 'string';
145
    }
146
    if (ch == '~') {    // _no_ CamelCase indicator should be bold
147
      return 'brace';
148
    }
149
    if (/[\[\]]/.test(ch)) { // check for [[..]]
150
      if (stream.peek() == ch) {
151
        stream.next();
152
        return 'brace';
153
      }
154
    }
155
    if (ch == "@") {    // check for space link. TODO fix @@...@@ highlighting
156
      stream.eatWhile(isSpaceName);
157
      return "link";
158
    }
159
    if (/\d/.test(ch)) {        // numbers
160
      stream.eatWhile(/\d/);
161
      return "number";
162
    }
163
    if (ch == "/") { // tw invisible comment
164
      if (stream.eat("%")) {
165
        return chain(stream, state, twTokenComment);
166
      }
167
      else if (stream.eat("/")) { //
168
        return chain(stream, state, twTokenEm);
169
      }
170
    }
171
    if (ch == "_") { // tw underline
172
      if (stream.eat("_")) {
173
        return chain(stream, state, twTokenUnderline);
174
      }
175
    }
176
    // strikethrough and mdash handling
177
    if (ch == "-") {
178
      if (stream.eat("-")) {
179
        // if strikethrough looks ugly, change CSS.
180
        if (stream.peek() != ' ')
181
          return chain(stream, state, twTokenStrike);
182
        // mdash
183
        if (stream.peek() == ' ')
184
          return 'brace';
185
      }
186
    }
187
    if (ch == "'") { // tw bold
188
      if (stream.eat("'")) {
189
        return chain(stream, state, twTokenStrong);
190
      }
191
    }
192
    if (ch == "<") { // tw macro
193
      if (stream.eat("<")) {
194
        return chain(stream, state, twTokenMacro);
195
      }
196
    }
197
    else {
198
      return null;
199
    }
200
201
    // core macro handling
202
    stream.eatWhile(/[\w\$_]/);
203
    var word = stream.current(),
204
    known = textwords.propertyIsEnumerable(word) && textwords[word];
205
206
    return known ? known.style : null;
207
  } // jsTokenBase()
208
209
  // tw invisible comment
210
  function twTokenComment(stream, state) {
211
    var maybeEnd = false,
212
    ch;
213
    while (ch = stream.next()) {
214
      if (ch == "/" && maybeEnd) {
215
        state.tokenize = jsTokenBase;
216
        break;
217
      }
218
      maybeEnd = (ch == "%");
219
    }
220
    return "comment";
221
  }
222
223
  // tw strong / bold
224
  function twTokenStrong(stream, state) {
225
    var maybeEnd = false,
226
    ch;
227
    while (ch = stream.next()) {
228
      if (ch == "'" && maybeEnd) {
229
        state.tokenize = jsTokenBase;
230
        break;
231
      }
232
      maybeEnd = (ch == "'");
233
    }
234
    return "strong";
235
  }
236
237
  // tw code
238
  function twTokenCode(stream, state) {
239
    var sb = state.block;
240
241
    if (sb && stream.current()) {
242
      return "comment";
243
    }
244
245
    if (!sb && stream.match(reUntilCodeStop)) {
246
      state.tokenize = jsTokenBase;
247
      return "comment";
248
    }
249
250
    if (sb && stream.sol() && stream.match(reCodeBlockStop)) {
251
      state.tokenize = jsTokenBase;
252
      return "comment";
253
    }
254
255
    stream.next();
256
    return "comment";
257
  }
258
259
  // tw em / italic
260
  function twTokenEm(stream, state) {
261
    var maybeEnd = false,
262
    ch;
263
    while (ch = stream.next()) {
264
      if (ch == "/" && maybeEnd) {
265
        state.tokenize = jsTokenBase;
266
        break;
267
      }
268
      maybeEnd = (ch == "/");
269
    }
270
    return "em";
271
  }
272
273
  // tw underlined text
274
  function twTokenUnderline(stream, state) {
275
    var maybeEnd = false,
276
    ch;
277
    while (ch = stream.next()) {
278
      if (ch == "_" && maybeEnd) {
279
        state.tokenize = jsTokenBase;
280
        break;
281
      }
282
      maybeEnd = (ch == "_");
283
    }
284
    return "underlined";
285
  }
286
287
  // tw strike through text looks ugly
288
  // change CSS if needed
289
  function twTokenStrike(stream, state) {
290
    var maybeEnd = false, ch;
291
292
    while (ch = stream.next()) {
293
      if (ch == "-" && maybeEnd) {
294
        state.tokenize = jsTokenBase;
295
        break;
296
      }
297
      maybeEnd = (ch == "-");
298
    }
299
    return "strikethrough";
300
  }
301
302
  // macro
303
  function twTokenMacro(stream, state) {
304
    var ch, word, known;
305
306
    if (stream.current() == '<<') {
307
      return 'macro';
308
    }
309
310
    ch = stream.next();
311
    if (!ch) {
312
      state.tokenize = jsTokenBase;
313
      return null;
314
    }
315
    if (ch == ">") {
316
      if (stream.peek() == '>') {
317
        stream.next();
318
        state.tokenize = jsTokenBase;
319
        return "macro";
320
      }
321
    }
322
323
    stream.eatWhile(/[\w\$_]/);
324
    word = stream.current();
325
    known = keywords.propertyIsEnumerable(word) && keywords[word];
326
327
    if (known) {
328
      return known.style, word;
329
    }
330
    else {
331
      return null, word;
332
    }
333
  }
334
335
  // Interface
336
  return {
337
    startState: function () {
338
      return {
339
        tokenize: jsTokenBase,
340
        indented: 0,
341
        level: 0
342
      };
343
    },
344
345
    token: function (stream, state) {
346
      if (stream.eatSpace()) return null;
347
      var style = state.tokenize(stream, state);
348
      return style;
349
    },
350
351
    electricChars: ""
352
  };
353
});
354
355
CodeMirror.defineMIME("text/x-tiddlywiki", "tiddlywiki");
356
});
357
358
//}}}
359