New partialRendering extension

This commit is contained in:
benweet 2013-07-28 18:14:42 +01:00
parent 0d6d329e6a
commit 539f39a2d9
10 changed files with 149 additions and 79 deletions

View File

@ -153,22 +153,26 @@ define([
var onAsyncPreviewCallbackList = getExtensionCallbackList("onAsyncPreview"); var onAsyncPreviewCallbackList = getExtensionCallbackList("onAsyncPreview");
// The number of times we expect tryFinished to be called // The number of times we expect tryFinished to be called
var nbAsyncPreviewCallback = onAsyncPreviewCallbackList.length + 1; var nbAsyncPreviewCallback = onAsyncPreviewCallbackList.length + 1;
var previewContentsElt = undefined;
var previewContentsJQElt = undefined;
extensionMgr["onAsyncPreview"] = function() { extensionMgr["onAsyncPreview"] = function() {
logger.log("onAsyncPreview"); logger.log("onAsyncPreview");
// Call onPreviewFinished callbacks when all async preview are finished // Call onPreviewFinished callbacks when all async preview are finished
var counter = 0; var counter = 0;
function tryFinished() { function tryFinished() {
if(++counter === nbAsyncPreviewCallback) { if(++counter === nbAsyncPreviewCallback) {
_.defer(function() {
var html = ""; var html = "";
$("#preview-contents > .preview-content").each(function() { _.each(previewContentsElt.children, function(elt) {
html += $(this).html(); html += elt.innerHTML;
}); });
onPreviewFinished(utils.trim(html)); onPreviewFinished(utils.trim(html));
logger.log("Preview time: " + (new Date() - extensionMgr.previewStartTime)); logger.log("Preview time: " + (new Date() - extensionMgr.previewStartTime));
});
} }
} }
// We assume images are loading in the preview // We assume images are loading in the preview
$("#preview-contents").waitForImages(tryFinished); previewContentsJQElt.waitForImages(tryFinished);
_.each(onAsyncPreviewCallbackList, function(asyncPreviewCallback) { _.each(onAsyncPreviewCallbackList, function(asyncPreviewCallback) {
asyncPreviewCallback(tryFinished); asyncPreviewCallback(tryFinished);
}); });
@ -184,6 +188,9 @@ define([
} }
extensionMgr["onReady"] = function() { extensionMgr["onReady"] = function() {
previewContentsElt = document.getElementById('preview-contents');
previewContentsJQElt = $(previewContentsElt);
// Create accordion in settings dialog // Create accordion in settings dialog
_.chain(extensionList).sortBy(function(extension) { _.chain(extensionList).sortBy(function(extension) {
return extension.extensionName.toLowerCase(); return extension.extensionName.toLowerCase();

View File

@ -30,6 +30,7 @@ define([
selectedFileDesc = fileDesc; selectedFileDesc = fileDesc;
}; };
var textareaElt = undefined;
buttonHtmlCode.onPreviewFinished = function(html) { buttonHtmlCode.onPreviewFinished = function(html) {
try { try {
var htmlCode = _.template(buttonHtmlCode.config.template, { var htmlCode = _.template(buttonHtmlCode.config.template, {
@ -37,7 +38,7 @@ define([
documentMarkdown: selectedFileDesc.content, documentMarkdown: selectedFileDesc.content,
documentHTML: html documentHTML: html
}); });
$("#input-html-code").val(htmlCode); textareaElt.value = htmlCode;
} }
catch(e) { catch(e) {
extensionMgr.onError(e); extensionMgr.onError(e);
@ -46,6 +47,7 @@ define([
}; };
buttonHtmlCode.onReady = function() { buttonHtmlCode.onReady = function() {
textareaElt = document.getElementById('input-html-code');
$(".action-html-code").click(function() { $(".action-html-code").click(function() {
_.defer(function() { _.defer(function() {
$("#input-html-code").each(function() { $("#input-html-code").each(function() {

View File

@ -44,11 +44,28 @@ define([
return $(_.template(buttonStatHTML, buttonStat.config)); return $(_.template(buttonStatHTML, buttonStat.config));
}; };
var previewContentsElt = undefined;
var value1Elt = undefined;
var value2Elt = undefined;
var value3Elt = undefined;
buttonStat.onReady = function() {
previewContentsElt = document.getElementById('preview-contents');
value1Elt = document.getElementById('span-stat-value1');
value2Elt = document.getElementById('span-stat-value2');
value3Elt = document.getElementById('span-stat-value3');
};
buttonStat.onPreviewFinished = function() { buttonStat.onPreviewFinished = function() {
var text = $("#preview-contents").clone().find("script").remove().end().text(); var previewContentsEltClone = previewContentsElt.cloneNode(true);
$("#span-stat-value1").text((text.match(new RegExp(buttonStat.config.value1, "g")) || []).length); var scriptEltList = previewContentsEltClone.getElementsByTagName('script');
$("#span-stat-value2").text((text.match(new RegExp(buttonStat.config.value2, "g")) || []).length); for(var i = scriptEltList.length-1; i >= 0; i--) {
$("#span-stat-value3").text((text.match(new RegExp(buttonStat.config.value3, "g")) || []).length); var scriptElt = scriptEltList[i];
scriptElt.parentNode.removeChild(scriptElt);
}
var text = previewContentsEltClone.textContent;
value1Elt.textContent = (text.match(new RegExp(buttonStat.config.value1, "g")) || []).length;
value2Elt.textContent = (text.match(new RegExp(buttonStat.config.value2, "g")) || []).length;
value3Elt.textContent = (text.match(new RegExp(buttonStat.config.value3, "g")) || []).length;
}; };
return buttonStat; return buttonStat;

View File

@ -10,12 +10,14 @@ define([
var libraries = { var libraries = {
"Bootstrap": "http://twitter.github.io/bootstrap/", "Bootstrap": "http://twitter.github.io/bootstrap/",
"crel": "https://github.com/KoryNunn/crel",
"CSS Browser Selector": "https://github.com/rafaelp/css_browser_selector/", "CSS Browser Selector": "https://github.com/rafaelp/css_browser_selector/",
"Dropbox-js": "https://github.com/dropbox/dropbox-js", "Dropbox-js": "https://github.com/dropbox/dropbox-js",
"FileSaver.js": "https://github.com/eligrey/FileSaver.js/", "FileSaver.js": "https://github.com/eligrey/FileSaver.js/",
"Gatekeeper": "https://github.com/prose/gatekeeper", "Gatekeeper": "https://github.com/prose/gatekeeper",
"Github.js": "https://github.com/michael/github", "Github.js": "https://github.com/michael/github",
"Glyphicons": "http://glyphicons.com/", "Glyphicons": "http://glyphicons.com/",
"Highlight.js": "http://softwaremaniacs.org/soft/highlight/en/",
"jGrowl": "https://github.com/stanlemon/jGrowl/", "jGrowl": "https://github.com/stanlemon/jGrowl/",
"jQuery": "http://jquery.com/", "jQuery": "http://jquery.com/",
"jQuery Mouse Wheel Plugin": "https://github.com/brandonaaron/jquery-mousewheel", "jQuery Mouse Wheel Plugin": "https://github.com/brandonaaron/jquery-mousewheel",
@ -34,6 +36,7 @@ define([
var projects = { var projects = {
"StackEdit Download Proxy": "https://github.com/benweet/stackedit-download-proxy", "StackEdit Download Proxy": "https://github.com/benweet/stackedit-download-proxy",
"StackEdit Picasa Proxy": "https://github.com/benweet/stackedit-picasa-proxy",
"StackEdit SSH Proxy": "https://github.com/benweet/stackedit-ssh-proxy", "StackEdit SSH Proxy": "https://github.com/benweet/stackedit-ssh-proxy",
"StackEdit Tumblr Proxy": "https://github.com/benweet/stackedit-tumblr-proxy", "StackEdit Tumblr Proxy": "https://github.com/benweet/stackedit-tumblr-proxy",
"StackEdit WordPress Proxy": "https://github.com/benweet/stackedit-wordpress-proxy", "StackEdit WordPress Proxy": "https://github.com/benweet/stackedit-wordpress-proxy",

View File

@ -1,10 +1,11 @@
define([ define([
"jquery", "jquery",
"underscore",
"utils", "utils",
"classes/Extension", "classes/Extension",
"text!html/markdownExtraSettingsBlock.html", "text!html/markdownExtraSettingsBlock.html",
"libs/Markdown.Extra", "libs/Markdown.Extra",
], function($, utils, Extension, markdownExtraSettingsBlockHTML) { ], function($, _, utils, Extension, markdownExtraSettingsBlockHTML) {
var markdownExtra = new Extension("markdownExtra", "Markdown Extra", true); var markdownExtra = new Extension("markdownExtra", "Markdown Extra", true);
markdownExtra.settingsBlock = markdownExtraSettingsBlockHTML; markdownExtra.settingsBlock = markdownExtraSettingsBlockHTML;
@ -50,9 +51,10 @@ define([
}; };
if(markdownExtra.config.highlighter == "highlight") { if(markdownExtra.config.highlighter == "highlight") {
options.highlighter = "prettify"; options.highlighter = "prettify";
var previewContentsElt = document.getElementById('preview-contents');
editor.hooks.chain("onPreviewRefresh", function() { editor.hooks.chain("onPreviewRefresh", function() {
$('.prettyprint').each(function(i, e) { _.each(previewContentsElt.querySelectorAll('.prettyprint'), function(elt) {
hljs.highlightBlock(e); hljs.highlightBlock(elt);
}); });
}); });
} }

View File

@ -1,9 +1,9 @@
define([ define([
"jquery",
"underscore", "underscore",
"crel",
"classes/Extension", "classes/Extension",
"text!html/partialRenderingSettingsBlock.html", "text!html/partialRenderingSettingsBlock.html",
], function($, _, Extension, partialRenderingSettingsBlockHTML) { ], function(_, crel, Extension, partialRenderingSettingsBlockHTML) {
var partialRendering = new Extension("partialRendering", "Partial Rendering", true); var partialRendering = new Extension("partialRendering", "Partial Rendering", true);
partialRendering.settingsBlock = partialRenderingSettingsBlockHTML; partialRendering.settingsBlock = partialRenderingSettingsBlockHTML;
@ -14,12 +14,12 @@ define([
var linkDefinition = undefined; var linkDefinition = undefined;
var sectionsToRemove = []; var sectionsToRemove = [];
var modifiedSections = []; var modifiedSections = [];
var insertAfterSection = undefined; var insertBeforeSection = undefined;
var fileChanged = false; var fileChanged = false;
function updateSectionList(newSectionList, newLinkDefinition) { function updateSectionList(newSectionList, newLinkDefinition) {
modifiedSections = []; modifiedSections = [];
sectionsToRemove = []; sectionsToRemove = [];
insertAfterSection = undefined; insertBeforeSection = undefined;
// Render everything if file or linkDefinition changed // Render everything if file or linkDefinition changed
if(fileChanged === true || linkDefinition != newLinkDefinition) { if(fileChanged === true || linkDefinition != newLinkDefinition) {
@ -59,7 +59,7 @@ define([
var leftSections = sectionList.slice(0, leftIndex); var leftSections = sectionList.slice(0, leftIndex);
modifiedSections = newSectionList.slice(leftIndex, newSectionList.length + rightIndex); modifiedSections = newSectionList.slice(leftIndex, newSectionList.length + rightIndex);
var rightSections = sectionList.slice(sectionList.length + rightIndex, sectionList.length); var rightSections = sectionList.slice(sectionList.length + rightIndex, sectionList.length);
insertAfterSection = _.last(leftSections); insertBeforeSection = _.first(rightSections);
sectionsToRemove = sectionList.slice(leftIndex, sectionList.length + rightIndex); sectionsToRemove = sectionList.slice(leftIndex, sectionList.length + rightIndex);
sectionList = leftSections.concat(modifiedSections).concat(rightSections); sectionList = leftSections.concat(modifiedSections).concat(rightSections);
} }
@ -73,16 +73,7 @@ define([
_.each(sectionListParam, function(text) { _.each(sectionListParam, function(text) {
text += "\n\n"; text += "\n\n";
// Strip link definitions // Strip footnotes
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 footnotes eventually
if(doFootnotes) { 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) { 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) { if(footnote) {
@ -94,6 +85,15 @@ define([
}); });
} }
// 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;
});
// Skip space only sections // Skip space only sections
if(/\S/.test(text)) { if(/\S/.test(text)) {
// Add section to the newSectionList // Add section to the newSectionList
@ -107,56 +107,73 @@ define([
updateSectionList(newSectionList, newLinkDefinition); updateSectionList(newSectionList, newLinkDefinition);
}; };
var footnoteContainerElt = $('<div id="wmd-preview-section-footnotes" class="preview-content">'); var footnoteContainerElt = undefined;
var footnoteList = {}; var previewContentsElt = undefined;
var footnoteMap = {};
function refreshSections() { function refreshSections() {
// Remove outdated sections // Remove outdated sections
_.each(sectionsToRemove, function(section) { _.each(sectionsToRemove, function(section) {
$("#wmd-preview-section-" + section.id).remove(); var sectionElt = document.getElementById("wmd-preview-section-" + section.id);
previewContentsElt.removeChild(sectionElt);
}); });
var wmdPreviewElt = $("#wmd-preview"); var wmdPreviewElt = document.getElementById("wmd-preview");
var insertAfterSectionElt = insertAfterSection === undefined ? wmdPreviewElt : $("#wmd-preview-section-" + insertAfterSection.id); var markdownEltList = Array.prototype.slice.call(wmdPreviewElt.childNodes);
wmdPreviewElt.innerHTML = '';
var newSectionEltList = document.createDocumentFragment();
_.each(modifiedSections, function(section) { _.each(modifiedSections, function(section) {
var sectionElt = $('<div id="wmd-preview-section-' + section.id + '" class="wmd-preview-section preview-content">'); var sectionElt = crel('div', {
_.some(wmdPreviewElt.contents(), function(elt, index) { id: 'wmd-preview-section-' + section.id,
elt = $(elt); class: 'wmd-preview-section preview-content'
if(index !== 0 && elt.is(".wmd-title")) { });
return true; var isFirst = true;
} while(markdownEltList.length !== 0) {
else if(elt.is("div.footnotes")) { var elt = markdownEltList[0];
elt.find("ol > li").each(function() { if(isFirst === false && /(^| )wmd-title($| )/.test(elt.className)) {
var footnoteElt = $(this).clone(); // Stop when encountered the next wmd-title
var id = footnoteElt.attr("id").substring(3); break;
footnoteList[id] = footnoteElt; }
isFirst = false;
if(elt.tagName == 'DIV' && elt.className == 'footnotes') {
_.each(elt.querySelectorAll("ol > li"), function(footnoteElt) {
// Store each footnote in our footnote map
var id = footnoteElt.id.substring(3);
footnoteMap[id] = footnoteElt;
}); });
elt.remove();
} }
else { else {
sectionElt.append(elt); sectionElt.appendChild(elt);
} }
markdownEltList.shift();
};
newSectionEltList.appendChild(sectionElt);
}); });
insertAfterSectionElt.after(sectionElt); var insertBeforeElt = footnoteContainerElt;
insertAfterSectionElt = sectionElt; if(insertBeforeSection !== undefined) {
}); insertBeforeElt = document.getElementById("wmd-preview-section-" + insertBeforeSection.id);
}
previewContentsElt.insertBefore(newSectionEltList, insertBeforeElt);
// Rewrite footnotes in the footer and update footnote numbers // Rewrite footnotes in the footer and update footnote numbers
footnoteContainerElt.empty(); footnoteContainerElt.innerHTML = '';
var usedFootnoteIds = []; var usedFootnoteIds = [];
if(hasFootnotes === true) { if(hasFootnotes === true) {
var footnoteElts = $("<ol>"); var footnoteElts = crel('ol');
$("#preview-contents a.footnote").each(function(index) { _.each(previewContentsElt.querySelectorAll('a.footnote'), function(elt, index) {
var id=$(this).text(index + 1).attr("id").substring(6); elt.textContent = index + 1;
var id = elt.id.substring(6);
usedFootnoteIds.push(id); usedFootnoteIds.push(id);
footnoteElts.append(footnoteList[id].clone()); footnoteElts.appendChild(footnoteMap[id].cloneNode(true));
}); });
if(usedFootnoteIds.length > 0) { if(usedFootnoteIds.length > 0) {
// Append the whole footnotes at the end of the document // Append the whole footnotes at the end of the document
footnoteContainerElt.html($('<div class="footnotes">').append("<hr>").append(footnoteElts)); footnoteContainerElt.appendChild(crel('div', {
class: 'footnotes'
}, crel('hr'), footnoteElts));
} }
// Keep used footnotes only in our map // Keep used footnotes only in our map
footnoteList = _.pick(footnoteList, usedFootnoteIds); footnoteMap = _.pick(footnoteMap, usedFootnoteIds);
} }
} }
@ -175,12 +192,18 @@ define([
}; };
partialRendering.onReady = function() { partialRendering.onReady = function() {
$("#preview-contents").append(footnoteContainerElt); footnoteContainerElt = crel('div', {
$("#wmd-preview").hide(); id: 'wmd-preview-section-footnotes',
class: 'preview-content'
});
previewContentsElt = document.getElementById("preview-contents");
previewContentsElt.appendChild(footnoteContainerElt);
}; };
partialRendering.onFileSelected = function() { partialRendering.onFileSelected = function() {
fileChanged = true; fileChanged = true;
}; };
partialRendering.onFileOpen = function() { partialRendering.onFileOpen = function() {
if(converter.extraExtensions) { if(converter.extraExtensions) {
doFootnotes = _.some(converter.extraExtensions, function(extension) { doFootnotes = _.some(converter.extraExtensions, function(extension) {

View File

@ -15,6 +15,9 @@ define([
sectionList = sectionListParam; sectionList = sectionListParam;
}; };
var editorElt = undefined;
var previewElt = undefined;
var textareaElt = undefined;
var mdSectionList = []; var mdSectionList = [];
var htmlSectionList = []; var htmlSectionList = [];
function pxToFloat(px) { function pxToFloat(px) {
@ -25,10 +28,7 @@ define([
var buildSections = _.debounce(function() { var buildSections = _.debounce(function() {
// Try to find Markdown sections by looking for titles // Try to find Markdown sections by looking for titles
var editorElt = $("#wmd-input");
mdSectionList = []; mdSectionList = [];
// This textarea is used to measure sections height
var textareaElt = $("#md-section-helper");
// It has to be the same width as wmd-input // It has to be the same width as wmd-input
textareaElt.width(editorElt.width()); textareaElt.width(editorElt.width());
// Consider wmd-input top padding (will be used for 1st and last // Consider wmd-input top padding (will be used for 1st and last
@ -65,14 +65,14 @@ define([
}); });
// Try to find corresponding sections in the preview // Try to find corresponding sections in the preview
var previewElt = $(".preview-container");
htmlSectionList = []; htmlSectionList = [];
var htmlSectionOffset = 0; var htmlSectionOffset = 0;
var previewScrollTop = previewElt.scrollTop(); var previewScrollTop = previewElt.scrollTop();
// Each title element is a section separator // Each title element is a section separator
$("#preview-contents > .preview-content").children(".wmd-title").each(function() { previewElt.find(".preview-content > .wmd-title").each(function() {
var titleElt = $(this);
// Consider div scroll position and header element top margin // Consider div scroll position and header element top margin
var newSectionOffset = $(this).position().top + previewScrollTop + pxToFloat($(this).css('margin-top')); var newSectionOffset = titleElt.position().top + previewScrollTop + pxToFloat(titleElt.css('margin-top'));
htmlSectionList.push({ htmlSectionList.push({
startOffset: htmlSectionOffset, startOffset: htmlSectionOffset,
endOffset: newSectionOffset, endOffset: newSectionOffset,
@ -100,9 +100,7 @@ define([
if(mdSectionList.length === 0 || mdSectionList.length !== htmlSectionList.length) { if(mdSectionList.length === 0 || mdSectionList.length !== htmlSectionList.length) {
return; return;
} }
var editorElt = $("#wmd-input");
var editorScrollTop = editorElt.scrollTop(); var editorScrollTop = editorElt.scrollTop();
var previewElt = $(".preview-container");
var previewScrollTop = previewElt.scrollTop(); var previewScrollTop = previewElt.scrollTop();
function animate(srcScrollTop, srcSectionList, destElt, destSectionList, currentDestScrollTop, callback) { function animate(srcScrollTop, srcSectionList, destElt, destSectionList, currentDestScrollTop, callback) {
// Find the section corresponding to the offset // Find the section corresponding to the offset
@ -160,6 +158,12 @@ define([
}; };
scrollLink.onLayoutCreated = function() { scrollLink.onLayoutCreated = function() {
editorElt = $("#wmd-input");
previewElt = $(".preview-container");
// This textarea is used to measure sections height
textareaElt = $("#md-section-helper");
$(".preview-container").bind("keyup mouseup mousewheel", function() { $(".preview-container").bind("keyup mouseup mousewheel", function() {
isScrollPreview = true; isScrollPreview = true;
isScrollEditor = false; isScrollEditor = false;
@ -172,19 +176,20 @@ define([
}); });
}; };
var previewContentsElt = undefined;
scrollLink.onEditorConfigure = function(editor) { scrollLink.onEditorConfigure = function(editor) {
previewContentsElt = $("#preview-contents");
editor.getConverter().hooks.chain("postConversion", function(text) { editor.getConverter().hooks.chain("postConversion", function(text) {
// To avoid losing scrolling position before elements are fully // To avoid losing scrolling position before elements are fully
// loaded // loaded
var previewElt = $("#preview-contents"); previewContentsElt.height(previewContentsElt.height());
previewElt.height(previewElt.height());
return text; return text;
}); });
}; };
scrollLink.onPreviewFinished = function() { scrollLink.onPreviewFinished = function() {
// Now set the correct height // Now set the correct height
$("#preview-contents").height("auto"); previewContentsElt.height("auto");
isScrollEditor = true; isScrollEditor = true;
buildSections(); buildSections();
}; };

View File

@ -90,10 +90,11 @@ define([
} }
// Build the TOC // Build the TOC
var previewContentsElt = undefined;
function buildToc() { function buildToc() {
var anchorList = {}; var anchorList = {};
function createAnchor(element) { function createAnchor(element) {
var id = element.prop("id") || utils.slugify(element.text()); var id = element.id || utils.slugify(element.textContent);
var anchor = id; var anchor = id;
var index = 0; var index = 0;
while (_.has(anchorList, anchor)) { while (_.has(anchorList, anchor)) {
@ -101,31 +102,35 @@ define([
} }
anchorList[anchor] = true; anchorList[anchor] = true;
// Update the id of the element // Update the id of the element
element.prop("id", anchor); element.id = anchor;
return anchor; return anchor;
} }
var elementList = []; var elementList = [];
$("#preview-contents > .preview-content").children("h1, h2, h3, h4, h5, h6").each(function() { _.each(previewContentsElt.querySelectorAll('.preview-content > .wmd-title'), function(elt) {
elementList.push(new TocElement($(this).prop("tagName"), createAnchor($(this)), $(this).text())); elementList.push(new TocElement(elt.tagName, createAnchor(elt), elt.textContent));
}); });
elementList = groupTags(elementList); elementList = groupTags(elementList);
return '<div class="toc">\n<ul>\n' + elementList.join("") + '</ul>\n</div>\n'; return '<div class="toc">\n<ul>\n' + elementList.join("") + '</ul>\n</div>\n';
} }
toc.onEditorConfigure = function(editor) { toc.onEditorConfigure = function(editor) {
var tocExp = new RegExp("^" + toc.config.marker + "$", "g") previewContentsElt = document.getElementById('preview-contents');
var tocEltList = document.querySelectorAll('.table-of-contents');
var tocExp = new RegExp("^" + toc.config.marker + "$", "g");
// Run TOC generation when conversion is finished directly on HTML // Run TOC generation when conversion is finished directly on HTML
editor.hooks.chain("onPreviewRefresh", function() { editor.hooks.chain("onPreviewRefresh", function() {
var htmlToc = buildToc(); var htmlToc = buildToc();
// Replace toc paragraphs // Replace toc paragraphs
$("#preview-contents p").each(function() { _.each(previewContentsElt.getElementsByTagName('p'), function(elt) {
if(tocExp.test($(this).html())) { if(tocExp.test(elt.innerHTML)) {
$(this).html(htmlToc); elt.innerHTML = htmlToc;
} }
}); });
// Add toc in the TOC button // Add toc in the TOC button
$(".table-of-contents").html(htmlToc); _.each(tocEltList, function(elt) {
elt.innerHTML = htmlToc;
});
}); });
}; };

View File

@ -482,6 +482,9 @@
// Find and convert footnotes references. // Find and convert footnotes references.
Markdown.Extra.prototype.doFootnotes = function(text) { Markdown.Extra.prototype.doFootnotes = function(text) {
var self = this; var self = this;
if(self.isConvertingFootnote === true) {
return text;
}
var footnoteCounter = 0; var footnoteCounter = 0;
text = text.replace(/\[\^(.+?)\]/g, function(wholeMatch, m1) { text = text.replace(/\[\^(.+?)\]/g, function(wholeMatch, m1) {
@ -512,7 +515,9 @@
for(var i=0; i<self.usedFootnotes.length; i++) { for(var i=0; i<self.usedFootnotes.length; i++) {
var id = self.usedFootnotes[i]; var id = self.usedFootnotes[i];
var footnote = self.footnotes[id]; var footnote = self.footnotes[id];
self.isConvertingFootnote = true;
var formattedfootnote = convertSpans(footnote, self); var formattedfootnote = convertSpans(footnote, self);
delete self.isConvertingFootnote;
text += '<li id="fn:' text += '<li id="fn:'
+ id + id
+ '">' + '">'

View File

@ -4,6 +4,7 @@ requirejs.config({
paths: { paths: {
"jquery": "libs/jquery", "jquery": "libs/jquery",
"underscore": "libs/underscore", "underscore": "libs/underscore",
"crel": "libs/crel",
"jgrowl": "libs/jgrowl", "jgrowl": "libs/jgrowl",
"mousetrap": "libs/mousetrap", "mousetrap": "libs/mousetrap",
"toMarkdown": "libs/to-markdown", "toMarkdown": "libs/to-markdown",