diff --git a/js/core.js b/js/core.js index 3080e63c..843d94cd 100644 --- a/js/core.js +++ b/js/core.js @@ -252,6 +252,25 @@ define([ // Create the converter and the editor var converter = new Markdown.Converter(); + // Create MD sections for extensions + converter.hooks.chain("preConversion", function(text) { + var tmpText = text + "\n\n"; + var sectionList = [], offset = 0; + // Look for titles (exclude gfm blocs) + tmpText.replace(/^```.*\n[\s\S]*?\n```|(^.+[ \t]*\n=+[ \t]*\n+|^.+[ \t]*\n-+[ \t]*\n+|^\#{1,6}[ \t]*.+?[ \t]*\#*\n+)/gm, function(match, title, matchOffset) { + if(title && matchOffset > offset) { + // We just found a title which means end of the previous section + // Exclude last \n of the section + sectionList.push(tmpText.substring(offset, matchOffset - 1)); + offset = matchOffset; + } + return ""; + }); + // Last section + sectionList.push(tmpText.substring(offset, text.length)); + extensionMgr.onSectionsCreated(sectionList); + return text; + }); editor = new Markdown.Editor(converter); // Custom insert link dialog editor.hooks.set("insertLinkDialog", function(callback) { diff --git a/js/extensionMgr.js b/js/extensionMgr.js index 2c8f52e5..27006b5c 100644 --- a/js/extensionMgr.js +++ b/js/extensionMgr.js @@ -147,6 +147,7 @@ define([ // Operations on PageDown addHook("onEditorConfigure"); + addHook("onSectionsCreated"); var onPreviewFinished = createHook("onPreviewFinished"); var onAsyncPreviewCallbackList = getExtensionCallbackList("onAsyncPreview"); @@ -162,7 +163,7 @@ define([ $("#preview-contents > .preview-content").each(function() { html += $(this).html(); }); - onPreviewFinished(html); + onPreviewFinished(utils.trim(html)); console.log("Preview time: " + (new Date().getTime() - window.previewStartTime)); } } diff --git a/js/extensions/mathJax.js b/js/extensions/mathJax.js index 7d9d4675..2229322c 100644 --- a/js/extensions/mathJax.js +++ b/js/extensions/mathJax.js @@ -210,7 +210,7 @@ define([ function RestartMJ() { pending = false; HUB.cancelTypeset = false; // won't need to do this in the future - HUB.Queue([ "Typeset", HUB, converter.eltList || preview ]); + HUB.Queue([ "Typeset", HUB, preview ]); HUB.Queue(afterRefreshCallback); } @@ -235,7 +235,7 @@ define([ // Create a preview refresh hook to handle starting MathJax. // mathJax.onEditorConfigure = function(editorObject) { - preview = document.getElementById("wmd-preview"); + preview = document.getElementById("preview-contents"); converter = editorObject.getConverter(); converter.hooks.chain("preConversion", removeMath); diff --git a/js/extensions/partialRendering.js b/js/extensions/partialRendering.js index c9809d92..c14fd257 100644 --- a/js/extensions/partialRendering.js +++ b/js/extensions/partialRendering.js @@ -9,14 +9,27 @@ define([ partialRendering.settingsBlock = partialRenderingSettingsBlockHTML; var converter = undefined; - var sectionIdGenerator = 0; - var sectionList = [ - { - text: "" + var sectionCounter = 0; + var sectionList = []; + var linkDefinition = ""; + var sectionsToRemove = []; + var modifiedSections = []; + var insertAfterSection = undefined; + var fileChanged = true; + function updateSectionList(newSectionList, newLinkDefinition) { + modifiedSections = []; + sectionsToRemove = []; + insertAfterSection = undefined; + + // Render everything if file changed or linkDefinition changed + if(fileChanged === true || linkDefinition != newLinkDefinition) { + fileChanged = false; + linkDefinition = newLinkDefinition; + sectionsToRemove = sectionList; + sectionList = newSectionList; + modifiedSections = newSectionList; + return; } - ]; - var sectionsToRemove = undefined; - function updateSectionList(newSectionList) { // Find modified sections starting from left var leftIndex = sectionList.length; @@ -44,134 +57,140 @@ define([ // Create an array composed of left unmodified, modified, right // unmodified sections var leftSections = sectionList.slice(0, leftIndex); - var modifiedSections = newSectionList.slice(leftIndex, newSectionList.length + rightIndex); + modifiedSections = newSectionList.slice(leftIndex, newSectionList.length + rightIndex); var rightSections = sectionList.slice(sectionList.length + rightIndex, sectionList.length); + insertAfterSection = _.last(leftSections); sectionsToRemove = sectionList.slice(leftIndex, sectionList.length + rightIndex); sectionList = leftSections.concat(modifiedSections).concat(rightSections); } + var doFootnotes = false; var hasFootnotes = false; - function extractSections(text) { + partialRendering.onSectionsCreated = function(sectionListParam) { - text += "\n\n"; - - // Strip link definitions - var linkDefinition = ""; - text = text.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*(\S+?)>?(?=\s|$)[ \t]*\n?[ \t]*((\n*)["(](.+?)[")][ \t]*)?(?:\n+)/gm, function(wholeMatch) { - linkDefinition += wholeMatch; - return ""; - }); - - // And eventually footnotes... - hasFootnotes = false; - var doFootnotes = _.some(converter.extraExtensions, function(extension) { - return extension == "footnotes"; - }); - if(doFootnotes) { - text = text.replace(/\n[ ]{0,3}\[\^(.+?)\]\:[ \t]*\n?([\s\S]*?)\n{1,2}((?=\n[ ]{0,3}\S)|$)/g, function(wholeMatch) { - hasFootnotes = true; - linkDefinition += wholeMatch; - return ""; - }); - } - - // Look for titles var newSectionList = []; - var offset = 0; - text.replace(/^```.*\n[\s\S]*?\n```|(^.+[ \t]*\n=+[ \t]*\n+|^.+[ \t]*\n-+[ \t]*\n+|^\#{1,6}[ \t]*.+?[ \t]*\#*\n+)/gm, function(match, title, matchOffset) { - if(title) { - // We just found a title which means end of the previous section - if(matchOffset > offset) { - newSectionList.push({ - id: ++sectionIdGenerator, - text: text.substring(offset, matchOffset) + "\n" + linkDefinition - }); - offset = matchOffset; + var newLinkDefinition = ""; + hasFootnotes = false; + _.each(sectionListParam, function(text) { + text += "\n\n"; + + // Strip link definitions + text = text.replace(/^```.*\n[\s\S]*?\n```|^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*(\S+?)>?(?=\s|$)[ \t]*\n?[ \t]*((\n*)["(](.+?)[")][ \t]*)?(?:\n+)/gm, function(wholeMatch, link) { + if(link) { + newLinkDefinition += wholeMatch; + return ""; } + return wholeMatch; + }); + + // And eventually footnotes... + if(doFootnotes) { + text = text.replace(/^```.*\n[\s\S]*?\n```|\n[ ]{0,3}\[\^(.+?)\]\:[ \t]*\n?([\s\S]*?)\n{1,2}((?=\n[ ]{0,3}\S)|$)/g, function(wholeMatch, footnote) { + if(footnote) { + hasFootnotes = true; + newLinkDefinition += wholeMatch; + return ""; + } + return wholeMatch; + }); + } + + // Skip space only sections + if(/\S/.test(text)) { + // Add section to the newSectionList + newSectionList.push({ + id: ++sectionCounter, + text: text + }); } - return ""; - }); - // Last section - newSectionList.push({ - id: ++sectionIdGenerator, - text: text.substring(offset, text.length) + linkDefinition }); - updateSectionList(newSectionList); - } + updateSectionList(newSectionList, newLinkDefinition); + }; + + var footnoteContainerElt = $('