Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
malwaredllc
GitHub Repository: malwaredllc/byob
Path: blob/master/web-gui/buildyourownbotnet/assets/js/codemirror/mode/markdown/markdown.js
1294 views
1
CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
2
3
var htmlFound = CodeMirror.modes.hasOwnProperty("xml");
4
var htmlMode = CodeMirror.getMode(cmCfg, htmlFound ? {name: "xml", htmlMode: true} : "text/plain");
5
var aliases = {
6
html: "htmlmixed",
7
js: "javascript",
8
json: "application/json",
9
c: "text/x-csrc",
10
"c++": "text/x-c++src",
11
java: "text/x-java",
12
csharp: "text/x-csharp",
13
"c#": "text/x-csharp",
14
scala: "text/x-scala"
15
};
16
17
var getMode = (function () {
18
var i, modes = {}, mimes = {}, mime;
19
20
var list = [];
21
for (var m in CodeMirror.modes)
22
if (CodeMirror.modes.propertyIsEnumerable(m)) list.push(m);
23
for (i = 0; i < list.length; i++) {
24
modes[list[i]] = list[i];
25
}
26
var mimesList = [];
27
for (var m in CodeMirror.mimeModes)
28
if (CodeMirror.mimeModes.propertyIsEnumerable(m))
29
mimesList.push({mime: m, mode: CodeMirror.mimeModes[m]});
30
for (i = 0; i < mimesList.length; i++) {
31
mime = mimesList[i].mime;
32
mimes[mime] = mimesList[i].mime;
33
}
34
35
for (var a in aliases) {
36
if (aliases[a] in modes || aliases[a] in mimes)
37
modes[a] = aliases[a];
38
}
39
40
return function (lang) {
41
return modes[lang] ? CodeMirror.getMode(cmCfg, modes[lang]) : null;
42
};
43
}());
44
45
// Should characters that affect highlighting be highlighted separate?
46
// Does not include characters that will be output (such as `1.` and `-` for lists)
47
if (modeCfg.highlightFormatting === undefined)
48
modeCfg.highlightFormatting = false;
49
50
// Maximum number of nested blockquotes. Set to 0 for infinite nesting.
51
// Excess `>` will emit `error` token.
52
if (modeCfg.maxBlockquoteDepth === undefined)
53
modeCfg.maxBlockquoteDepth = 0;
54
55
// Should underscores in words open/close em/strong?
56
if (modeCfg.underscoresBreakWords === undefined)
57
modeCfg.underscoresBreakWords = true;
58
59
// Turn on fenced code blocks? ("```" to start/end)
60
if (modeCfg.fencedCodeBlocks === undefined) modeCfg.fencedCodeBlocks = false;
61
62
// Turn on task lists? ("- [ ] " and "- [x] ")
63
if (modeCfg.taskLists === undefined) modeCfg.taskLists = false;
64
65
var codeDepth = 0;
66
67
var header = 'header'
68
, code = 'comment'
69
, quote = 'quote'
70
, list1 = 'variable-2'
71
, list2 = 'variable-3'
72
, list3 = 'keyword'
73
, hr = 'hr'
74
, image = 'tag'
75
, formatting = 'formatting'
76
, linkinline = 'link'
77
, linkemail = 'link'
78
, linktext = 'link'
79
, linkhref = 'string'
80
, em = 'em'
81
, strong = 'strong';
82
83
var hrRE = /^([*\-=_])(?:\s*\1){2,}\s*$/
84
, ulRE = /^[*\-+]\s+/
85
, olRE = /^[0-9]+\.\s+/
86
, taskListRE = /^\[(x| )\](?=\s)/ // Must follow ulRE or olRE
87
, atxHeaderRE = /^#+/
88
, setextHeaderRE = /^(?:\={1,}|-{1,})$/
89
, textRE = /^[^#!\[\]*_\\<>` "'(]+/;
90
91
function switchInline(stream, state, f) {
92
state.f = state.inline = f;
93
return f(stream, state);
94
}
95
96
function switchBlock(stream, state, f) {
97
state.f = state.block = f;
98
return f(stream, state);
99
}
100
101
102
// Blocks
103
104
function blankLine(state) {
105
// Reset linkTitle state
106
state.linkTitle = false;
107
// Reset EM state
108
state.em = false;
109
// Reset STRONG state
110
state.strong = false;
111
// Reset state.quote
112
state.quote = 0;
113
if (!htmlFound && state.f == htmlBlock) {
114
state.f = inlineNormal;
115
state.block = blockNormal;
116
}
117
// Reset state.trailingSpace
118
state.trailingSpace = 0;
119
state.trailingSpaceNewLine = false;
120
// Mark this line as blank
121
state.thisLineHasContent = false;
122
return null;
123
}
124
125
function blockNormal(stream, state) {
126
127
var sol = stream.sol();
128
129
var prevLineIsList = (state.list !== false);
130
if (state.list !== false && state.indentationDiff >= 0) { // Continued list
131
if (state.indentationDiff < 4) { // Only adjust indentation if *not* a code block
132
state.indentation -= state.indentationDiff;
133
}
134
state.list = null;
135
} else if (state.list !== false && state.indentation > 0) {
136
state.list = null;
137
state.listDepth = Math.floor(state.indentation / 4);
138
} else if (state.list !== false) { // No longer a list
139
state.list = false;
140
state.listDepth = 0;
141
}
142
143
var match = null;
144
if (state.indentationDiff >= 4) {
145
state.indentation -= 4;
146
stream.skipToEnd();
147
return code;
148
} else if (stream.eatSpace()) {
149
return null;
150
} else if (match = stream.match(atxHeaderRE)) {
151
state.header = match[0].length <= 6 ? match[0].length : 6;
152
if (modeCfg.highlightFormatting) state.formatting = "header";
153
state.f = state.inline;
154
return getType(state);
155
} else if (state.prevLineHasContent && (match = stream.match(setextHeaderRE))) {
156
state.header = match[0].charAt(0) == '=' ? 1 : 2;
157
if (modeCfg.highlightFormatting) state.formatting = "header";
158
state.f = state.inline;
159
return getType(state);
160
} else if (stream.eat('>')) {
161
state.indentation++;
162
state.quote = sol ? 1 : state.quote + 1;
163
if (modeCfg.highlightFormatting) state.formatting = "quote";
164
stream.eatSpace();
165
return getType(state);
166
} else if (stream.peek() === '[') {
167
return switchInline(stream, state, footnoteLink);
168
} else if (stream.match(hrRE, true)) {
169
return hr;
170
} else if ((!state.prevLineHasContent || prevLineIsList) && (stream.match(ulRE, false) || stream.match(olRE, false))) {
171
var listType = null;
172
if (stream.match(ulRE, true)) {
173
listType = 'ul';
174
} else {
175
stream.match(olRE, true);
176
listType = 'ol';
177
}
178
state.indentation += 4;
179
state.list = true;
180
state.listDepth++;
181
if (modeCfg.taskLists && stream.match(taskListRE, false)) {
182
state.taskList = true;
183
}
184
state.f = state.inline;
185
if (modeCfg.highlightFormatting) state.formatting = ["list", "list-" + listType];
186
return getType(state);
187
} else if (modeCfg.fencedCodeBlocks && stream.match(/^```([\w+#]*)/, true)) {
188
// try switching mode
189
state.localMode = getMode(RegExp.$1);
190
if (state.localMode) state.localState = state.localMode.startState();
191
switchBlock(stream, state, local);
192
if (modeCfg.highlightFormatting) state.formatting = "code-block";
193
state.code = true;
194
return getType(state);
195
}
196
197
return switchInline(stream, state, state.inline);
198
}
199
200
function htmlBlock(stream, state) {
201
var style = htmlMode.token(stream, state.htmlState);
202
if ((htmlFound && !state.htmlState.tagName && !state.htmlState.context) ||
203
(state.md_inside && stream.current().indexOf(">") > -1)) {
204
state.f = inlineNormal;
205
state.block = blockNormal;
206
state.htmlState = null;
207
}
208
return style;
209
}
210
211
function local(stream, state) {
212
if (stream.sol() && stream.match(/^```/, true)) {
213
state.localMode = state.localState = null;
214
state.f = inlineNormal;
215
state.block = blockNormal;
216
if (modeCfg.highlightFormatting) state.formatting = "code-block";
217
state.code = true;
218
var returnType = getType(state);
219
state.code = false;
220
return returnType;
221
} else if (state.localMode) {
222
return state.localMode.token(stream, state.localState);
223
} else {
224
stream.skipToEnd();
225
return code;
226
}
227
}
228
229
// Inline
230
function getType(state) {
231
var styles = [];
232
233
if (state.formatting) {
234
styles.push(formatting);
235
236
if (typeof state.formatting === "string") state.formatting = [state.formatting];
237
238
for (var i = 0; i < state.formatting.length; i++) {
239
styles.push(formatting + "-" + state.formatting[i]);
240
241
if (state.formatting[i] === "header") {
242
styles.push(formatting + "-" + state.formatting[i] + state.header);
243
}
244
245
// Add `formatting-quote` and `formatting-quote-#` for blockquotes
246
// Add `error` instead if the maximum blockquote nesting depth is passed
247
if (state.formatting[i] === "quote") {
248
if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
249
styles.push(formatting + "-" + state.formatting[i] + "-" + state.quote);
250
} else {
251
styles.push("error");
252
}
253
}
254
}
255
}
256
257
if (state.taskOpen) {
258
styles.push("meta");
259
return styles.length ? styles.join(' ') : null;
260
}
261
if (state.taskClosed) {
262
styles.push("property");
263
return styles.length ? styles.join(' ') : null;
264
}
265
266
if (state.linkHref) {
267
styles.push(linkhref);
268
return styles.length ? styles.join(' ') : null;
269
}
270
271
if (state.strong) { styles.push(strong); }
272
if (state.em) { styles.push(em); }
273
274
if (state.linkText) { styles.push(linktext); }
275
276
if (state.code) { styles.push(code); }
277
278
if (state.header) { styles.push(header); styles.push(header + state.header); }
279
280
if (state.quote) {
281
styles.push(quote);
282
283
// Add `quote-#` where the maximum for `#` is modeCfg.maxBlockquoteDepth
284
if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
285
styles.push(quote + "-" + state.quote);
286
} else {
287
styles.push(quote + "-" + modeCfg.maxBlockquoteDepth);
288
}
289
}
290
291
if (state.list !== false) {
292
var listMod = (state.listDepth - 1) % 3;
293
if (!listMod) {
294
styles.push(list1);
295
} else if (listMod === 1) {
296
styles.push(list2);
297
} else {
298
styles.push(list3);
299
}
300
}
301
302
if (state.trailingSpaceNewLine) {
303
styles.push("trailing-space-new-line");
304
} else if (state.trailingSpace) {
305
styles.push("trailing-space-" + (state.trailingSpace % 2 ? "a" : "b"));
306
}
307
308
return styles.length ? styles.join(' ') : null;
309
}
310
311
function handleText(stream, state) {
312
if (stream.match(textRE, true)) {
313
return getType(state);
314
}
315
return undefined;
316
}
317
318
function inlineNormal(stream, state) {
319
var style = state.text(stream, state);
320
if (typeof style !== 'undefined')
321
return style;
322
323
if (state.list) { // List marker (*, +, -, 1., etc)
324
state.list = null;
325
return getType(state);
326
}
327
328
if (state.taskList) {
329
var taskOpen = stream.match(taskListRE, true)[1] !== "x";
330
if (taskOpen) state.taskOpen = true;
331
else state.taskClosed = true;
332
if (modeCfg.highlightFormatting) state.formatting = "task";
333
state.taskList = false;
334
return getType(state);
335
}
336
337
state.taskOpen = false;
338
state.taskClosed = false;
339
340
if (state.header && stream.match(/^#+$/, true)) {
341
if (modeCfg.highlightFormatting) state.formatting = "header";
342
return getType(state);
343
}
344
345
// Get sol() value now, before character is consumed
346
var sol = stream.sol();
347
348
var ch = stream.next();
349
350
if (state.escape) {
351
state.escape = false;
352
return getType(state);
353
}
354
355
if (ch === '\\') {
356
if (modeCfg.highlightFormatting) state.formatting = "escape";
357
state.escape = true;
358
return getType(state);
359
}
360
361
// Matches link titles present on next line
362
if (state.linkTitle) {
363
state.linkTitle = false;
364
var matchCh = ch;
365
if (ch === '(') {
366
matchCh = ')';
367
}
368
matchCh = (matchCh+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
369
var regex = '^\\s*(?:[^' + matchCh + '\\\\]+|\\\\\\\\|\\\\.)' + matchCh;
370
if (stream.match(new RegExp(regex), true)) {
371
return linkhref;
372
}
373
}
374
375
// If this block is changed, it may need to be updated in GFM mode
376
if (ch === '`') {
377
var previousFormatting = state.formatting;
378
if (modeCfg.highlightFormatting) state.formatting = "code";
379
var t = getType(state);
380
var before = stream.pos;
381
stream.eatWhile('`');
382
var difference = 1 + stream.pos - before;
383
if (!state.code) {
384
codeDepth = difference;
385
state.code = true;
386
return getType(state);
387
} else {
388
if (difference === codeDepth) { // Must be exact
389
state.code = false;
390
return t;
391
}
392
state.formatting = previousFormatting;
393
return getType(state);
394
}
395
} else if (state.code) {
396
return getType(state);
397
}
398
399
if (ch === '!' && stream.match(/\[[^\]]*\] ?(?:\(|\[)/, false)) {
400
stream.match(/\[[^\]]*\]/);
401
state.inline = state.f = linkHref;
402
return image;
403
}
404
405
if (ch === '[' && stream.match(/.*\](\(| ?\[)/, false)) {
406
state.linkText = true;
407
if (modeCfg.highlightFormatting) state.formatting = "link";
408
return getType(state);
409
}
410
411
if (ch === ']' && state.linkText) {
412
if (modeCfg.highlightFormatting) state.formatting = "link";
413
var type = getType(state);
414
state.linkText = false;
415
state.inline = state.f = linkHref;
416
return type;
417
}
418
419
if (ch === '<' && stream.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/, false)) {
420
state.f = state.inline = linkInline;
421
if (modeCfg.highlightFormatting) state.formatting = "link";
422
var type = getType(state);
423
if (type){
424
type += " ";
425
} else {
426
type = "";
427
}
428
return type + linkinline;
429
}
430
431
if (ch === '<' && stream.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/, false)) {
432
state.f = state.inline = linkInline;
433
if (modeCfg.highlightFormatting) state.formatting = "link";
434
var type = getType(state);
435
if (type){
436
type += " ";
437
} else {
438
type = "";
439
}
440
return type + linkemail;
441
}
442
443
if (ch === '<' && stream.match(/^\w/, false)) {
444
if (stream.string.indexOf(">") != -1) {
445
var atts = stream.string.substring(1,stream.string.indexOf(">"));
446
if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) {
447
state.md_inside = true;
448
}
449
}
450
stream.backUp(1);
451
state.htmlState = CodeMirror.startState(htmlMode);
452
return switchBlock(stream, state, htmlBlock);
453
}
454
455
if (ch === '<' && stream.match(/^\/\w*?>/)) {
456
state.md_inside = false;
457
return "tag";
458
}
459
460
var ignoreUnderscore = false;
461
if (!modeCfg.underscoresBreakWords) {
462
if (ch === '_' && stream.peek() !== '_' && stream.match(/(\w)/, false)) {
463
var prevPos = stream.pos - 2;
464
if (prevPos >= 0) {
465
var prevCh = stream.string.charAt(prevPos);
466
if (prevCh !== '_' && prevCh.match(/(\w)/, false)) {
467
ignoreUnderscore = true;
468
}
469
}
470
}
471
}
472
if (ch === '*' || (ch === '_' && !ignoreUnderscore)) {
473
if (sol && stream.peek() === ' ') {
474
// Do nothing, surrounded by newline and space
475
} else if (state.strong === ch && stream.eat(ch)) { // Remove STRONG
476
if (modeCfg.highlightFormatting) state.formatting = "strong";
477
var t = getType(state);
478
state.strong = false;
479
return t;
480
} else if (!state.strong && stream.eat(ch)) { // Add STRONG
481
state.strong = ch;
482
if (modeCfg.highlightFormatting) state.formatting = "strong";
483
return getType(state);
484
} else if (state.em === ch) { // Remove EM
485
if (modeCfg.highlightFormatting) state.formatting = "em";
486
var t = getType(state);
487
state.em = false;
488
return t;
489
} else if (!state.em) { // Add EM
490
state.em = ch;
491
if (modeCfg.highlightFormatting) state.formatting = "em";
492
return getType(state);
493
}
494
} else if (ch === ' ') {
495
if (stream.eat('*') || stream.eat('_')) { // Probably surrounded by spaces
496
if (stream.peek() === ' ') { // Surrounded by spaces, ignore
497
return getType(state);
498
} else { // Not surrounded by spaces, back up pointer
499
stream.backUp(1);
500
}
501
}
502
}
503
504
if (ch === ' ') {
505
if (stream.match(/ +$/, false)) {
506
state.trailingSpace++;
507
} else if (state.trailingSpace) {
508
state.trailingSpaceNewLine = true;
509
}
510
}
511
512
return getType(state);
513
}
514
515
function linkInline(stream, state) {
516
var ch = stream.next();
517
518
if (ch === ">") {
519
state.f = state.inline = inlineNormal;
520
if (modeCfg.highlightFormatting) state.formatting = "link";
521
var type = getType(state);
522
if (type){
523
type += " ";
524
} else {
525
type = "";
526
}
527
return type + linkinline;
528
}
529
530
stream.match(/^[^>]+/, true);
531
532
return linkinline;
533
}
534
535
function linkHref(stream, state) {
536
// Check if space, and return NULL if so (to avoid marking the space)
537
if(stream.eatSpace()){
538
return null;
539
}
540
var ch = stream.next();
541
if (ch === '(' || ch === '[') {
542
state.f = state.inline = getLinkHrefInside(ch === "(" ? ")" : "]");
543
if (modeCfg.highlightFormatting) state.formatting = "link-string";
544
state.linkHref = true;
545
return getType(state);
546
}
547
return 'error';
548
}
549
550
function getLinkHrefInside(endChar) {
551
return function(stream, state) {
552
var ch = stream.next();
553
554
if (ch === endChar) {
555
state.f = state.inline = inlineNormal;
556
if (modeCfg.highlightFormatting) state.formatting = "link-string";
557
var returnState = getType(state);
558
state.linkHref = false;
559
return returnState;
560
}
561
562
if (stream.match(inlineRE(endChar), true)) {
563
stream.backUp(1);
564
}
565
566
state.linkHref = true;
567
return getType(state);
568
};
569
}
570
571
function footnoteLink(stream, state) {
572
if (stream.match(/^[^\]]*\]:/, false)) {
573
state.f = footnoteLinkInside;
574
stream.next(); // Consume [
575
if (modeCfg.highlightFormatting) state.formatting = "link";
576
state.linkText = true;
577
return getType(state);
578
}
579
return switchInline(stream, state, inlineNormal);
580
}
581
582
function footnoteLinkInside(stream, state) {
583
if (stream.match(/^\]:/, true)) {
584
state.f = state.inline = footnoteUrl;
585
if (modeCfg.highlightFormatting) state.formatting = "link";
586
var returnType = getType(state);
587
state.linkText = false;
588
return returnType;
589
}
590
591
stream.match(/^[^\]]+/, true);
592
593
return linktext;
594
}
595
596
function footnoteUrl(stream, state) {
597
// Check if space, and return NULL if so (to avoid marking the space)
598
if(stream.eatSpace()){
599
return null;
600
}
601
// Match URL
602
stream.match(/^[^\s]+/, true);
603
// Check for link title
604
if (stream.peek() === undefined) { // End of line, set flag to check next line
605
state.linkTitle = true;
606
} else { // More content on line, check if link title
607
stream.match(/^(?:\s+(?:"(?:[^"\\]|\\\\|\\.)+"|'(?:[^'\\]|\\\\|\\.)+'|\((?:[^)\\]|\\\\|\\.)+\)))?/, true);
608
}
609
state.f = state.inline = inlineNormal;
610
return linkhref;
611
}
612
613
var savedInlineRE = [];
614
function inlineRE(endChar) {
615
if (!savedInlineRE[endChar]) {
616
// Escape endChar for RegExp (taken from http://stackoverflow.com/a/494122/526741)
617
endChar = (endChar+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
618
// Match any non-endChar, escaped character, as well as the closing
619
// endChar.
620
savedInlineRE[endChar] = new RegExp('^(?:[^\\\\]|\\\\.)*?(' + endChar + ')');
621
}
622
return savedInlineRE[endChar];
623
}
624
625
var mode = {
626
startState: function() {
627
return {
628
f: blockNormal,
629
630
prevLineHasContent: false,
631
thisLineHasContent: false,
632
633
block: blockNormal,
634
htmlState: null,
635
indentation: 0,
636
637
inline: inlineNormal,
638
text: handleText,
639
640
escape: false,
641
formatting: false,
642
linkText: false,
643
linkHref: false,
644
linkTitle: false,
645
em: false,
646
strong: false,
647
header: 0,
648
taskList: false,
649
list: false,
650
listDepth: 0,
651
quote: 0,
652
trailingSpace: 0,
653
trailingSpaceNewLine: false
654
};
655
},
656
657
copyState: function(s) {
658
return {
659
f: s.f,
660
661
prevLineHasContent: s.prevLineHasContent,
662
thisLineHasContent: s.thisLineHasContent,
663
664
block: s.block,
665
htmlState: s.htmlState && CodeMirror.copyState(htmlMode, s.htmlState),
666
indentation: s.indentation,
667
668
localMode: s.localMode,
669
localState: s.localMode ? CodeMirror.copyState(s.localMode, s.localState) : null,
670
671
inline: s.inline,
672
text: s.text,
673
escape: false,
674
formatting: false,
675
linkTitle: s.linkTitle,
676
em: s.em,
677
strong: s.strong,
678
header: s.header,
679
taskList: s.taskList,
680
list: s.list,
681
listDepth: s.listDepth,
682
quote: s.quote,
683
trailingSpace: s.trailingSpace,
684
trailingSpaceNewLine: s.trailingSpaceNewLine,
685
md_inside: s.md_inside
686
};
687
},
688
689
token: function(stream, state) {
690
691
// Reset state.formatting
692
state.formatting = false;
693
694
if (stream.sol()) {
695
var forceBlankLine = stream.match(/^\s*$/, true) || state.header;
696
697
// Reset state.header
698
state.header = 0;
699
700
if (forceBlankLine) {
701
state.prevLineHasContent = false;
702
return blankLine(state);
703
} else {
704
state.prevLineHasContent = state.thisLineHasContent;
705
state.thisLineHasContent = true;
706
}
707
708
// Reset state.escape
709
state.escape = false;
710
711
// Reset state.taskList
712
state.taskList = false;
713
714
// Reset state.code
715
state.code = false;
716
717
// Reset state.trailingSpace
718
state.trailingSpace = 0;
719
state.trailingSpaceNewLine = false;
720
721
state.f = state.block;
722
var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, ' ').length;
723
var difference = Math.floor((indentation - state.indentation) / 4) * 4;
724
if (difference > 4) difference = 4;
725
var adjustedIndentation = state.indentation + difference;
726
state.indentationDiff = adjustedIndentation - state.indentation;
727
state.indentation = adjustedIndentation;
728
if (indentation > 0) return null;
729
}
730
return state.f(stream, state);
731
},
732
733
innerMode: function(state) {
734
if (state.block == htmlBlock) return {state: state.htmlState, mode: htmlMode};
735
if (state.localState) return {state: state.localState, mode: state.localMode};
736
return {state: state, mode: mode};
737
},
738
739
blankLine: blankLine,
740
741
getType: getType
742
};
743
return mode;
744
}, "xml");
745
746
CodeMirror.defineMIME("text/x-markdown", "markdown");
747
748