Switch to ACE editor

This commit is contained in:
benweet 2013-09-14 17:59:40 +01:00
parent f5e80f2bbc
commit ca34415d22
24 changed files with 12111 additions and 3859 deletions

View File

@ -21,6 +21,7 @@ module.exports = function(grunt) {
out: "res-min/main.js",
mainConfigFile: 'res/main.js',
optimize: "uglify2",
inlineText: true,
uglify2: {
output: {
beautify: true,

View File

@ -1,6 +1,6 @@
{
"name": "stackedit",
"version": "2.0.3",
"version": "2.1.0",
"description": "StackEdit is a free, open-source Markdown editor based on PageDown, the Markdown library used by Stack Overflow and the other Stack Exchange sites.",
"dependencies": {
"bootstrap": "3.0.0",

View File

@ -1,5 +1,5 @@
CACHE MANIFEST
#Date Sat Sep 07 2013 23:38:12
#Date Sat Sep 14 2013 17:58:48
CACHE:
index.html

View File

@ -1,6 +1,6 @@
{
"name": "stackedit",
"version": "2.0.3",
"version": "2.1.0",
"description": "StackEdit is a free, open-source Markdown editor based on PageDown, the Markdown library used by Stack Overflow and the other Stack Exchange sites.",
"main": "res/main.js",
"directories": {

Binary file not shown.

View File

@ -186,7 +186,7 @@
<glyph glyph-name="angle-up" unicode="&#xe87f;" d="M600 189q0-7-6-13l-28-28q-6-6-13-6t-13 6l-219 219-219-219q-6-6-13-6t-13 6l-28 28q-6 6-6 13t6 13l260 260q6 6 13 6t13-6l260-260q6-6 6-13z" horiz-adv-x="642.857" />
<glyph glyph-name="angle-down" unicode="&#xe880;" d="M600 439q0-7-6-13l-260-260q-6-6-13-6t-13 6l-260 260q-6 6-6 13t6 13l28 28q6 6 13 6t13-6l219-219 219 219q6 6 13 6t13-6l28-28q6-6 6-13z" horiz-adv-x="642.857" />
<glyph glyph-name="desktop" unicode="&#xe95a;" d="M1000 296l0 464q0 7-5 13t-13 5l-893 0q-7 0-13-5t-5-13l0-464q0-7 5-13t13-5l893 0q7 0 13 5t5 13z m71 464l0-607q0-37-26-63t-63-26l-304 0q0-21 9-43t18-40 9-24q0-15-11-25t-25-11l-286 0q-15 0-25 11t-11 25q0 8 9 25t18 39 9 44l-304 0q-37 0-63 26t-26 63l0 607q0 37 26 63t63 26l893 0q37 0 63-26t26-63z" horiz-adv-x="1071.429" />
<glyph glyph-name="laptop" unicode="&#xe95b;" d="M232 136q-37 0-63 26t-26 63l0 393q0 37 26 63t63 26l607 0q37 0 63-26t26-63l0-393q0-37-26-63t-63-26l-607 0z m-18 482l0-393q0-7 5-13t13-5l607 0q7 0 13 5t5 13l0 393q0 7-5 13t-13 5l-607 0q-7 0-13-5t-5-13z m768-518l89 0 0-54q0-22-26-38t-63-16l-893 0q-37 0-63 16t-26 38l0 54 982 0z m-402-54q9 0 9 9t-9 9l-89 0q-9 0-9-9t9-9l89 0z" horiz-adv-x="1071.429" />
<glyph glyph-name="laptop" unicode="&#xe90e;" d="M232 136q-37 0-63 26t-26 63l0 393q0 37 26 63t63 26l607 0q37 0 63-26t26-63l0-393q0-37-26-63t-63-26l-607 0z m-18 482l0-393q0-7 5-13t13-5l607 0q7 0 13 5t5 13l0 393q0 7-5 13t-13 5l-607 0q-7 0-13-5t-5-13z m768-518l89 0 0-54q0-22-26-38t-63-16l-893 0q-37 0-63 16t-26 38l0 54 982 0z m-402-54q9 0 9 9t-9 9l-89 0q-9 0-9-9t9-9l89 0z" horiz-adv-x="1071.429" />
<glyph glyph-name="tablet" unicode="&#xe95c;" d="M357 64q0 15-11 25t-25 11-25-11-11-25 11-25 25-11 25 11 11 25z m214 89l0 536q0 7-5 13t-13 5l-464 0q-7 0-13-5t-5-13l0-536q0-7 5-13t13-5l464 0q7 0 13 5t5 13z m71 536l0-607q0-37-26-63t-63-26l-464 0q-37 0-63 26t-26 63l0 607q0 37 26 63t63 26l464 0q37 0 63-26t26-63z" horiz-adv-x="642.857" />
<glyph glyph-name="mobile" unicode="&#xe8a9;" d="M259 64q0 18-13 32t-32 13-32-13-13-32 13-32 32-13 32 13 13 32z m116 89l0 393q0 7-5 13t-13 5l-286 0q-7 0-13-5t-5-13l0-393q0-7 5-13t13-5l286 0q7 0 13 5t5 13z m-107 473q0 9-9 9l-89 0q-9 0-9-9t9-9l89 0q9 0 9 9z m161 9l0-571q0-29-21-50t-50-21l-286 0q-29 0-50 21t-21 50l0 571q0 29 21 50t50 21l286 0q29 0 50-21t21-50z" horiz-adv-x="428.571" />
<glyph glyph-name="circle-empty" unicode="&#xe8d2;" d="M429 654q-83 0-152-41t-110-110-41-152 41-152 110-110 152-41 152 41 110 110 41 152-41 152-110 110-152 41z m429-304q0-117-57-215t-156-156-215-57-215 57-156 156-57 215 57 215 156 156 215 57 215-57 156-156 57-215z" horiz-adv-x="857.143" />
@ -286,7 +286,7 @@
<glyph glyph-name="videocam" unicode="&#xe811;" d="M1000 654l0-607q0-23-22-33-7-3-14-3-15 0-25 11l-225 225 0-93q0-66-47-114t-114-47l-393 0q-66 0-114 47t-47 114l0 393q0 66 47 114t114 47l393 0q66 0 114-47t47-114l0-92 225 224q10 11 25 11 7 0 14-3 22-9 22-33z" horiz-adv-x="1000" />
<glyph glyph-name="headphones" unicode="&#xe86b;" d="M929 356q0-93-33-175l-11-27-103-18q-12-46-50-76t-87-30l0-18q0-8-5-13t-13-5l-36 0q-8 0-13 5t-5 13l0 321q0 8 5 13t13 5l36 0q8 0 13-5t5-13l0-18q40 0 73-20t52-53l38 7q16 53 16 108 0 83-49 156t-132 117-176 44-176-44-132-117-49-156q0-55 16-108l38-7q19 33 52 53t73 20l0 18q0 8 5 13t13 5l36 0q8 0 13-5t5-13l0-321q0-8-5-13t-13-5l-36 0q-8 0-13 5t-5 13l0 18q-49 0-87 30t-50 76l-103 18-11 27q-33 83-33 175 0 84 37 162t100 135 148 91 179 34 179-34 148-91 100-135 37-162z" horiz-adv-x="928.571" />
<glyph glyph-name="video" unicode="&#xe810;" d="M214-43l0 71q0 15-11 25t-25 11l-71 0q-15 0-25-11t-11-25l0-71q0-15 11-25t25-11l71 0q15 0 25 11t11 25z m0 214l0 71q0 15-11 25t-25 11l-71 0q-15 0-25-11t-11-25l0-71q0-15 11-25t25-11l71 0q15 0 25 11t11 25z m0 214l0 71q0 15-11 25t-25 11l-71 0q-15 0-25-11t-11-25l0-71q0-15 11-25t25-11l71 0q15 0 25 11t11 25z m571-429l0 286q0 15-11 25t-25 11l-429 0q-15 0-25-11t-11-25l0-286q0-15 11-25t25-11l429 0q15 0 25 11t11 25z m-571 643l0 71q0 15-11 25t-25 11l-71 0q-15 0-25-11t-11-25l0-71q0-15 11-25t25-11l71 0q15 0 25 11t11 25z m786-643l0 71q0 15-11 25t-25 11l-71 0q-15 0-25-11t-11-25l0-71q0-15 11-25t25-11l71 0q15 0 25 11t11 25z m-214 429l0 286q0 15-11 25t-25 11l-429 0q-15 0-25-11t-11-25l0-286q0-15 11-25t25-11l429 0q15 0 25 11t11 25z m214-214l0 71q0 15-11 25t-25 11l-71 0q-15 0-25-11t-11-25l0-71q0-15 11-25t25-11l71 0q15 0 25 11t11 25z m0 214l0 71q0 15-11 25t-25 11l-71 0q-15 0-25-11t-11-25l0-71q0-15 11-25t25-11l71 0q15 0 25 11t11 25z m0 214l0 71q0 15-11 25t-25 11l-71 0q-15 0-25-11t-11-25l0-71q0-15 11-25t25-11l71 0q15 0 25 11t11 25z m71 89l0-750q0-37-26-63t-63-26l-893 0q-37 0-63 26t-26 63l0 750q0 37 26 63t63 26l893 0q37 0 63-26t26-63z" horiz-adv-x="1071.429" />
<glyph glyph-name="target" unicode="&#xe8a7;" d="M668 279l-61 0q-15 0-25 11t-11 25l0 71q0 15 11 25t25 11l61 0q-18 60-63 105t-105 63l0-61q0-15-11-25t-25-11l-71 0q-15 0-25 11t-11 25l0 61q-60-18-105-63t-63-105l61 0q15 0 25-11t11-25l0-71q0-15-11-25t-25-11l-61 0q18-60 63-105t105-63l0 61q0 15 11 25t25 11l71 0q15 0 25-11t11-25l0-61q60 18 105 63t63 105z m189 107l0-71q0-15-11-25t-25-11l-80 0q-21-90-86-155t-155-86l0-80q0-15-11-25t-25-11l-71 0q-15 0-25 11t-11 25l0 80q-90 21-155 86t-86 155l-80 0q-15 0-25 11t-11 25l0 71q0 15 11 25t25 11l80 0q21 90 86 155t155 86l0 80q0 15 11 25t25 11l71 0q15 0 25-11t11-25l0-80q90-21 155-86t86-155l80 0q15 0 25-11t11-25z" horiz-adv-x="857.143" />
<glyph glyph-name="target" unicode="&#xe8a7;" d="M521 407l0 162q60-16 103-60t59-103l-162 0z m0-113l162 0q-16-59-59-103t-103-60l0 162z m-113 113l-162 0q16 59 59 103t103 60l0-162z m0-113l0-162q-60 16-103 60t-59 103l162 0z m113 390l0 113q152-19 261-128t130-263l-113 0q-18 107-95 183t-182 94z m-390-277l-113 0q19 152 128 262t263 129l0-113q-106-18-183-94t-95-183z m277-390l0-113q-154 19-263 129t-128 262l113 0q18-107 95-183t183-94z m390 277l113 0q-21-153-130-262t-261-128l0 113q105 18 182 94t95 183z" horiz-adv-x="928" />
<glyph glyph-name="award" unicode="&#xe959;" d="M256 357q-41 90-41 207l-143 0 0-54q0-44 53-90t131-63z m602 153l0 54-143 0q0-117-41-207 79 16 131 63t53 90z m71 71l0-71q0-40-23-80t-62-73-97-54-120-25q-23-30-53-53-21-19-29-40t-8-50q0-30 17-51t54-21q42 0 74-25t33-64l0-36q0-8-5-13t-13-5l-464 0q-8 0-13 5t-5 13l0 36q0 39 33 64t74 25q37 0 54 21t17 51q0 28-8 50t-29 40q-30 23-53 53-63 3-120 25t-97 54-62 73-23 80l0 71q0 22 16 38t38 16l161 0 0 54q0 37 26 63t63 26l321 0q37 0 63-26t26-63l0-54 161 0q22 0 38-16t16-38z" horiz-adv-x="928.571" />
<glyph glyph-name="thumbs-up" unicode="&#xe93f;" d="M143 100q0 15-11 25t-25 11-25-11-11-25 11-25 25-11 25 11 11 25z m643 321q0 28-22 50t-50 21l-196 0q0 32 27 89t27 90q0 55-18 81t-71 26q-15-15-21-47t-17-70-33-61q-12-13-43-51-2-3-13-17t-18-23-19-24-22-25-21-20-22-15-20-5l-18 0 0-357 18 0q7 0 18-2t18-4 21-6 20-6 20-7 16-6q118-41 191-41l68 0q107 0 107 93 0 15-3 31 17 9 27 29t10 41-10 39q30 28 30 66 0 14-6 31t-14 27q18 1 30 26t12 45z m71 1q0-50-27-91 5-18 5-39 0-43-21-80 2-12 2-24 0-56-33-99 1-78-47-122t-127-45l-72 0q-54 0-106 13t-121 37q-65 22-77 22l-161 0q-30 0-50 21t-21 50l0 357q0 30 21 50t50 21l153 0q20 13 76 86 32 42 60 71 13 14 20 48t17 71 35 60q22 21 50 21 47 0 84-18t57-57 20-104q0-52-27-107l98 0q58 0 100-42t42-100z" horiz-adv-x="857.143" />
<glyph glyph-name="thumbs-down" unicode="&#xe940;" d="M143 600q0 15-11 25t-25 11-25-11-11-25 11-25 25-11 25 11 11 25z m643-321q0 20-12 45t-30 26q8 9 14 27t6 31q0 39-30 66 10 18 10 39t-10 41-27 29q3 17 3 31 0 47-27 70t-76 23l-71 0q-73 0-191-41-3-1-16-6t-20-7-20-6-21-6-18-4-18-2l-18 0 0-357 18 0q9 0 20-5t22-15 21-20 22-25 19-24 18-23 13-17q31-38 43-51 23-24 33-61t17-70 21-47q54 0 71 26t18 81q0 33-27 90t-27 89l196 0q28 0 50 21t22 50z m71-1q0-57-42-100t-100-42l-98 0q27-55 27-107 0-66-20-104-20-39-57-57t-84-18q-28 0-50 21-19 18-30 46t-14 50-10 47-17 36q-27 28-60 71-56 73-76 86l-153 0q-30 0-50 21t-21 50l0 357q0 30 21 50t50 21l161 0q12 0 77 22 71 25 124 37t112 12l62 0q78 0 126-44t48-121l0-3q33-43 33-99 0-12-2-24 21-37 21-80 0-20-5-39 27-41 27-91z" horiz-adv-x="857.143" />

Before

Width:  |  Height:  |  Size: 144 KiB

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
var VERSION = "2.0.3";
var VERSION = "2.1.0";
var MAIN_URL = "http://benweet.github.io/stackedit/";
var GOOGLE_ANALYTICS_ACCOUNT_ID = "UA-39556145-1";

View File

@ -14,7 +14,11 @@ define([
"storage",
"config",
"uilayout",
"libs/Markdown.Editor"
"libs/Markdown.Editor",
'libs/ace_mode',
'ace/requirejs/text!ace/css/editor.css',
'ace/requirejs/text!ace/theme/textmate.css',
], function($, _, crel, ace, utils, settings, eventMgr, mousetrap, bodyIndexHTML, bodyViewerHTML, settingsTemplateTooltipHTML, settingsUserCustomExtensionTooltipHTML) {
var core = {};
@ -207,7 +211,7 @@ define([
aceEditor.renderer.setPrintMarginColumn(false);
aceEditor.renderer.setPadding(EDITOR_DEFAULT_PADDING);
aceEditor.session.setUseWrapMode(true);
aceEditor.session.setMode("libs/acemode");
aceEditor.session.setMode("libs/ace_mode");
// Make titles bold...
(function(self) {
function customWorker() {
@ -373,13 +377,8 @@ define([
if(editor !== undefined) {
// If the editor is already created
if(aceEditor !== undefined) {
aceEditor.selection.setSelectionRange(fileDesc.editorSelectRange);
aceEditor.focus();
}
else {
$editorElt.focus();
}
aceEditor && aceEditor.selection.setSelectionRange(fileDesc.editorSelectRange);
(aceEditor && aceEditor.focus()) || $editorElt.focus();
editor.refreshPreview();
return;
}
@ -434,6 +433,18 @@ define([
return text;
});
function checkDocumentChanges() {
var newDocumentContent = $editorElt.val();
if(aceEditor !== undefined) {
newDocumentContent = aceEditor.getValue();
}
if(documentContent !== undefined && documentContent != newDocumentContent) {
fileDesc.content = newDocumentContent;
eventMgr.onContentChanged(fileDesc);
}
documentContent = newDocumentContent;
}
if(!lightMode) {
editor = new Markdown.Editor(converter);
// Custom insert link dialog
@ -455,22 +466,36 @@ define([
});
}
else {
$editor.on("input propertychange", function() {
});
// That's the light Markdown editor replacing the one from pagedown
var $wmdPreviewElt = $('#wmd-preview');
var hooks = new Markdown.HookCollection();
hooks.addNoop("onPreviewRefresh");
function makePreviewHtml() {
var text = $editorElt.val();
text = converter.makeHtml(text);
$wmdPreviewElt.html(text);
hooks.onPreviewRefresh();
}
var debouncedMakePreview = _.debounce(makePreviewHtml, 1000);
var previewWrapper = function() {
if(documentContent === undefined) {
makePreviewHtml();
eventMgr.onFileOpen(fileDesc);
}
else {
debouncedMakePreview();
}
checkDocumentChanges();
};
$editorElt.on("input propertychange", previewWrapper);
editor = {
hooks: hooks,
getConverter: function () { return converter; },
run: previewWrapper,
refreshPreview: previewWrapper
};
}
function checkDocumentChanges() {
var newDocumentContent = aceEditor.getValue();
if(documentContent !== undefined && documentContent != newDocumentContent) {
fileDesc.content = newDocumentContent;
eventMgr.onContentChanged(fileDesc);
}
documentContent = newDocumentContent;
}
var previewWrapper;
if(settings.lazyRendering === true) {
previewWrapper = function(makePreview) {
@ -505,8 +530,8 @@ define([
eventMgr.onPagedownConfigure(editor);
editor.hooks.chain("onPreviewRefresh", eventMgr.onAsyncPreview);
editor.run(aceEditor, previewWrapper);
aceEditor.selection.setSelectionRange(fileDesc.editorSelectRange);
aceEditor.focus();
aceEditor && aceEditor.selection.setSelectionRange(fileDesc.editorSelectRange);
(aceEditor && aceEditor.focus()) || $editorElt.focus();
// Hide default buttons
$(".wmd-button-row li").addClass("btn btn-success").css("left", 0).find("span").hide();
@ -575,7 +600,7 @@ define([
isMenuPanelShown = false;
menuPanelBackdropElt.parentNode.removeChild(menuPanelBackdropElt);
$menuPanelElt.removeClass('move-to-front');
aceEditor.focus();
(aceEditor && aceEditor.focus()) || $editorElt.focus();
}
}).on('hidden.bs.collapse', function(e) {
if(e.target === $menuPanelElt[0]) {
@ -603,7 +628,7 @@ define([
isDocumentPanelShown = false;
documentPanelBackdropElt.parentNode.removeChild(documentPanelBackdropElt);
$documentPanelElt.removeClass('move-to-front');
aceEditor.focus();
(aceEditor && aceEditor.focus()) || $editorElt.focus();
}
}).on('hidden.bs.collapse', function(e) {
if(e.target === $documentPanelElt[0]) {
@ -657,7 +682,7 @@ define([
}).on('hidden.bs.modal', function() {
// Focus on the editor when modal is gone
isModalShown = false;
aceEditor.focus();
(aceEditor && aceEditor.focus()) || $editorElt.focus();
// Revert to current theme when settings modal is closed
applyTheme(localStorage.theme);
}).keyup(function(e) {
@ -669,7 +694,7 @@ define([
// Configure Mousetrap
mousetrap.stopCallback = function(e, element, combo) {
return uiLocked || isMenuPanelShown || isDocumentPanelShown || isModalShown || $(element).is("input, select, textarea:not(#wmd-input)");
return isMenuPanelShown || isDocumentPanelShown || isModalShown || $(element).is("input, select, textarea:not(.ace_text-input)");
};
// Click events on "insert link" and "insert image" dialog buttons

View File

@ -130,6 +130,7 @@ define([
// Handle key shortcut
var shortcutPrevious = documentSelector.config.shortcutPrevious.toLowerCase();
mousetrap.bind(shortcutPrevious, function() {
console.log('keydown')
if(selectedLi === undefined) {
$dropdownElt.dropdown('toggle');
selectedLi = liEltMap[selectFileDesc.fileIndex];
@ -146,6 +147,7 @@ define([
});
var shortcutNext = documentSelector.config.shortcutNext.toLowerCase();
mousetrap.bind(documentSelector.config.shortcutNext.toLowerCase(), function() {
console.log('keydown')
if(selectedLi === undefined) {
$dropdownElt.dropdown('toggle');
selectedLi = liEltMap[selectFileDesc.fileIndex];
@ -165,6 +167,7 @@ define([
shortcutSelect1,
shortcutSelect2
], function() {
console.log('keyup')
if(selectedLi !== undefined) {
selectedLi.find("a").click();
}

View File

@ -156,6 +156,7 @@ define([
});
eventMgr.addListener("onReady", function() {
$editorElt = $("#wmd-input")
fileMgr.selectFile();
var $fileTitleElt = $('.file-title-navbar');
@ -188,7 +189,7 @@ define([
eventMgr.onTitleChanged(fileDesc);
}
$fileTitleInputElt.val(fileDesc.title);
aceEditor.focus();
(aceEditor && aceEditor.focus()) || $editorElt.focus();
}
$fileTitleInputElt.blur(function() {
applyTitle();
@ -205,7 +206,10 @@ define([
window.location.href = ".";
});
$(".action-edit-document").click(function() {
var content = aceEditor.getValue();
var content = $editorElt.val();
if(aceEditor !== undefined) {
content = aceEditor.getValue();
}
var title = fileMgr.currentFile.title;
var fileDesc = fileMgr.createFile(title, content);
fileMgr.selectFile(fileDesc);

View File

@ -737,7 +737,7 @@
}
*/
var Range = require('ace/range').Range;
var Range = typeof require !== 'undefined' ? require('ace/range').Range : ace.require('ace/range').Range;
(function(range) {
stateObj.before = inputArea.session.getTextRange(new Range(0,0,range.start.row, range.start.column));
stateObj.selection = inputArea.session.getTextRange();
@ -758,7 +758,7 @@
// operation.
this.setInputAreaSelection = function () {
var Range = require('ace/range').Range;
var Range = typeof require !== 'undefined' ? require('ace/range').Range : ace.require('ace/range').Range;
inputArea.selection.setSelectionRange((function(posStart, posEnd) {
return new Range(posStart.row, posStart.column, posEnd.row, posEnd.column);
})(inputArea.session.doc.indexToPosition(stateObj.start), inputArea.session.doc.indexToPosition(stateObj.end)));
@ -870,7 +870,7 @@
endIndex++;
}
var Range = require('ace/range').Range;
var Range = typeof require !== 'undefined' ? require('ace/range').Range : ace.require('ace/range').Range;
var range = (function(posStart, posEnd) {
return new Range(posStart.row, posStart.column, posEnd.row, posEnd.column);
})(inputArea.session.doc.indexToPosition(startIndex), inputArea.session.doc.indexToPosition(stateObj.length - endIndex));

410
res/libs/ace_commands.js Normal file
View File

@ -0,0 +1,410 @@
/* ***** BEGIN LICENSE BLOCK *****
* Distributed under the BSD license:
*
* Copyright (c) 2010, Ajax.org B.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Ajax.org B.V. nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ***** END LICENSE BLOCK ***** */
define(function(require, exports, module) {
"use strict";
var lang = require("ace/lib/lang");
var config = require("ace/config");
function bindKey(win, mac) {
return {
win: win,
mac: mac
};
}
exports.commands = [{
name: "selectall",
bindKey: bindKey("Ctrl-A", "Command-A"),
exec: function(editor) { editor.selectAll(); },
readOnly: true
}, {
name: "find",
bindKey: bindKey("Ctrl-F", "Command-F"),
exec: function(editor) {
config.loadModule("ace/ext/searchbox", function(e) {e.Search(editor)});
},
readOnly: true
}, {
name: "overwrite",
bindKey: "Insert",
exec: function(editor) { editor.toggleOverwrite(); },
readOnly: true
}, {
name: "selecttostart",
bindKey: bindKey("Ctrl-Shift-Home", "Command-Shift-Up"),
exec: function(editor) { editor.getSelection().selectFileStart(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "gotostart",
bindKey: bindKey("Ctrl-Home", "Command-Home|Command-Up"),
exec: function(editor) { editor.navigateFileStart(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "selectup",
bindKey: bindKey("Shift-Up", "Shift-Up"),
exec: function(editor) { editor.getSelection().selectUp(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "golineup",
bindKey: bindKey("Up", "Up|Ctrl-P"),
exec: function(editor, args) { editor.navigateUp(args.times); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "selecttoend",
bindKey: bindKey("Ctrl-Shift-End", "Command-Shift-Down"),
exec: function(editor) { editor.getSelection().selectFileEnd(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "gotoend",
bindKey: bindKey("Ctrl-End", "Command-End|Command-Down"),
exec: function(editor) { editor.navigateFileEnd(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "selectdown",
bindKey: bindKey("Shift-Down", "Shift-Down"),
exec: function(editor) { editor.getSelection().selectDown(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "golinedown",
bindKey: bindKey("Down", "Down|Ctrl-N"),
exec: function(editor, args) { editor.navigateDown(args.times); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "selectwordleft",
bindKey: bindKey("Ctrl-Shift-Left", "Option-Shift-Left"),
exec: function(editor) { editor.getSelection().selectWordLeft(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "gotowordleft",
bindKey: bindKey("Ctrl-Left", "Option-Left"),
exec: function(editor) { editor.navigateWordLeft(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "selecttolinestart",
bindKey: bindKey("Alt-Shift-Left", "Command-Shift-Left"),
exec: function(editor) { editor.getSelection().selectLineStart(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "gotolinestart",
bindKey: bindKey("Alt-Left|Home", "Command-Left|Home|Ctrl-A"),
exec: function(editor) { editor.navigateLineStart(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "selectleft",
bindKey: bindKey("Shift-Left", "Shift-Left"),
exec: function(editor) { editor.getSelection().selectLeft(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "gotoleft",
bindKey: bindKey("Left", "Left|Ctrl-B"),
exec: function(editor, args) { editor.navigateLeft(args.times); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "selectwordright",
bindKey: bindKey("Ctrl-Shift-Right", "Option-Shift-Right"),
exec: function(editor) { editor.getSelection().selectWordRight(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "gotowordright",
bindKey: bindKey("Ctrl-Right", "Option-Right"),
exec: function(editor) { editor.navigateWordRight(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "selecttolineend",
bindKey: bindKey("Alt-Shift-Right", "Command-Shift-Right"),
exec: function(editor) { editor.getSelection().selectLineEnd(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "gotolineend",
bindKey: bindKey("Alt-Right|End", "Command-Right|End|Ctrl-E"),
exec: function(editor) { editor.navigateLineEnd(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "selectright",
bindKey: bindKey("Shift-Right", "Shift-Right"),
exec: function(editor) { editor.getSelection().selectRight(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "gotoright",
bindKey: bindKey("Right", "Right|Ctrl-F"),
exec: function(editor, args) { editor.navigateRight(args.times); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "selectpagedown",
bindKey: "Shift-PageDown",
exec: function(editor) { editor.selectPageDown(); },
readOnly: true
}, {
name: "pagedown",
bindKey: bindKey(null, "Option-PageDown"),
exec: function(editor) { editor.scrollPageDown(); },
readOnly: true
}, {
name: "gotopagedown",
bindKey: bindKey("PageDown", "PageDown|Ctrl-V"),
exec: function(editor) { editor.gotoPageDown(); },
readOnly: true
}, {
name: "selectpageup",
bindKey: "Shift-PageUp",
exec: function(editor) { editor.selectPageUp(); },
readOnly: true
}, {
name: "pageup",
bindKey: bindKey(null, "Option-PageUp"),
exec: function(editor) { editor.scrollPageUp(); },
readOnly: true
}, {
name: "gotopageup",
bindKey: "PageUp",
exec: function(editor) { editor.gotoPageUp(); },
readOnly: true
}, {
name: "scrollup",
bindKey: bindKey("Ctrl-Up", null),
exec: function(e) { e.renderer.scrollBy(0, -2 * e.renderer.layerConfig.lineHeight); },
readOnly: true
}, {
name: "scrolldown",
bindKey: bindKey("Ctrl-Down", null),
exec: function(e) { e.renderer.scrollBy(0, 2 * e.renderer.layerConfig.lineHeight); },
readOnly: true
}, {
name: "selectlinestart",
bindKey: "Shift-Home",
exec: function(editor) { editor.getSelection().selectLineStart(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "selectlineend",
bindKey: "Shift-End",
exec: function(editor) { editor.getSelection().selectLineEnd(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "togglerecording",
bindKey: bindKey("Ctrl-Alt-E", "Command-Option-E"),
exec: function(editor) { editor.commands.toggleRecording(editor); },
readOnly: true
}, {
name: "replaymacro",
bindKey: bindKey("Ctrl-Shift-E", "Command-Shift-E"),
exec: function(editor) { editor.commands.replay(editor); },
readOnly: true
}, {
name: "jumptomatching",
bindKey: bindKey("Ctrl-P", "Ctrl-Shift-P"),
exec: function(editor) { editor.jumpToMatching(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "selecttomatching",
bindKey: bindKey("Ctrl-Shift-P", null),
exec: function(editor) { editor.jumpToMatching(true); },
multiSelectAction: "forEach",
readOnly: true
},
// commands disabled in readOnly mode
{
name: "cut",
exec: function(editor) {
var range = editor.getSelectionRange();
editor._emit("cut", range);
if (!editor.selection.isEmpty()) {
editor.session.remove(range);
editor.clearSelection();
}
},
multiSelectAction: "forEach"
}, {
name: "removeline",
bindKey: bindKey("Ctrl-D", "Command-D"),
exec: function(editor) { editor.removeLines(); },
multiSelectAction: "forEachLine"
}, {
name: "duplicateSelection",
bindKey: bindKey("Ctrl-Shift-D", "Command-Shift-D"),
exec: function(editor) { editor.duplicateSelection(); },
multiSelectAction: "forEach"
}, {
name: "sortlines",
bindKey: bindKey("Ctrl-Alt-S", "Command-Alt-S"),
exec: function(editor) { editor.sortLines(); },
multiSelectAction: "forEachLine"
}, {
name: "togglecomment",
bindKey: bindKey("Ctrl-/", "Command-/"),
exec: function(editor) { editor.toggleCommentLines(); },
multiSelectAction: "forEachLine"
}, {
name: "toggleBlockComment",
bindKey: bindKey("Ctrl-Shift-/", "Command-Shift-/"),
exec: function(editor) { editor.toggleBlockComment(); },
multiSelectAction: "forEach"
}, {
name: "modifyNumberUp",
bindKey: bindKey("Ctrl-Shift-Up", "Alt-Shift-Up"),
exec: function(editor) { editor.modifyNumber(1); },
multiSelectAction: "forEach"
}, {
name: "modifyNumberDown",
bindKey: bindKey("Ctrl-Shift-Down", "Alt-Shift-Down"),
exec: function(editor) { editor.modifyNumber(-1); },
multiSelectAction: "forEach"
}, {
name: "replace",
bindKey: bindKey("Ctrl-H", "Command-Option-F"),
exec: function(editor) {
config.loadModule("ace/ext/searchbox", function(e) {e.Search(editor, true)});
}
}, {
name: "undo",
bindKey: bindKey("Ctrl-Z", "Command-Z"),
exec: function(editor) { editor.undo(); }
}, {
name: "redo",
bindKey: bindKey("Ctrl-Shift-Z|Ctrl-Y", "Command-Shift-Z|Command-Y"),
exec: function(editor) { editor.redo(); }
}, {
name: "copylinesup",
bindKey: bindKey("Alt-Shift-Up", "Command-Option-Up"),
exec: function(editor) { editor.copyLinesUp(); }
}, {
name: "movelinesup",
bindKey: bindKey("Alt-Up", "Option-Up"),
exec: function(editor) { editor.moveLinesUp(); }
}, {
name: "copylinesdown",
bindKey: bindKey("Alt-Shift-Down", "Command-Option-Down"),
exec: function(editor) { editor.copyLinesDown(); }
}, {
name: "movelinesdown",
bindKey: bindKey("Alt-Down", "Option-Down"),
exec: function(editor) { editor.moveLinesDown(); }
}, {
name: "del",
bindKey: bindKey("Delete", "Delete|Ctrl-D"),
exec: function(editor) { editor.remove("right"); },
multiSelectAction: "forEach"
}, {
name: "backspace",
bindKey: bindKey(
"Command-Backspace|Option-Backspace|Shift-Backspace|Backspace",
"Ctrl-Backspace|Command-Backspace|Shift-Backspace|Backspace|Ctrl-H"
),
exec: function(editor) { editor.remove("left"); },
multiSelectAction: "forEach"
}, {
name: "removetolinestart",
bindKey: bindKey("Alt-Backspace", "Command-Backspace"),
exec: function(editor) { editor.removeToLineStart(); },
multiSelectAction: "forEach"
}, {
name: "removetolineend",
bindKey: bindKey("Alt-Delete", "Ctrl-K"),
exec: function(editor) { editor.removeToLineEnd(); },
multiSelectAction: "forEach"
}, {
name: "removewordleft",
bindKey: bindKey("Ctrl-Backspace", "Alt-Backspace|Ctrl-Alt-Backspace"),
exec: function(editor) { editor.removeWordLeft(); },
multiSelectAction: "forEach"
}, {
name: "removewordright",
bindKey: bindKey("Ctrl-Delete", "Alt-Delete"),
exec: function(editor) { editor.removeWordRight(); },
multiSelectAction: "forEach"
}, {
name: "outdent",
bindKey: bindKey("Shift-Tab", "Shift-Tab"),
exec: function(editor) { editor.blockOutdent(); },
multiSelectAction: "forEach"
}, {
name: "indent",
bindKey: bindKey("Tab", "Tab"),
exec: function(editor) { editor.indent(); },
multiSelectAction: "forEach"
}, {
name: "insertstring",
exec: function(editor, str) { editor.insert(str); },
multiSelectAction: "forEach"
}, {
name: "inserttext",
exec: function(editor, args) {
editor.insert(lang.stringRepeat(args.text || "", args.times || 1));
},
multiSelectAction: "forEach"
}, {
name: "splitline",
bindKey: bindKey(null, "Ctrl-O"),
exec: function(editor) { editor.splitLine(); },
multiSelectAction: "forEach"
}, {
name: "transposeletters",
bindKey: bindKey("Ctrl-T", "Ctrl-T"),
exec: function(editor) { editor.transposeLetters(); },
multiSelectAction: function(editor) {editor.transposeSelections(1); }
}, {
name: "touppercase",
bindKey: bindKey("Ctrl-U", "Ctrl-U"),
exec: function(editor) { editor.toUpperCase(); },
multiSelectAction: "forEach"
}, {
name: "tolowercase",
bindKey: bindKey("Ctrl-Shift-U", "Ctrl-Shift-U"),
exec: function(editor) { editor.toLowerCase(); },
multiSelectAction: "forEach"
}];
});

View File

@ -34,7 +34,7 @@ define(function(require, exports, module) {
var oop = require("ace/lib/oop");
var TextMode = require("ace/mode/text").Mode;
var Tokenizer = require("ace/tokenizer").Tokenizer;
var MarkdownHighlightRules = require("./acemode_highlight_rules").MarkdownHighlightRules;
var MarkdownHighlightRules = require("./ace_mode_highlight_rules").MarkdownHighlightRules;
var MarkdownFoldMode = require("ace/mode/folding/markdown").FoldMode;
var Mode = function() {

11
res/libs/ace_text.js Normal file
View File

@ -0,0 +1,11 @@
(function() {
define(function (require, exports, module) {
"use strict";
exports.load = function (name, req, onLoad, config) {
onLoad('', 'utf8');
};
});
})();

View File

@ -45,6 +45,12 @@ requirejs.config({
'requirejs-text': 'bower-libs/requirejs-text/text',
'bootstrap-tour': 'bower-libs/bootstrap-tour/build/js/bootstrap-tour'
},
map: {
'ace': {
'ace/requirejs/text': 'libs/ace_text',
'ace/commands/default_commands': 'libs/ace_commands'
}
},
shim: {
underscore: {
exports: '_'
@ -104,7 +110,7 @@ requirejs.config({
],
'libs/Markdown.Editor': [
'libs/Markdown.Converter'
]
],
}
});

View File

@ -81,7 +81,8 @@ define([
gdriveProvider.exportFile = function(event, title, content, callback) {
var fileId = utils.getInputTextValue("#input-sync-export-gdrive-fileid");
if(fileId) {
// Check that file is not synchronized with another an existing document
// Check that file is not synchronized with another an existing
// document
var syncIndex = createSyncIndex(fileId);
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
if(fileDesc !== undefined) {
@ -272,6 +273,7 @@ define([
// Start realtime synchronization
var realtimeDocument = undefined;
var realtimeBinding = undefined;
var realtimeString = undefined;
var undoExecute = undefined;
var redoExecute = undefined;
@ -314,9 +316,11 @@ define([
utils.storeAttributes(syncAttributes);
}
var debouncedRefreshPreview = _.debounce(pagedownEditor.refreshPreview, 100);
// Listen to insert text events
realtimeString.addEventListener(gapi.drive.realtime.EventType.TEXT_INSERTED, function(e) {
if(isAceUpToDate === false || e.isLocal === false) {
if(aceEditor !== undefined && (isAceUpToDate === false || e.isLocal === false)) {
// Update ACE editor
var position = aceEditor.session.doc.indexToPosition(e.index);
aceEditor.session.insert(position, e.text);
@ -326,11 +330,12 @@ define([
if(e.isLocal === false) {
logger.log("Google Drive realtime document updated from server");
updateContentState();
aceEditor === undefined && debouncedRefreshPreview();
}
});
// Listen to delete text events
realtimeString.addEventListener(gapi.drive.realtime.EventType.TEXT_DELETED, function(e) {
if(isAceUpToDate === false || e.isLocal === false) {
if(aceEditor !== undefined && (isAceUpToDate === false || e.isLocal === false)) {
// Update ACE editor
var range = (function(posStart, posEnd) {
return new Range(posStart.row, posStart.column, posEnd.row, posEnd.column);
@ -342,6 +347,7 @@ define([
if(e.isLocal === false) {
logger.log("Google Drive realtime document updated from server");
updateContentState();
aceEditor === undefined && debouncedRefreshPreview();
}
});
realtimeDocument.addEventListener(gapi.drive.realtime.EventType.DOCUMENT_SAVE_STATE_CHANGED, function(e) {
@ -370,13 +376,21 @@ define([
realtimeString.setText(localContent);
}
}
if(aceEditor === undefined) {
// Binds model with textarea
realtimeBinding = gapi.drive.realtime.databinding.bindString(realtimeString, document.getElementById("wmd-input"));
}
// Update content state according to collaborators changes
if(remoteContentChanged === true) {
logger.log("Google Drive realtime document updated from server");
aceEditor.setValue(remoteContent);
aceEditor !== undefined && aceEditor.setValue(remoteContent, -1);
updateContentState();
aceEditor === undefined && debouncedRefreshPreview();
}
if(aceEditor !== undefined) {
// Save undo/redo buttons actions
undoExecute = pagedownEditor.uiManager.buttons.undo.execute;
redoExecute = pagedownEditor.uiManager.buttons.redo.execute;
@ -385,14 +399,16 @@ define([
// Set new actions for undo/redo buttons
pagedownEditor.uiManager.buttons.undo.execute = function() {
if(model.canUndo) {
// This flag is used to avoid replaying editor's own modifications (assuming it's synchronous)
// This flag is used to avoid replaying editor's own
// modifications (assuming it's synchronous)
isAceUpToDate = false;
model.undo();
}
};
pagedownEditor.uiManager.buttons.redo.execute = function() {
if(model.canRedo) {
// This flag is used to avoid replaying editor's own modifications (assuming it's synchronous)
// This flag is used to avoid replaying editor's own
// modifications (assuming it's synchronous)
isAceUpToDate = false;
model.redo();
}
@ -409,6 +425,7 @@ define([
model.addEventListener(gapi.drive.realtime.EventType.UNDO_REDO_STATE_CHANGED, function() {
pagedownEditor.uiManager.setUndoRedoButtonStates();
});
}
}, function(err) {
console.error(err);
@ -434,16 +451,22 @@ define([
if(realtimeString !== undefined) {
realtimeString = undefined;
}
if(realtimeBinding !== undefined) {
realtimeBinding.unbind();
realtimeBinding = undefined;
}
if(realtimeDocument !== undefined) {
realtimeDocument.close();
realtimeDocument = undefined;
}
if(aceEditor !== undefined) {
// Set back original undo/redo actions
pagedownEditor.uiManager.buttons.undo.execute = undoExecute;
pagedownEditor.uiManager.buttons.redo.execute = redoExecute;
pagedownEditor.uiManager.setUndoRedoButtonStates = setUndoRedoButtonStates;
pagedownEditor.uiManager.setUndoRedoButtonStates();
}
};
eventMgr.addListener("onReady", function() {

View File

@ -1,4 +1,7 @@
@import "../bower-libs/bootstrap/less/bootstrap.less";
@import "../bower-libs/ace/lib/ace/css/editor.css";
@import "../bower-libs/ace/lib/ace/ext/searchbox.css";
@import "../bower-libs/ace/lib/ace/theme/textmate.css";
@import "../bower-libs/google-code-prettify/src/prettify.css";
@import "../bower-libs/highlightjs/styles/default.css";
@import "../bower-libs/bootstrap-tour/src/less/bootstrap-tour.less";
@ -986,6 +989,11 @@ ul,ol {
}
}
.ace_search {
background-color: @primary-bg;
border: 0;
}
#wmd-input {
color: @primary-color-light;
.box-shadow(none);