diff --git a/public/res/classes/FileDescriptor.js b/public/res/classes/FileDescriptor.js index 5b990492..ce0a1e89 100644 --- a/public/res/classes/FileDescriptor.js +++ b/public/res/classes/FileDescriptor.js @@ -131,7 +131,7 @@ define([ result.push(''); }); if(_.size(this.publishLocations) !== 0) { - result.push(''); + result.push(''); } result.push(_.escape(this.title)); return result.join(''); diff --git a/public/res/core.js b/public/res/core.js index 78322ee4..8b7e8eb1 100644 --- a/public/res/core.js +++ b/public/res/core.js @@ -4,7 +4,7 @@ define([ "underscore", "crel", "ace", - "classes/PreEditor", + "preEditor", "constants", "utils", "storage", @@ -26,7 +26,7 @@ define([ 'ace/ext/spellcheck', 'ace/ext/searchbox' -], function($, _, crel, ace, PreEditor, constants, utils, storage, settings, eventMgr, shortcutMgr, mousetrap, bodyIndexHTML, bodyViewerHTML, settingsTemplateTooltipHTML, settingsUserCustomExtensionTooltipHTML) { +], function($, _, crel, ace, preEditor, constants, utils, storage, settings, eventMgr, shortcutMgr, mousetrap, bodyIndexHTML, bodyViewerHTML, settingsTemplateTooltipHTML, settingsUserCustomExtensionTooltipHTML) { var core = {}; @@ -362,10 +362,10 @@ define([ north__minSize: 49, center__minWidth: 250, center__minHeight: 180, - east__onAlert: function() { + east__onalert: function() { window.location.href = 'viewer'; }, - south__onAlert: function() { + south__onalert: function() { window.location.href = 'viewer'; }, fxSettings: { @@ -385,12 +385,12 @@ define([ } }, onresize_end: function(paneName) { - if(preEditor.$preContentElt !== undefined && paneName == 'center') { + if(preEditor.$contentElt !== undefined && paneName == 'center') { var padding = ($editorElt.width() - getMaxWidth()) / 2; if(padding < constants.EDITOR_DEFAULT_PADDING) { padding = constants.EDITOR_DEFAULT_PADDING; } - preEditor.$preContentElt.css({ + preEditor.$contentElt.css({ 'padding-left': padding + 'px', 'padding-right': padding + 'px' }); @@ -499,7 +499,6 @@ define([ var fileDesc; var documentContent; var UndoManager = require("ace/undomanager").UndoManager; - var preEditor; core.initEditor = function(fileDescParam) { if(fileDesc !== undefined) { eventMgr.onFileClosed(fileDesc); @@ -587,15 +586,30 @@ define([ if(aceEditor !== undefined) { newDocumentContent = aceEditor.getValue(); } - if(documentContent === undefined) { - preEditor.highlight(); + if(documentContent == newDocumentContent) { + return false; } - else if(documentContent != newDocumentContent) { + + if(documentContent !== undefined) { fileDesc.content = newDocumentContent; eventMgr.onContentChanged(fileDesc); - preEditor.highlight(); } + else { + eventMgr.onFileOpen(fileDesc); + $previewContainerElt.scrollTop(fileDesc.previewScrollTop); + if(window.lightMode) { + $editorElt.scrollTop(fileDesc.editorScrollTop); + } + else { + preEditor.scrollTop = fileDesc.editorScrollTop; + _.defer(function() { + aceEditor.renderer.scrollToY(fileDesc.editorScrollTop); + }); + } + } + documentContent = newDocumentContent; + return true; } var previewWrapper; @@ -629,44 +643,17 @@ define([ previewWrapper = function(makePreview) { var debouncedMakePreview = _.debounce(makePreview, 500); return function() { - if(documentContent === undefined) { - makePreview(); - eventMgr.onFileOpen(fileDesc); - $previewContainerElt.scrollTop(fileDesc.previewScrollTop); - if(window.lightMode) { - preEditor.scrollTop = fileDesc.editorScrollTop; - $editorElt.scrollTop(preEditor.scrollTop); - } - else { - _.defer(function() { - aceEditor.renderer.scrollToY(fileDesc.editorScrollTop); - }); - } + var debounce = documentContent !== undefined; + if(checkDocumentChanges()) { + debounce ? debouncedMakePreview() : makePreview(); } - else { - debouncedMakePreview(); - } - checkDocumentChanges(); }; }; } else { previewWrapper = function(makePreview) { return function() { - makePreview(); - if(documentContent === undefined) { - eventMgr.onFileOpen(fileDesc); - $previewContainerElt.scrollTop(fileDesc.previewScrollTop); - if(window.lightMode) { - $editorElt.scrollTop(fileDesc.editorScrollTop); - } - else { - _.defer(function() { - aceEditor.renderer.scrollToY(fileDesc.editorScrollTop); - }); - } - } - checkDocumentChanges(); + checkDocumentChanges() && makePreview(); }; }; } @@ -861,7 +848,7 @@ define([ // In pre mode, we replace ACE with an editable pre $('#wmd-input').replaceWith(function() { var result = $('
').addClass(this.className).addClass('form-control');
- preEditor = new PreEditor(result[0]);
+ preEditor.init(result[0]);
return result;
});
@@ -1032,7 +1019,7 @@ define([
});
$(".action-import-docs-settings-confirm").click(function() {
storage.clear();
- var allowedKeys = /^file\.|^focusMode$|^folder\.|^publish\.|^settings$|^sync\.|^google\.|^themeV3$|^mode$|^version$|^welcomeTour$/;
+ var allowedKeys = /^file\.|^folder\.|^publish\.|^settings$|^sync\.|^google\.|^themeV3$|^mode$|^version$|^welcomeTour$/;
_.each(newstorage, function(value, key) {
if(allowedKeys.test(key)) {
storage[key] = value;
diff --git a/public/res/eventMgr.js b/public/res/eventMgr.js
index 631b7f60..451695aa 100644
--- a/public/res/eventMgr.js
+++ b/public/res/eventMgr.js
@@ -39,7 +39,7 @@ define([
"extensions/spellCheck",
"extensions/userCustom",
"bootstrap",
- "jquery-waitforimages"
+ "jquery-waitforimages",
], function($, _, crel, utils, logger, Extension, settings, settingsExtensionsAccordionHTML) {
var eventMgr = {};
@@ -233,7 +233,6 @@ define([
_.each(previewContentsElt.children, function(elt) {
html += elt.innerHTML;
});
- html = html.replace(/^<\/div>\n\n/gm, '');
var htmlWithComments = utils.trim(html);
var htmlWithoutComments = htmlWithComments.replace(/ .*?<\/span> /g, '');
onPreviewFinished(htmlWithComments, htmlWithoutComments);
diff --git a/public/res/extensions/buttonFocusMode.js b/public/res/extensions/buttonFocusMode.js
index 890c59ee..ec83adc4 100644
--- a/public/res/extensions/buttonFocusMode.js
+++ b/public/res/extensions/buttonFocusMode.js
@@ -2,11 +2,10 @@ define([
"jquery",
"underscore",
"crel",
- "storage",
"classes/Extension"
-], function($, _, crel, storage, Extension) {
+], function($, _, crel, Extension) {
- var buttonFocusMode = new Extension("buttonFocusMode", 'Button "Focus Mode"', true, true, true);
+ var buttonFocusMode = new Extension("buttonFocusMode", 'Button "Focus Mode"', true, true);
buttonFocusMode.settingsBlock = "When typing, scrolls automatically the editor to always have the caret centered verticaly.";
var aceEditor;
@@ -14,48 +13,57 @@ define([
aceEditor = aceEditorParam;
};
- var isFocusModeOn = false;
var isMouseActive = false;
function doFocusMode() {
- if(isFocusModeOn === false || isMouseActive === true) {
- return;
+ if(aceEditor) {
+ if(isMouseActive === true) {
+ return;
+ }
+ var positionInDocument = aceEditor.selection.getCursor();
+ var positionInScreen = aceEditor.session.documentToScreenPosition(positionInDocument.row, positionInDocument.column);
+ aceEditor.session.setScrollTop((positionInScreen.row + 0.5) * aceEditor.renderer.lineHeight - aceEditor.renderer.$size.scrollerHeight / 2);
}
- var positionInDocument = aceEditor.selection.getCursor();
- var positionInScreen = aceEditor.session.documentToScreenPosition(positionInDocument.row, positionInDocument.column);
- aceEditor.session.setScrollTop((positionInScreen.row + 0.5) * aceEditor.renderer.lineHeight - aceEditor.renderer.$size.scrollerHeight / 2);
}
- var $button;
buttonFocusMode.onReady = function() {
- aceEditor.getSession().selection.on('changeCursor', doFocusMode);
- aceEditor.container.addEventListener('keydown', function() {
- isMouseActive = false;
- }, true);
- aceEditor.container.addEventListener('mousedown', function() {
- isMouseActive = true;
- }, true);
- if(storage.focusMode == 'on') {
- $button.click();
- }
- };
-
- buttonFocusMode.onCreateEditorButton = function() {
- $button = $([
- ''
- ].join(''));
- $button.click(function() {
- _.defer(function() {
- isFocusModeOn = $button.is('.active');
- storage.focusMode = isFocusModeOn ? 'on' : 'off';
+ if(aceEditor) {
+ aceEditor.getSession().selection.on('changeCursor', doFocusMode);
+ aceEditor.container.addEventListener('keydown', function() {
isMouseActive = false;
- aceEditor.focus();
- doFocusMode();
- });
+ }, true);
+ aceEditor.container.addEventListener('mousedown', function() {
+ isMouseActive = true;
+ }, true);
+ return;
+ }
+ var $editorElt = $('#wmd-input');
+ var $positionHelper = $('').css('display', 'inline-block');
+ var coef = 0.2;
+ $editorElt.on('keydown', function(event) {
+ if(event.altKey || event.ctrlKey || event.shiftKey || event.metaKey) {
+ return;
+ }
+ setTimeout(function() {
+ var range = window.getSelection().getRangeAt(0);
+ range.insertNode($positionHelper[0]);
+ var parentNode = $positionHelper[0].parentNode;
+ var editorHeight = $editorElt.height();
+ var cursorMinY = coef*editorHeight;
+ var cursorMaxY = (1-coef)*editorHeight;
+ var cursorY = $positionHelper.offset().top - $editorElt.offset().top;
+ $positionHelper.detach();
+ parentNode.normalize();
+ if(cursorY < cursorMinY) {
+ $editorElt.scrollTop($editorElt.scrollTop() - cursorMinY + cursorY);
+ }
+ else if(cursorY > cursorMaxY) {
+ $editorElt.scrollTop($editorElt.scrollTop() + cursorY - cursorMaxY);
+ }
+ }, 0);
});
- return $button[0];
};
return buttonFocusMode;
-});
\ No newline at end of file
+});
+
+
diff --git a/public/res/extensions/buttonPublish.js b/public/res/extensions/buttonPublish.js
index 0fc766aa..b7e78275 100644
--- a/public/res/extensions/buttonPublish.js
+++ b/public/res/extensions/buttonPublish.js
@@ -37,7 +37,7 @@ define([
class: 'btn btn-success button-publish',
title: 'Update document publication'
}, crel('i', {
- class: 'icon-share'
+ class: 'icon-upload'
}));
$button = $(button).click(function() {
if(!$button.hasClass("disabled")) {
diff --git a/public/res/extensions/markdownSectionParser.js b/public/res/extensions/markdownSectionParser.js
index f2a5f974..e5a13af1 100644
--- a/public/res/extensions/markdownSectionParser.js
+++ b/public/res/extensions/markdownSectionParser.js
@@ -11,11 +11,12 @@ define([
markdownSectionParser.onEventMgrCreated = function(eventMgrParameter) {
eventMgr = eventMgrParameter;
};
-
+
+ var sectionList = [];
+
+ // Regexp to look for section delimiters
+ var regexp = '^.+[ \\t]*\\n=+[ \\t]*\\n+|^.+[ \\t]*\\n-+[ \\t]*\\n+|^\\#{1,6}[ \\t]*.+?[ \\t]*\\#*\\n+'; // Title delimiters
markdownSectionParser.onPagedownConfigure = function(editor) {
-
- // Build a regexp to look for section delimiters
- var regexp = '^.+[ \\t]*\\n=+[ \\t]*\\n+|^.+[ \\t]*\\n-+[ \\t]*\\n+|^\\#{1,6}[ \\t]*.+?[ \\t]*\\#*\\n+'; // Title delimiters
if(markdownExtra.enabled) {
if(_.some(markdownExtra.config.extensions, function(extension) {
return extension == "fenced_code_gfm";
@@ -32,31 +33,44 @@ define([
regexp = new RegExp(regexp, 'gm');
var converter = editor.getConverter();
- converter.hooks.chain("preConversion", function(text) {
- eventMgr.previewStartTime = new Date();
- var tmpText = text + "\n\n";
- function addSection(startOffset, endOffset) {
- var sectionText = tmpText.substring(offset, endOffset);
- sectionList.push({
- text: sectionText,
- textWithDelimiter: '\n\n\n' + sectionText + '\n'
- });
- }
- var sectionList = [], offset = 0;
- // Look for delimiters
- tmpText.replace(regexp, function(match, matchOffset) {
- // Create a new section with the text preceding the delimiter
- addSection(offset, matchOffset);
- offset = matchOffset;
- });
- // Last section
- addSection(offset, text.length);
- eventMgr.onSectionsCreated(sectionList);
+ converter.hooks.chain("preConversion", function() {
return _.reduce(sectionList, function(result, section) {
- return result + section.textWithDelimiter;
+ return result + section.previewText;
}, '');
});
};
+
+ var trimLen;
+ markdownSectionParser.onMarkdownTrim = function(len) {
+ trimLen = len;
+ };
+
+ var sectionCounter = 0;
+ function parseFileContent(fileDesc) {
+ var text = fileDesc.content.substring(trimLen);
+ var tmpText = text + "\n\n";
+ function addSection(startOffset, endOffset) {
+ var sectionText = tmpText.substring(offset, endOffset);
+ sectionList.push({
+ id: ++sectionCounter,
+ text: sectionText
+ });
+ }
+ sectionList = [];
+ var offset = 0;
+ // Look for delimiters
+ tmpText.replace(regexp, function(match, matchOffset) {
+ // Create a new section with the text preceding the delimiter
+ addSection(offset, matchOffset);
+ offset = matchOffset;
+ });
+ // Last section
+ addSection(offset, text.length);
+ eventMgr.onSectionsCreated(sectionList);
+ }
+
+ markdownSectionParser.onFileOpen = parseFileContent;
+ markdownSectionParser.onContentChanged = parseFileContent;
return markdownSectionParser;
});
\ No newline at end of file
diff --git a/public/res/extensions/partialRendering.js b/public/res/extensions/partialRendering.js
index 32a288a6..e2d9dc7a 100644
--- a/public/res/extensions/partialRendering.js
+++ b/public/res/extensions/partialRendering.js
@@ -10,14 +10,51 @@ define([
partialRendering.settingsBlock = partialRenderingSettingsBlockHTML;
var converter;
- var sectionCounter = 0;
+ var doFootnotes = false;
+ var hasFootnotes = false;
+ var currentSectionList = [];
+
var sectionList = [];
var linkDefinition;
var sectionsToRemove = [];
var modifiedSections = [];
var insertBeforeSection;
var fileChanged = false;
- function updateSectionList(newSectionList, newLinkDefinition) {
+ function updateSectionList() {
+ var newSectionList = [];
+ var newLinkDefinition = '\n';
+ hasFootnotes = false;
+ _.each(currentSectionList, function(section) {
+ var text = '\n\n\n' + section.text + '\n\n';
+
+ // Strip footnotes
+ if(doFootnotes) {
+ text = text.replace(/^```.*\n[\s\S]*?\n```|\n[ ]{0,3}\[\^(.+?)\]\:[ \t]*\n?([\s\S]*?)\n{1,2}((?=\n[ ]{0,3}\S)|$)/gm, function(wholeMatch, footnote) {
+ if(footnote) {
+ hasFootnotes = true;
+ newLinkDefinition += wholeMatch.replace(/^\s*\n/gm, '') + '\n';
+ return "";
+ }
+ return wholeMatch;
+ });
+ }
+
+ // 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.replace(/^\s*\n/gm, '') + '\n';
+ return "";
+ }
+ return wholeMatch;
+ });
+
+ // Add section to the newSectionList
+ newSectionList.push({
+ id: section.id,
+ text: text + '\n'
+ });
+ });
+
modifiedSections = [];
sectionsToRemove = [];
insertBeforeSection = undefined;
@@ -65,47 +102,6 @@ define([
sectionList = leftSections.concat(modifiedSections).concat(rightSections);
}
- var doFootnotes = false;
- var hasFootnotes = false;
- partialRendering.onSectionsCreated = function(sectionListParam) {
-
- var newSectionList = [];
- var newLinkDefinition = '\n';
- hasFootnotes = false;
- _.each(sectionListParam, function(section) {
- var text = section.textWithDelimiter + '\n';
-
- // Strip footnotes
- if(doFootnotes) {
- text = text.replace(/^```.*\n[\s\S]*?\n```|\n[ ]{0,3}\[\^(.+?)\]\:[ \t]*\n?([\s\S]*?)\n{1,2}((?=\n[ ]{0,3}\S)|$)/gm, function(wholeMatch, footnote) {
- if(footnote) {
- hasFootnotes = true;
- newLinkDefinition += wholeMatch.replace(/^\s*\n/gm, '') + '\n';
- return "";
- }
- return wholeMatch;
- });
- }
-
- // 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.replace(/^\s*\n/gm, '') + '\n';
- return "";
- }
- return wholeMatch;
- });
-
- // Add section to the newSectionList
- newSectionList.push({
- id: ++sectionCounter,
- text: text + '\n'
- });
- });
-
- updateSectionList(newSectionList, newLinkDefinition);
- };
-
var footnoteMap = {};
// Store one footnote elt in the footnote map
function storeFootnote(footnoteElt) {
@@ -133,7 +129,8 @@ define([
var isNextDelimiter = false;
while (childNode) {
var nextNode = childNode.nextSibling;
- if(isNextDelimiter === true && childNode.tagName == 'DIV' && childNode.className == 'se-section-delimiter') {
+ var isDelimiter = childNode.className == 'se-preview-section-delimiter';
+ if(isNextDelimiter === true && childNode.tagName == 'DIV' && isDelimiter) {
// Stop when encountered the next delimiter
break;
}
@@ -142,7 +139,7 @@ define([
_.each(childNode.querySelectorAll("ol > li"), storeFootnote);
}
else {
- sectionElt.appendChild(childNode);
+ isDelimiter || sectionElt.appendChild(childNode);
}
childNode = nextNode;
}
@@ -182,9 +179,14 @@ define([
}
}
+ partialRendering.onSectionsCreated = function(sectionListParam) {
+ currentSectionList = sectionListParam;
+ };
+
partialRendering.onPagedownConfigure = function(editor) {
converter = editor.getConverter();
converter.hooks.chain("preConversion", function() {
+ updateSectionList();
var result = _.map(modifiedSections, function(section) {
return section.text;
});
diff --git a/public/res/extensions/scrollLink.js b/public/res/extensions/scrollLink.js
index 457babaa..9ebc86a4 100644
--- a/public/res/extensions/scrollLink.js
+++ b/public/res/extensions/scrollLink.js
@@ -23,68 +23,48 @@ define([
offsetBegin = offsetBeginParam;
};
- var $textareaElt;
- var $textareaHelperElt;
+ var $editorElt;
var $previewElt;
var mdSectionList = [];
var htmlSectionList = [];
var lastEditorScrollTop;
var lastPreviewScrollTop;
var buildSections = _.debounce(function() {
-
+ if(!isPreviewVisible) {
+ return;
+ }
mdSectionList = [];
- var mdTextOffset = 0;
- var mdSectionOffset = 0;
+ var mdSectionOffset;
var firstSectionOffset = offsetBegin;
- var padding = 0;
- function addTextareaSection(sectionText) {
- var sectionHeight = padding;
- if(sectionText !== undefined) {
- var textNode = document.createTextNode(sectionText);
- $textareaHelperElt.empty().append(textNode);
- sectionHeight += $textareaHelperElt.prop('scrollHeight');
- }
- var newSectionOffset = mdSectionOffset + sectionHeight;
+ var scrollHeight;
+ if(window.lightMode) {
+ var editorScrollTop = $editorElt.scrollTop();
+ $editorElt.find(".wmd-input-section").each(function() {
+ if(mdSectionOffset === undefined) {
+ // Force start to 0 for the first section
+ mdSectionOffset = 0;
+ return;
+ }
+ var $delimiterElt = $(this);
+ // Consider div scroll position
+ var newSectionOffset = $delimiterElt.position().top + editorScrollTop;
+ mdSectionList.push({
+ startOffset: mdSectionOffset,
+ endOffset: newSectionOffset,
+ height: newSectionOffset - mdSectionOffset
+ });
+ mdSectionOffset = newSectionOffset;
+ });
+ // Last section
+ scrollHeight = $editorElt.prop('scrollHeight');
mdSectionList.push({
startOffset: mdSectionOffset,
- endOffset: newSectionOffset,
- height: sectionHeight
- });
- mdSectionOffset = newSectionOffset;
- }
- if(window.lightMode) {
- // Special treatment for light mode
- $textareaHelperElt.innerWidth($textareaElt.innerWidth());
- _.each(sectionList, function(section, index) {
- var sectionText = section.text;
- if(index !== sectionList.length - 1) {
- if(sectionText.length === 0) {
- sectionText = undefined;
- }
- }
- else {
- if(/\n$/.test(sectionText)) {
- // Need to add a line break to take into account a final empty line
- sectionText += '\n';
- }
- }
- addTextareaSection(sectionText);
- });
-
- // Apply a coef to manage divergence in some browsers
- var theoricalHeight = _.last(mdSectionList).endOffset;
- var realHeight = $textareaElt[0].scrollHeight;
- var coef = realHeight/theoricalHeight;
- mdSectionList = _.map(mdSectionList, function(mdSection) {
- return {
- startOffset: mdSection.startOffset * coef,
- endOffset: mdSection.endOffset * coef,
- height: mdSection.height * coef,
- };
+ endOffset: scrollHeight,
+ height: scrollHeight - mdSectionOffset
});
}
else {
- // Everything's much simpler with ACE
+ var mdTextOffset = 0;
_.each(sectionList, function(section) {
mdTextOffset += section.text.length + firstSectionOffset;
firstSectionOffset = 0;
@@ -101,11 +81,11 @@ define([
});
}
- // Try to find corresponding sections in the preview
+ // Find corresponding sections in the preview
htmlSectionList = [];
var htmlSectionOffset;
var previewScrollTop = $previewElt.scrollTop();
- $previewElt.find(".preview-content > .se-section-delimiter").each(function() {
+ $previewElt.find(".wmd-preview-section").each(function() {
if(htmlSectionOffset === undefined) {
// Force start to 0 for the first section
htmlSectionOffset = 0;
@@ -122,7 +102,7 @@ define([
htmlSectionOffset = newSectionOffset;
});
// Last section
- var scrollHeight = $previewElt.prop('scrollHeight');
+ scrollHeight = $previewElt.prop('scrollHeight');
htmlSectionList.push({
startOffset: htmlSectionOffset,
endOffset: scrollHeight,
@@ -141,12 +121,10 @@ define([
var isPreviewMoving = false;
var scrollingHelper = $('');
var doScrollLink = _.throttle(function() {
- if(mdSectionList.length === 0 || mdSectionList.length !== htmlSectionList.length) {
- // Delay
- doScrollLink();
+ if(!isPreviewVisible || mdSectionList.length === 0 || mdSectionList.length !== htmlSectionList.length) {
return;
}
- var editorScrollTop = window.lightMode ? $textareaElt.scrollTop() : aceEditor.renderer.getScrollTop();
+ var editorScrollTop = window.lightMode ? $editorElt.scrollTop() : aceEditor.renderer.getScrollTop();
editorScrollTop < 0 && (editorScrollTop = 0);
var previewScrollTop = $previewElt.scrollTop();
function getDestScrollTop(srcScrollTop, srcSectionList, destSectionList) {
@@ -157,7 +135,7 @@ define([
return srcScrollTop < section.endOffset;
});
if(srcSection === undefined) {
- // Something wrong in the algorithm...
+ // Something very bad happened
return;
}
var posInSection = (srcScrollTop - srcSection.startOffset) / (srcSection.height || 1);
@@ -211,7 +189,7 @@ define([
if(window.lightMode) {
destScrollTop = _.min([
destScrollTop,
- $textareaElt.prop('scrollHeight') - $textareaElt.outerHeight()
+ $editorElt.prop('scrollHeight') - $editorElt.outerHeight()
]);
}
else {
@@ -228,7 +206,7 @@ define([
return;
}
if(window.lightMode) {
- $textareaElt.stop('scrollLinkFx', true).animate({
+ $editorElt.stop('scrollLinkFx', true).animate({
scrollTop: destScrollTop
}, {
easing: 'easeOutSine',
@@ -271,6 +249,23 @@ define([
isScrollEditor = true;
buildSections();
};
+
+ var isPreviewVisible = true;
+ function setPreviewHidden() {
+ isPreviewVisible = false;
+ console.log(isPreviewVisible);
+ }
+ function setPreviewVisible() {
+ isPreviewVisible = true;
+ console.log(isPreviewVisible);
+ }
+
+ scrollLink.onLayoutConfigure = function(layoutGlobalConfig) {
+ layoutGlobalConfig.east__onclose = setPreviewHidden;
+ layoutGlobalConfig.south__onclose = setPreviewHidden;
+ layoutGlobalConfig.east__onopen_start = setPreviewVisible;
+ layoutGlobalConfig.south__onclose_start = setPreviewVisible;
+ };
scrollLink.onFileClosed = function() {
mdSectionList = [];
@@ -279,9 +274,7 @@ define([
var scrollAdjust = false;
scrollLink.onReady = function() {
$previewElt = $(".preview-container");
- $textareaElt = $("#wmd-input");
- // This helper is used to measure sections height in light mode
- $textareaHelperElt = $('.textarea-helper');
+ $editorElt = $("#wmd-input");
$previewElt.scroll(function() {
if(isPreviewMoving === false && scrollAdjust === false) {
@@ -299,7 +292,7 @@ define([
}
};
if(window.lightMode) {
- $textareaElt.scroll(handleEditorScroll);
+ $editorElt.scroll(handleEditorScroll);
}
else {
aceEditor.session.on("changeScrollTop", handleEditorScroll);
diff --git a/public/res/extensions/toc.js b/public/res/extensions/toc.js
index c592050b..554af8f2 100644
--- a/public/res/extensions/toc.js
+++ b/public/res/extensions/toc.js
@@ -121,7 +121,7 @@ define([
toc.onPagedownConfigure = function(editor) {
previewContentsElt = document.getElementById('preview-contents');
- var tocExp = new RegExp("^" + toc.config.marker + "$");
+ var tocExp = new RegExp("^\\s*" + toc.config.marker + "\\s*$");
// Run TOC generation when conversion is finished directly on HTML
editor.hooks.chain("onPreviewRefresh", function() {
var tocEltList = document.querySelectorAll('.table-of-contents, .toc');
diff --git a/public/res/extensions/welcomeTour.js b/public/res/extensions/welcomeTour.js
index e959d05d..a0c8860b 100644
--- a/public/res/extensions/welcomeTour.js
+++ b/public/res/extensions/welcomeTour.js
@@ -100,7 +100,7 @@ define([
{
element: '.navbar-inner > .nav .button-publish, .navbar .right-buttons-dropdown > .nav > .btn:not(:hidden)',
title: 'Update publication',
- content: 'Once published, use the Publish button to update the publication.',
+ content: 'Once published, use the Publish button to update the publication.',
placement: 'left',
reflex: true,
},
diff --git a/public/res/extensions/yamlFrontMatterParser.js b/public/res/extensions/yamlFrontMatterParser.js
index 7eca45fd..7e98cb63 100644
--- a/public/res/extensions/yamlFrontMatterParser.js
+++ b/public/res/extensions/yamlFrontMatterParser.js
@@ -17,30 +17,27 @@ define([
};
var regex = /^(\s*-{3}\s*\n([\w\W]+?)\n\s*-{3}\s*\n)?([\w\W]*)$/;
- yamlFrontMatterParser.onPagedownConfigure = function(editor) {
- var converter = editor.getConverter();
- converter.hooks.chain("preConversion", function(text) {
- var results = regex.exec(text);
- var yaml = results[2];
+ yamlFrontMatterParser.onContentChanged = function(fileDesc) {
+ var text = fileDesc.content;
+ var results = regex.exec(text);
+ var yaml = results[2];
- if (yaml && (!fileDesc.frontMatter || fileDesc.frontMatter._yaml != yaml)) {
- fileDesc.frontMatter = undefined;
- try {
- fileDesc.frontMatter = YAML.parse(yaml);
- if(!_.isObject(fileDesc.frontMatter)) {
- fileDesc.frontMatter = undefined;
- }
- fileDesc.frontMatter._yaml = yaml;
- fileDesc.frontMatter._frontMatter = results[1];
- }
- catch (e) {
- eventMgr.onMarkdownTrim(0);
- return text;
+ if (yaml && (!fileDesc.frontMatter || fileDesc.frontMatter._yaml != yaml)) {
+ fileDesc.frontMatter = undefined;
+ try {
+ fileDesc.frontMatter = YAML.parse(yaml);
+ if(!_.isObject(fileDesc.frontMatter)) {
+ fileDesc.frontMatter = undefined;
}
+ fileDesc.frontMatter._yaml = yaml;
+ fileDesc.frontMatter._frontMatter = results[1];
}
- eventMgr.onMarkdownTrim((results[1] || '').length);
- return results[3];
- });
+ catch (e) {
+ eventMgr.onMarkdownTrim(0);
+ return text;
+ }
+ }
+ eventMgr.onMarkdownTrim((results[1] || '').length);
};
return yamlFrontMatterParser;
diff --git a/public/res/font/fontello.eot b/public/res/font/fontello.eot
index 3899c95a..52d6a9e3 100644
Binary files a/public/res/font/fontello.eot and b/public/res/font/fontello.eot differ
diff --git a/public/res/font/fontello.svg b/public/res/font/fontello.svg
index cd208f44..06932346 100644
--- a/public/res/font/fontello.svg
+++ b/public/res/font/fontello.svg
@@ -1,7 +1,7 @@
\ No newline at end of file
diff --git a/public/res/font/fontello.ttf b/public/res/font/fontello.ttf
index 67268b8b..f33dbb00 100644
Binary files a/public/res/font/fontello.ttf and b/public/res/font/fontello.ttf differ
diff --git a/public/res/font/fontello.woff b/public/res/font/fontello.woff
index c0eb19e1..da4c5042 100644
Binary files a/public/res/font/fontello.woff and b/public/res/font/fontello.woff differ
diff --git a/public/res/html/bodyIndex.html b/public/res/html/bodyIndex.html
index bcf2b9be..bb5612c3 100644
--- a/public/res/html/bodyIndex.html
+++ b/public/res/html/bodyIndex.html
@@ -62,20 +62,6 @@
EXPORT
- Save...
-
Synchronize...
@@ -87,13 +73,13 @@
Publish...
+ class="list-group-item"> Publish...
- Sharing...
+ Sharing links
+ Export to disk
+
IMPORT
Open from disk
+ class="icon-hdd"> Import from disk
Open from URL
+ class="icon-globe"> Import from URL
- Open from URL
+ Import from URL
Please provide a link to a Markdown document.
@@ -485,7 +485,7 @@
- Export to Dropbox
+ Save on Dropbox
diff --git a/public/res/html/dialogExportGdrive.html b/public/res/html/dialogExportGdrive.html
index 61a236fc..83192b7b 100644
--- a/public/res/html/dialogExportGdrive.html
+++ b/public/res/html/dialogExportGdrive.html
@@ -4,7 +4,7 @@
- Export to <%= providerName %>
+ Save on <%= providerName %>
diff --git a/public/res/libs/layout.js b/public/res/libs/layout.js
index 6adcf9b8..72de2f3a 100644
--- a/public/res/libs/layout.js
+++ b/public/res/libs/layout.js
@@ -793,7 +793,7 @@ $.layout.defaults = {
, onswap_end: null // CALLBACK when pane ENDS being Swapped
, ondrag_start: null // CALLBACK when pane STARTS being ***MANUALLY*** Resized
, ondrag_end: null // CALLBACK when pane ENDS being ***MANUALLY*** Resized
- , onAlert: null
+ , onalert: null
}
/*
* PANE-SPECIFIC SETTINGS
@@ -3479,7 +3479,7 @@ $.fn.layout = function (opts) {
if (s.minSize > s.maxSize) { // INSUFFICIENT ROOM FOR PANE TO OPEN!
syncPinBtns(pane, false); // make sure pin-buttons are reset
if (!noAlert && o.tips.noRoomToOpen)
- o.onAlert ? o.onAlert(o.tips.noRoomToOpen) : alert(o.tips.noRoomToOpen);
+ o.onalert ? o.onalert(o.tips.noRoomToOpen) : alert(o.tips.noRoomToOpen);
return queueNext(); // ABORT
}
diff --git a/public/res/libs/prism-markdown.js b/public/res/libs/prism-markdown.js
index 564a8b76..dc0875f4 100644
--- a/public/res/libs/prism-markdown.js
+++ b/public/res/libs/prism-markdown.js
@@ -100,15 +100,10 @@ Prism.languages.md = (function() {
linktitle: /['\"\(][^\'\"\)]*['\"\)]/
}
};
- md.tocmarker = {
- pattern: /(^|(?:^|\n)\s*\n)[ \t]*\[(toc|TOC)\]($|\n($|\s*\n))$/g,
- inside: {
- "md md-toc": /\[(toc|TOC)\]/
- }
- };
md.p = {
- pattern: /^[^\n]+(?:\n|$)/gm,
+ pattern: /.+/g,
inside: {
+ 'md md-toc': /^\s*\[(toc|TOC)\]\s*$/g
}
};
md.img = {
diff --git a/public/res/classes/PreEditor.js b/public/res/preEditor.js
similarity index 65%
rename from public/res/classes/PreEditor.js
rename to public/res/preEditor.js
index 7d44b161..033b9921 100644
--- a/public/res/classes/PreEditor.js
+++ b/public/res/preEditor.js
@@ -1,55 +1,57 @@
/* jshint -W084, -W099 */
define([
'jquery',
+ 'underscore',
'eventMgr',
'prism-core',
+ 'crel',
'libs/prism-markdown'
-], function ($, eventMgr, Prism) {
+], function ($, _, eventMgr, Prism, crel) {
+
+ String.prototype.splice = function (i, remove, add) {
+ remove = +remove || 0;
+ add = add || '';
+ return this.slice(0, i) + add + this.slice(i + remove);
+ };
+
+ var preEditor = {};
var undoManager;
- eventMgr.addListener('onPagedownConfigure', function (pagedownEditor) {
+ eventMgr.addListener('onPagedownConfigure', function(pagedownEditor) {
// Undo manager does exist at the moment
setTimeout(function () {
undoManager = pagedownEditor.undoManager;
}, 0);
});
- String.prototype.splice = function (i, remove, add) {
- remove = +remove || 0;
- add = add || '';
+ eventMgr.addListener('onSectionsCreated', function(newSectionList) {
+ updateSectionList(newSectionList);
+ highlightSections();
+ });
- return this.slice(0, i) + add + this.slice(i + remove);
- };
+ var fileChanged = false;
+ eventMgr.addListener('onFileSelected', function() {
+ fileChanged = true;
+ });
- function PreEditor(preElt) {
- var preEditor = this;
- preEditor.selectionStart = 0;
- preEditor.selectionEnd = 0;
- preEditor.scrollTop = 0;
- preEditor.$preContentElt = $('
');
+ preEditor.selectionStart = 0;
+ preEditor.selectionEnd = 0;
+ preEditor.scrollTop = 0;
+ var preElt;
+ preEditor.init = function(elt) {
+ preElt = elt;
+ preEditor.$contentElt = $('');
+ preElt.appendChild(preEditor.$contentElt[0]);
- preElt.appendChild(preEditor.$preContentElt[0]);
- preEditor.highlight = function () {
- setTimeout(function () {
- preEditor.selectionStart = preElt.selectionStart;
- preEditor.selectionEnd = preElt.selectionEnd;
- var startDate = Date.now();
- Prism.highlightElement(preEditor.$preContentElt[0], false, function () {
- console.log(Date.now() - startDate);
- preElt.setSelectionRange(preEditor.selectionStart, preEditor.selectionEnd);
- });
- }, 0);
- };
-
- preElt.focus = function () {
- preEditor.$preContentElt.focus();
+ preElt.focus = function() {
+ preEditor.$contentElt.focus();
this.setSelectionRange(preEditor.selectionStart, preEditor.selectionEnd);
preElt.scrollTop = preEditor.scrollTop;
};
- preEditor.$preContentElt.focus(function () {
+ preEditor.$contentElt.focus(function () {
preElt.focused = true;
});
- preEditor.$preContentElt.blur(function () {
+ preEditor.$contentElt.blur(function () {
preElt.focused = false;
});
Object.defineProperty(preElt, 'value', {
@@ -57,7 +59,7 @@ define([
return this.textContent;
},
set: function (value) {
- //return preEditor.$preContentElt.text(value);
+ //return preEditor.$contentElt.text(value);
var currentValue = this.textContent;
// Find the first modified char
@@ -70,7 +72,7 @@ define([
startIndex++;
}
if (startIndex === startIndexMax) {
- return preEditor.$preContentElt.text(value);
+ return preEditor.$contentElt.text(value);
}
// Find the last modified char
@@ -385,7 +387,7 @@ define([
}
};
- preEditor.$preContentElt.on('keydown', function (evt) {
+ preEditor.$contentElt.on('keydown', function (evt) {
var cmdOrCtrl = evt.metaKey || evt.ctrlKey;
switch (evt.keyCode) {
@@ -411,8 +413,144 @@ define([
break;
}
});
+ };
+
+ var sectionList = [];
+ var sectionsToRemove = [];
+ var modifiedSections = [];
+ var insertBeforeSection;
+ function updateSectionList(newSectionList) {
+
+ modifiedSections = [];
+ sectionsToRemove = [];
+ insertBeforeSection = undefined;
+
+ // Render everything if file changed
+ if(fileChanged === true) {
+ sectionsToRemove = sectionList;
+ sectionList = newSectionList;
+ modifiedSections = newSectionList;
+ return;
+ }
+
+ // Find modified section starting from top
+ var leftIndex = sectionList.length;
+ _.some(sectionList, function(section, index) {
+ if(index >= newSectionList.length || section.text != newSectionList[index].text) {
+ leftIndex = index;
+ return true;
+ }
+ });
+
+ // Find modified section starting from bottom
+ var rightIndex = -sectionList.length;
+ _.some(sectionList.slice().reverse(), function(section, index) {
+ if(index >= newSectionList.length || section.text != newSectionList[newSectionList.length - index - 1].text) {
+ rightIndex = -index;
+ return true;
+ }
+ });
+
+ if(leftIndex - rightIndex > sectionList.length) {
+ // Prevent overlap
+ rightIndex = leftIndex - sectionList.length;
+ }
+
+ // Create an array composed of left unmodified, modified, right
+ // unmodified sections
+ var leftSections = sectionList.slice(0, leftIndex);
+ modifiedSections = newSectionList.slice(leftIndex, newSectionList.length + rightIndex);
+ var rightSections = sectionList.slice(sectionList.length + rightIndex, sectionList.length);
+ insertBeforeSection = _.first(rightSections);
+ sectionsToRemove = sectionList.slice(leftIndex, sectionList.length + rightIndex);
+ sectionList = leftSections.concat(modifiedSections).concat(rightSections);
+ }
+
+ var elapsedTime = 0;
+ var timeoutId;
+ function highlightSections() {
+
+ if(fileChanged === true) {
+ fileChanged = false;
+ // Perform a synchronous transformation
+ preEditor.selectionStart = preElt.selectionStart;
+ preEditor.selectionEnd = preElt.selectionEnd;
+ var newSectionEltList = document.createDocumentFragment();
+ modifiedSections.forEach(function(section) {
+ highlight(section);
+ newSectionEltList.appendChild(section.highlightedContent);
+ });
+ preEditor.$contentElt.html('');
+ preEditor.$contentElt[0].appendChild(newSectionEltList);
+ preElt.setSelectionRange(preEditor.selectionStart, preEditor.selectionEnd);
+ return;
+ }
+
+ // Perform an asynchronous transformation on each modified sections
+ clearTimeout(timeoutId);
+ //timeoutId = setTimeout(asyncHighlightSections, elapsedTime);
+ preEditor.selectionStart = preElt.selectionStart;
+ preEditor.selectionEnd = preElt.selectionEnd;
+ Prism.highlightElement(preEditor.$contentElt[0]);
+ //preElt.setSelectionRange(preEditor.selectionStart, preEditor.selectionEnd);
}
- return PreEditor;
+ function asyncHighlightSections() {
+ var startTime = Date.now();
+ var deferredList = [];
+ modifiedSections.forEach(function(section) {
+ var deferred = $.Deferred();
+ setTimeout(function() {
+ highlight(section);
+ deferred.resolve();
+ }, 0);
+ deferredList.push(deferred);
+ });
+ $.when.apply($, deferredList).then(function() {
+ var text = _.reduce(sectionList, function(text, section) {
+ return text + section.text;
+ }, '');
+
+ // Check that the editor has the actual value
+ if(preElt.textContent == text) {
+ preEditor.selectionStart = preElt.selectionStart;
+ preEditor.selectionEnd = preElt.selectionEnd;
+
+ // Remove outdated sections
+ _.each(sectionsToRemove, function(section) {
+ var sectionElt = document.getElementById("wmd-input-section-" + section.id);
+ preEditor.$contentElt[0].removeChild(sectionElt);
+ });
+
+ var newSectionEltList = document.createDocumentFragment();
+ modifiedSections.forEach(function(section) {
+ newSectionEltList.appendChild(section.highlightedContent);
+ });
+
+ if(insertBeforeSection !== undefined) {
+ var insertBeforeElt = document.getElementById("wmd-input-section-" + insertBeforeSection.id);
+ preEditor.$contentElt[0].insertBefore(newSectionEltList, insertBeforeElt);
+ }
+ else {
+ preEditor.$contentElt[0].appendChild(newSectionEltList);
+ }
+
+ preElt.setSelectionRange(preEditor.selectionStart, preEditor.selectionEnd);
+ elapsedTime = Date.now() - startTime;
+ }
+ });
+ }
+
+ function highlight(section) {
+ var text = section.text.replace(/&/g, '&').replace(/