diff options
Diffstat (limited to 'imports/codemirror/mode/gfm/gfm.js')
-rwxr-xr-x | imports/codemirror/mode/gfm/gfm.js | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/imports/codemirror/mode/gfm/gfm.js b/imports/codemirror/mode/gfm/gfm.js new file mode 100755 index 00000000..1e9d7d87 --- /dev/null +++ b/imports/codemirror/mode/gfm/gfm.js | |||
@@ -0,0 +1,108 @@ | |||
1 | CodeMirror.defineMode("gfm", function(config, parserConfig) { | ||
2 | var mdMode = CodeMirror.getMode(config, "markdown"); | ||
3 | var aliases = { | ||
4 | html: "htmlmixed", | ||
5 | js: "javascript", | ||
6 | json: "application/json", | ||
7 | c: "text/x-csrc", | ||
8 | "c++": "text/x-c++src", | ||
9 | java: "text/x-java", | ||
10 | csharp: "text/x-csharp", | ||
11 | "c#": "text/x-csharp", | ||
12 | }; | ||
13 | |||
14 | // make this lazy so that we don't need to load GFM last | ||
15 | var getMode = (function () { | ||
16 | var i, modes = {}, mimes = {}, mime; | ||
17 | |||
18 | var list = CodeMirror.listModes(); | ||
19 | for (i = 0; i < list.length; i++) { | ||
20 | modes[list[i]] = list[i]; | ||
21 | } | ||
22 | var mimesList = CodeMirror.listMIMEs(); | ||
23 | for (i = 0; i < mimesList.length; i++) { | ||
24 | mime = mimesList[i].mime; | ||
25 | mimes[mime] = mimesList[i].mime; | ||
26 | } | ||
27 | |||
28 | for (var a in aliases) { | ||
29 | if (aliases[a] in modes || aliases[a] in mimes) | ||
30 | modes[a] = aliases[a]; | ||
31 | } | ||
32 | |||
33 | return function (lang) { | ||
34 | return modes[lang] ? CodeMirror.getMode(config, modes[lang]) : null; | ||
35 | } | ||
36 | }()); | ||
37 | |||
38 | function markdown(stream, state) { | ||
39 | // intercept fenced code blocks | ||
40 | if (stream.sol() && stream.match(/^```([\w+#]*)/)) { | ||
41 | // try switching mode | ||
42 | state.localMode = getMode(RegExp.$1) | ||
43 | if (state.localMode) | ||
44 | state.localState = state.localMode.startState(); | ||
45 | |||
46 | state.token = local; | ||
47 | return 'code'; | ||
48 | } | ||
49 | |||
50 | return mdMode.token(stream, state.mdState); | ||
51 | } | ||
52 | |||
53 | function local(stream, state) { | ||
54 | if (stream.sol() && stream.match(/^```/)) { | ||
55 | state.localMode = state.localState = null; | ||
56 | state.token = markdown; | ||
57 | return 'code'; | ||
58 | } | ||
59 | else if (state.localMode) { | ||
60 | return state.localMode.token(stream, state.localState); | ||
61 | } else { | ||
62 | stream.skipToEnd(); | ||
63 | return 'code'; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | // custom handleText to prevent emphasis in the middle of a word | ||
68 | // and add autolinking | ||
69 | function handleText(stream, mdState) { | ||
70 | var match; | ||
71 | if (stream.match(/^\w+:\/\/\S+/)) { | ||
72 | return 'linkhref'; | ||
73 | } | ||
74 | if (stream.match(/^[^\[*\\<>` _][^\[*\\<>` ]*[^\[*\\<>` _]/)) { | ||
75 | return mdMode.getType(mdState); | ||
76 | } | ||
77 | if (match = stream.match(/^[^\[*\\<>` ]+/)) { | ||
78 | var word = match[0]; | ||
79 | if (word[0] === '_' && word[word.length-1] === '_') { | ||
80 | stream.backUp(word.length); | ||
81 | return undefined; | ||
82 | } | ||
83 | return mdMode.getType(mdState); | ||
84 | } | ||
85 | if (stream.eatSpace()) { | ||
86 | return null; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | return { | ||
91 | startState: function() { | ||
92 | var mdState = mdMode.startState(); | ||
93 | mdState.text = handleText; | ||
94 | return {token: markdown, mode: "markdown", mdState: mdState, | ||
95 | localMode: null, localState: null}; | ||
96 | }, | ||
97 | |||
98 | copyState: function(state) { | ||
99 | return {token: state.token, mode: state.mode, mdState: CodeMirror.copyState(mdMode, state.mdState), | ||
100 | localMode: state.localMode, | ||
101 | localState: state.localMode ? CodeMirror.copyState(state.localMode, state.localState) : null}; | ||
102 | }, | ||
103 | |||
104 | token: function(stream, state) { | ||
105 | return state.token(stream, state); | ||
106 | } | ||
107 | } | ||
108 | }); | ||