diff --git a/common/static/js/vendor/CodeMirror/mitx_markdown.js b/common/static/js/vendor/CodeMirror/mitx_markdown.js index da8d095742..2157f75fac 100644 --- a/common/static/js/vendor/CodeMirror/mitx_markdown.js +++ b/common/static/js/vendor/CodeMirror/mitx_markdown.js @@ -8,9 +8,9 @@ $(function(){ $(document).ready(function() { //$("a[rel*=leanModal]").leanModal(); //TODO: Make this work with the new modal library. Try and integrate this with the "slices" - $("body").append('
'+ + $("body").append('
'+ '' + - '
'); + '
'); //This is the editor that pops up as a modal var editorCircuit = $("#schematic_editor").get(0); @@ -54,7 +54,8 @@ $(function(){ CodeMirror.defineMode("mitx_markdown", function(cmCfg, modeCfg) { - var htmlMode = CodeMirror.getMode(cmCfg, { name: 'xml', htmlMode: true }); + var htmlFound = CodeMirror.mimeModes.hasOwnProperty("text/html"); + var htmlMode = CodeMirror.getMode(cmCfg, htmlFound ? "text/html" : "text/plain"); var header = 'header' , code = 'comment' @@ -66,54 +67,11 @@ CodeMirror.defineMode("mitx_markdown", function(cmCfg, modeCfg) { , em = 'em' , strong = 'strong' , emstrong = 'emstrong'; - - function escapeHtml(unsafe) { - return unsafe - .replace(/&/g, "&") - .replace(//g, ">") - .replace(/"/g, """) - .replace(/'/g, "'"); - } - - var circuit_formatter = { - creator: function(text) { - var circuit_value = text.match(circuitRE)[1] - - circuit_value = escapeHtml(circuit_value); - - var html = "
" + - "
"; - - return html; - }, - size: function(text) { - return {width: schematic_width, height:schematic_height}; - }, - callback: function(node, line) { - try { - update_schematics(); - var schmInput = node.firstChild.firstChild; - schmInput.codeMirrorLine = line; - if (schmInput.schematic) { //This is undefined if there was an error making the schematic - schmInput.schematic.canvas.style.display = "block"; //Otherwise, it gets line height and is a weird size - schmInput.schematic.always_draw_grid = true; - schmInput.schematic.redraw_background(); - } - $(node.firstChild).leanModal(); - } catch (err) { - console.log("Error in mitx_markdown callback: " + err); - } - } - }; - - - var hrRE = /^[*-=_]/ - , ulRE = /^[*-+]\s+/ + var hrRE = /^([*\-=_])(?:\s*\1){2,}\s*$/ + , ulRE = /^[*\-+]\s+/ , olRE = /^[0-9]+\.\s+/ , headerRE = /^(?:\={3,}|-{3,})$/ - , codeRE = /^(k:\t|\s{4,})/ , textRE = /^[^\[*_\\<>`]+/ , circuitRE = /^circuit-schematic:(.*)$/; @@ -130,12 +88,66 @@ CodeMirror.defineMode("mitx_markdown", function(cmCfg, modeCfg) { // Blocks + function blankLine(state) { + // Reset EM state + state.em = false; + // Reset STRONG state + state.strong = false; + if (!htmlFound && state.f == htmlBlock) { + state.f = inlineNormal; + state.block = blockNormal; + } + return null; + } + + function escapeHtml(unsafe) { + return unsafe + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); + } + + var circuit_formatter = { + creator: function(text) { + var circuit_value = text.match(circuitRE)[1] + + circuit_value = escapeHtml(circuit_value); + + var html = "
" + + "
"; + + return html; + }, + size: function(text) { + return {width: schematic_width, height:schematic_height}; + }, + callback: function(node, line) { + try { + update_schematics(); + var schmInput = node.firstChild.firstChild; + schmInput.codeMirrorLine = line; + if (schmInput.schematic) { //This is undefined if there was an error making the schematic + schmInput.schematic.canvas.style.display = "block"; //Otherwise, it gets line height and is a weird size + schmInput.schematic.always_draw_grid = true; + schmInput.schematic.redraw_background(); + } + $(node.firstChild).leanModal(); + } catch (err) { + console.log("Error in mitx_markdown callback: " + err); + } + + } + }; + function blockNormal(stream, state) { var match; if (stream.match(circuitRE)) { stream.skipToEnd(); return circuit_formatter; - } else if (stream.match(codeRE)) { + } else if (state.indentationDiff >= 4) { + state.indentation -= state.indentationDiff; stream.skipToEnd(); return code; } else if (stream.eatSpace()) { @@ -147,11 +159,8 @@ CodeMirror.defineMode("mitx_markdown", function(cmCfg, modeCfg) { state.quote = true; } else if (stream.peek() === '[') { return switchInline(stream, state, footnoteLink); - } else if (hrRE.test(stream.peek())) { - var re = new RegExp('(?:\s*['+stream.peek()+']){3,}$'); - if (stream.match(re, true)) { - return hr; - } + } else if (stream.match(hrRE, true)) { + return hr; } else if (match = stream.match(ulRE, true) || stream.match(olRE, true)) { state.indentation += match[0].length; return list; @@ -162,49 +171,30 @@ CodeMirror.defineMode("mitx_markdown", function(cmCfg, modeCfg) { function htmlBlock(stream, state) { var style = htmlMode.token(stream, state.htmlState); - if (style === 'tag' && state.htmlState.type !== 'openTag' && !state.htmlState.context) { + if (htmlFound && style === 'tag' && state.htmlState.type !== 'openTag' && !state.htmlState.context) { state.f = inlineNormal; state.block = blockNormal; } + if (state.md_inside && stream.current().indexOf(">")!=-1) { + state.f = inlineNormal; + state.block = blockNormal; + state.htmlState.context = undefined; + } return style; } // Inline function getType(state) { + var styles = []; - // Set defaults - returnValue = ''; - - // Strong / Emphasis - if(state.strong){ - if(state.em){ - returnValue += (returnValue ? ' ' : '') + emstrong; - } else { - returnValue += (returnValue ? ' ' : '') + strong; - } - } else { - if(state.em){ - returnValue += (returnValue ? ' ' : '') + em; - } - } - - // Header - if(state.header){ - returnValue += (returnValue ? ' ' : '') + header; - } - - // Quotes - if(state.quote){ - returnValue += (returnValue ? ' ' : '') + quote; - } - - // Check valud and return - if(!returnValue){ - returnValue = null; - } - return returnValue; + if (state.strong) { styles.push(state.em ? emstrong : strong); } + else if (state.em) { styles.push(em); } + if (state.header) { styles.push(header); } + if (state.quote) { styles.push(quote); } + + return styles.length ? styles.join(' ') : null; } function handleText(stream, state) { @@ -232,10 +222,22 @@ CodeMirror.defineMode("mitx_markdown", function(cmCfg, modeCfg) { return switchInline(stream, state, linkText); } if (ch === '<' && stream.match(/^\w/, false)) { + var md_inside = false; + if (stream.string.indexOf(">")!=-1) { + var atts = stream.string.substring(1,stream.string.indexOf(">")); + if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) { + state.md_inside = true; + } + } stream.backUp(1); return switchBlock(stream, state, htmlBlock); } - + + if (ch === '<' && stream.match(/^\/\w*?>/)) { + state.md_inside = false; + return "tag"; + } + var t = getType(state); if (ch === '*' || ch === '_') { if (stream.eat(ch)) { @@ -307,7 +309,7 @@ CodeMirror.defineMode("mitx_markdown", function(cmCfg, modeCfg) { f: blockNormal, block: blockNormal, - htmlState: htmlMode.startState(), + htmlState: CodeMirror.startState(htmlMode), indentation: 0, inline: inlineNormal, @@ -326,51 +328,40 @@ CodeMirror.defineMode("mitx_markdown", function(cmCfg, modeCfg) { block: s.block, htmlState: CodeMirror.copyState(htmlMode, s.htmlState), indentation: s.indentation, - + inline: s.inline, text: s.text, em: s.em, strong: s.strong, header: s.header, - quote: s.quote + quote: s.quote, + md_inside: s.md_inside }; }, token: function(stream, state) { if (stream.sol()) { - // Reset EM state - state.em = false; - // Reset STRONG state - state.strong = false; + if (stream.match(/^\s*$/, true)) { return blankLine(state); } + // Reset state.header state.header = false; // Reset state.quote state.quote = false; state.f = state.block; - var previousIndentation = state.indentation - , currentIndentation = 0; - while (previousIndentation > 0) { - if (stream.eat(' ')) { - previousIndentation--; - currentIndentation++; - } else if (previousIndentation >= 4 && stream.eat('\t')) { - previousIndentation -= 4; - currentIndentation += 4; - } else { - break; - } - } - state.indentation = currentIndentation; - - if (currentIndentation > 0) return null; + var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, ' ').length; + state.indentationDiff = indentation - state.indentation; + state.indentation = indentation; + if (indentation > 0) { return null; } } return state.f(stream, state); }, + blankLine: blankLine, + getType: getType }; -}); +}, "xml"); CodeMirror.defineMIME("text/x-markdown", "markdown"); diff --git a/common/static/js/vendor/CodeMirror/xml.js b/common/static/js/vendor/CodeMirror/xml.js index f467bddccc..060dad181b 100644 --- a/common/static/js/vendor/CodeMirror/xml.js +++ b/common/static/js/vendor/CodeMirror/xml.js @@ -1,12 +1,44 @@ CodeMirror.defineMode("xml", function(config, parserConfig) { var indentUnit = config.indentUnit; var Kludges = parserConfig.htmlMode ? { - autoSelfClosers: {"br": true, "img": true, "hr": true, "link": true, "input": true, - "meta": true, "col": true, "frame": true, "base": true, "area": true}, + autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true, + 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true, + 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true, + 'track': true, 'wbr': true}, + implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true, + 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true, + 'th': true, 'tr': true}, + contextGrabbers: { + 'dd': {'dd': true, 'dt': true}, + 'dt': {'dd': true, 'dt': true}, + 'li': {'li': true}, + 'option': {'option': true, 'optgroup': true}, + 'optgroup': {'optgroup': true}, + 'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true, + 'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true, + 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true, + 'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true, + 'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true}, + 'rp': {'rp': true, 'rt': true}, + 'rt': {'rp': true, 'rt': true}, + 'tbody': {'tbody': true, 'tfoot': true}, + 'td': {'td': true, 'th': true}, + 'tfoot': {'tbody': true}, + 'th': {'td': true, 'th': true}, + 'thead': {'tbody': true, 'tfoot': true}, + 'tr': {'tr': true} + }, doNotIndent: {"pre": true}, allowUnquoted: true, allowMissing: false - } : {autoSelfClosers: {}, doNotIndent: {}, allowUnquoted: false, allowMissing: false}; + } : { + autoSelfClosers: {}, + implicitlyClosed: {}, + contextGrabbers: {}, + doNotIndent: {}, + allowUnquoted: false, + allowMissing: false + }; var alignCDATA = parserConfig.alignCDATA; // Return variables for tokenizers @@ -162,7 +194,12 @@ CodeMirror.defineMode("xml", function(config, parserConfig) { } else if (type == "closeTag") { var err = false; if (curState.context) { - err = curState.context.tagName != tagName; + if (curState.context.tagName != tagName) { + if (Kludges.implicitlyClosed.hasOwnProperty(curState.context.tagName.toLowerCase())) { + popContext(); + } + err = !curState.context || curState.context.tagName != tagName; + } } else { err = true; } @@ -174,9 +211,15 @@ CodeMirror.defineMode("xml", function(config, parserConfig) { function endtag(startOfLine) { return function(type) { if (type == "selfcloseTag" || - (type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase()))) + (type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase()))) { + maybePopContext(curState.tagName.toLowerCase()); return cont(); - if (type == "endTag") {pushContext(curState.tagName, startOfLine); return cont();} + } + if (type == "endTag") { + maybePopContext(curState.tagName.toLowerCase()); + pushContext(curState.tagName, startOfLine); + return cont(); + } return cont(); }; } @@ -188,6 +231,20 @@ CodeMirror.defineMode("xml", function(config, parserConfig) { return cont(arguments.callee); } } + function maybePopContext(nextTagName) { + var parentTagName; + while (true) { + if (!curState.context) { + return; + } + parentTagName = curState.context.tagName.toLowerCase(); + if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) || + !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) { + return; + } + popContext(); + } + } function attributes(type) { if (type == "word") {setStyle = "attribute"; return cont(attribute, attributes);} @@ -255,7 +312,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) { if (a.indented != b.indented || a.tokenize != b.tokenize) return false; for (var ca = a.context, cb = b.context; ; ca = ca.prev, cb = cb.prev) { if (!ca || !cb) return ca == cb; - if (ca.tagName != cb.tagName) return false; + if (ca.tagName != cb.tagName || ca.indent != cb.indent) return false; } }, @@ -263,5 +320,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) { }; }); +CodeMirror.defineMIME("text/xml", "xml"); CodeMirror.defineMIME("application/xml", "xml"); -CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true}); +if (!CodeMirror.mimeModes.hasOwnProperty("text/html")) + CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});