1
CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
3
var htmlMode = CodeMirror.getMode(cmCfg, { name: 'xml', htmlMode: true });
14
, emstrong = 'emstrong';
18
, olRE = /^[0-9]+\.\s+/
19
, headerRE = /^(?:\={3,}|-{3,})$/
20
, codeRE = /^(k:\t|\s{4,})/
21
, textRE = /^[^\[*_\\<>`]+/;
23
function switchInline(stream, state, f) {
24
state.f = state.inline = f;
25
return f(stream, state);
28
function switchBlock(stream, state, f) {
29
state.f = state.block = f;
30
return f(stream, state);
36
function blockNormal(stream, state) {
37
if (stream.match(codeRE)) {
42
if (stream.eatSpace()) {
46
if (stream.peek() === '#' || stream.match(headerRE)) {
50
if (stream.eat('>')) {
54
if (stream.peek() === '[') {
55
return switchInline(stream, state, footnoteLink);
57
if (hrRE.test(stream.peek())) {
58
var re = new RegExp('(?:\s*['+stream.peek()+']){3,}$');
59
if (stream.match(re, true)) {
65
if (match = stream.match(ulRE, true) || stream.match(olRE, true)) {
66
state.indentation += match[0].length;
70
return switchInline(stream, state, state.inline);
73
function htmlBlock(stream, state) {
74
var style = htmlMode.token(stream, state.htmlState);
75
if (style === 'tag' && state.htmlState.type !== 'openTag' && !state.htmlState.context) {
76
state.f = inlineNormal;
77
state.block = blockNormal;
84
function getType(state) {
85
return state.strong ? (state.em ? emstrong : strong)
86
: (state.em ? em : null);
89
function handleText(stream, state) {
90
if (stream.match(textRE, true)) {
91
return getType(state);
96
function inlineNormal(stream, state) {
97
var style = state.text(stream, state)
98
if (typeof style !== 'undefined')
101
var ch = stream.next();
105
return getType(state);
108
return switchInline(stream, state, inlineElement(code, '`'));
111
return switchInline(stream, state, linkText);
113
if (ch === '<' && stream.match(/^\w/, false)) {
115
return switchBlock(stream, state, htmlBlock);
118
var t = getType(state);
119
if (ch === '*' || ch === '_') {
120
if (stream.eat(ch)) {
121
return (state.strong = !state.strong) ? getType(state) : t;
123
return (state.em = !state.em) ? getType(state) : t;
126
return getType(state);
129
function linkText(stream, state) {
130
while (!stream.eol()) {
131
var ch = stream.next();
132
if (ch === '\\') stream.next();
134
state.inline = state.f = linkHref;
141
function linkHref(stream, state) {
143
var ch = stream.next();
144
if (ch === '(' || ch === '[') {
145
return switchInline(stream, state, inlineElement(linkhref, ch === '(' ? ')' : ']'));
150
function footnoteLink(stream, state) {
151
if (stream.match(/^[^\]]*\]:/, true)) {
152
state.f = footnoteUrl;
155
return switchInline(stream, state, inlineNormal);
158
function footnoteUrl(stream, state) {
160
stream.match(/^[^\s]+/, true);
161
state.f = state.inline = inlineNormal;
165
function inlineRE(endChar) {
166
if (!inlineRE[endChar]) {
167
// match any not-escaped-non-endChar and any escaped char
168
// then match endChar or eol
169
inlineRE[endChar] = new RegExp('^(?:[^\\\\\\' + endChar + ']|\\\\.)*(?:\\' + endChar + '|$)');
171
return inlineRE[endChar];
174
function inlineElement(type, endChar, next) {
175
next = next || inlineNormal;
176
return function(stream, state) {
177
stream.match(inlineRE(endChar));
178
state.inline = state.f = next;
184
startState: function() {
189
htmlState: htmlMode.startState(),
192
inline: inlineNormal,
199
copyState: function(s) {
204
htmlState: CodeMirror.copyState(htmlMode, s.htmlState),
205
indentation: s.indentation,
214
token: function(stream, state) {
218
// Reset STRONG state
219
state.strong = false;
220
state.f = state.block;
221
var previousIndentation = state.indentation
222
, currentIndentation = 0;
223
while (previousIndentation > 0) {
224
if (stream.eat(' ')) {
225
previousIndentation--;
226
currentIndentation++;
227
} else if (previousIndentation >= 4 && stream.eat('\t')) {
228
previousIndentation -= 4;
229
currentIndentation += 4;
234
state.indentation = currentIndentation;
236
if (currentIndentation > 0) return null;
238
return state.f(stream, state);
246
CodeMirror.defineMIME("text/x-markdown", "markdown");