New extension pattern

This commit is contained in:
benweet 2013-05-27 20:45:33 +01:00
parent 56fa0c5873
commit d636e80646
59 changed files with 1160 additions and 927 deletions

View File

@ -6,7 +6,7 @@ index.html
viewer.html
css/main-min.css
js/main-min.js
js/require.js
js/lib/require.js
img/ajax-loader.gif
img/glyphicons-halflings.png
img/glyphicons-halflings-white.png

47
css/main-min.css vendored
View File

@ -5513,6 +5513,12 @@ code {
h1 {
margin: 30px 0 30px;
}
h4, h5, h6 {
line-height: 40px;
}
.toc ul {
list-style-type: none;
}
p, pre, blockquote {
margin: 0 0 20px;
}
@ -5727,9 +5733,48 @@ div.dropdown-menu i {
height: 80px;
max-width: 206px;
}
.tooltip-inner {
#modal-settings .accordion-group {
border: 0;
border-bottom: 1px solid #eee;
-webkit-border-radius: inherit;
-moz-border-radius: inherit;
border-radius: inherit;
margin-bottom: 10px;
}
#modal-settings .accordion-heading .checkbox {
padding: 8px 15px;
margin-bottom: 0px;
}
#modal-settings .accordion-inner {
border: 0;
padding: 10px 40px;
}
#modal-settings .accordion-inner .form-horizontal .control-group {
color: #999;
}
#modal-settings .accordion-inner .form-horizontal .control-label {
text-align: left;
}
.accordion-toggle {
cursor: help;
}
.nav-tabs > .active > a, .nav-tabs > .active > a:hover, .nav-tabs > .active > a:focus {
color: #fff;
background-color: #777;
border-color: #777;
border-bottom-color: transparent;
}
.nav-tabs {
border-bottom-color: #eee;
}
.nav > li > a:hover,
.nav > li > a:focus {
background-color: #eee;
}
.nav-tabs > li > a:hover,
.nav-tabs > li > a:focus {
border-color: #eee;
}
table {
margin-bottom: 20px;
}

View File

@ -19,13 +19,12 @@
document.write('<link href="css/main' + suffix + '.css" rel="stylesheet">');
var theme = localStorage.theme;
if (theme) {
document
.write('<link href="themes/' + theme + '/' + theme + '.css" rel="stylesheet">');
document.write('<link href="themes/' + theme + '/' + theme + '.css" rel="stylesheet">');
}
var require = { baseUrl : "js", deps : [ "main" + suffix ] };
var viewerMode = false;
</script>
<script src="js/require.js"></script>
<script src="js/lib/require.js"></script>
</head>
<body>
<div id="navbar" class="navbar navbar-fixed-top ui-layout-north">

View File

@ -2,7 +2,12 @@
* Used to run asynchronous tasks sequentially (ajax mainly). An asynchronous
* task is composed of different callback types: onRun, onSuccess, onError
*/
define([ "core", "underscore" ], function(core) {
define([
"underscore",
"core",
"utils",
"extension-manager"
], function(_, core, utils, extensionMgr) {
var asyncRunner = {};
@ -81,7 +86,7 @@ define([ "core", "underscore" ], function(core) {
}
error = error || new Error("Unknown error");
if(error.message) {
core.showError(error);
extensionMgr.onError(error);
}
runSafe(task, task.errorCallbacks, error);
// Exit the current call stack
@ -102,7 +107,7 @@ define([ "core", "underscore" ], function(core) {
}
// Implement an exponential backoff
var delay = Math.pow(2, task.retryCounter++) * 1000;
currentTaskStartTime = core.currentTime + delay;
currentTaskStartTime = utils.currentTime + delay;
currentTaskRunning = false;
asyncRunner.runTask();
};
@ -117,7 +122,7 @@ define([ "core", "underscore" ], function(core) {
// If there is a task currently running
if (currentTaskRunning === true) {
// If the current task takes too long
if (currentTaskStartTime + currentTask.timeout < core.currentTime) {
if (currentTaskStartTime + currentTask.timeout < utils.currentTime) {
currentTask.error(new Error("A timeout occurred."));
}
return;
@ -131,12 +136,12 @@ define([ "core", "underscore" ], function(core) {
// Dequeue an enqueued task
currentTask = taskQueue.shift();
currentTaskStartTime = core.currentTime;
core.showWorkingIndicator(true);
currentTaskStartTime = utils.currentTime;
extensionMgr.onAsyncRunning(true);
}
// Run the task
if (currentTaskStartTime <= core.currentTime) {
if (currentTaskStartTime <= utils.currentTime) {
currentTaskRunning = true;
currentTask.chain();
}
@ -157,7 +162,7 @@ define([ "core", "underscore" ], function(core) {
currentTaskRunning = false;
}
if (taskQueue.length === 0) {
core.showWorkingIndicator(false);
extensionMgr.onAsyncRunning(false);
} else {
asyncRunner.runTask();
}

View File

@ -1,4 +1,8 @@
define(["utils", "google-helper"], function(utils, googleHelper) {
define([
"underscore",
"utils",
"google-helper"
], function(_, utils, googleHelper) {
var PROVIDER_BLOGGER = "blogger";
@ -39,8 +43,9 @@ define(["utils", "google-helper"], function(utils, googleHelper) {
publishAttributes.labelList = [];
var labels = utils.getInputTextValue("#input-publish-labels");
if(labels !== undefined) {
publishAttributes.labelList = _.chain(labels.split(","))
.map(function(label) {
publishAttributes.labelList = _.chain(
labels.split(",")
).map(function(label) {
return utils.trim(label);
}).compact().value();
}

View File

@ -1,28 +1,18 @@
define([
"jquery",
"underscore",
"utils",
"settings",
"extension-manager",
"bootstrap",
"layout",
"Markdown.Editor",
"storage",
"config",
"underscore",
"FileSaver",
"css_browser_selector"
], function($, utils, extensionManager) {
"lib/bootstrap",
"lib/layout",
"lib/Markdown.Editor"
], function($, _, utils, settings, extensionMgr) {
var core = {};
// For convenience
core.doNothing = function() {};
// Time shared by others modules
function updateCurrentTime() {
core.currentTime = new Date().getTime();
}
updateCurrentTime();
// Used for periodic tasks
var intervalId = undefined;
var periodicCallbacks = [];
@ -38,11 +28,11 @@ define([
function setUserActive() {
userReal = true;
userActive = true;
userLastActivity = core.currentTime;
userLastActivity = utils.currentTime;
};
function isUserActive() {
if(userActive === true
&& core.currentTime - userLastActivity > USER_IDLE_THRESHOLD) {
&& utils.currentTime - userLastActivity > USER_IDLE_THRESHOLD) {
userActive = false;
}
return userActive && windowUnique;
@ -50,7 +40,7 @@ define([
// Used to only have 1 window of the application in the same browser
var windowId = undefined;
core.checkWindowUnique = function() {
function checkWindowUnique() {
if(userReal === false || windowUnique === false) {
return;
}
@ -70,136 +60,65 @@ define([
keyboard: false
});
}
};
// Export data on disk
core.saveFile = function(content, filename) {
if(saveAs !== undefined) {
var blob = new Blob([content], {type: "text/plain;charset=utf-8"});
saveAs(blob, filename);
}
else {
var uriContent = "data:application/octet-stream;base64,"
+ utils.encodeBase64(content);
window.open(uriContent, 'file');
}
};
// Used by asyncRunner
core.showWorkingIndicator = function(show) {
if (show === false) {
$(".working-indicator").removeClass("show");
$("body").removeClass("working");
} else {
$(".working-indicator").addClass("show");
$("body").addClass("working");
}
};
// Log a message
core.showMessage = function(message) {
console.log(message);
extensionManager.onMessage(message);
};
// Log an error
core.showError = function(error) {
console.error(error);
if(_.isString(error)) {
extensionManager.onMessage(error);
}
else if(_.isObject(error)) {
extensionManager.onMessage(error.message);
}
};
// Offline management
core.isOffline = false;
var offlineTime = core.currentTime;
var offlineListeners = [];
core.addOfflineListener = function(callback) {
offlineListeners.push(callback);
};
var offlineTime = utils.currentTime;
core.setOffline = function() {
offlineTime = core.currentTime;
offlineTime = utils.currentTime;
if(core.isOffline === false) {
core.isOffline = true;
extensionManager.onOfflineChanged(true);
_.each(offlineListeners, function(listener) {
listener();
});
extensionMgr.onOfflineChanged(true);
}
};
core.setOnline = function() {
function setOnline() {
if(core.isOffline === true) {
core.isOffline = false;
extensionManager.onOfflineChanged(false);
_.each(offlineListeners, function(listener) {
listener();
});
extensionMgr.onOfflineChanged(false);
}
}
};
function checkOnline() {
// Try to reconnect if we are offline but we have some network
if (core.isOffline === true && navigator.onLine === true
&& offlineTime + CHECK_ONLINE_PERIOD < core.currentTime) {
offlineTime = core.currentTime;
&& offlineTime + CHECK_ONLINE_PERIOD < utils.currentTime) {
offlineTime = utils.currentTime;
// Try to download anything to test the connection
$.ajax({
url : "//www.google.com/jsapi",
timeout : AJAX_TIMEOUT, dataType : "script"
}).done(function() {
core.setOnline();
setOnline();
});
}
}
// Setting management
core.settings = {
layoutOrientation : "horizontal",
lazyRendering : true,
editorFontSize : 14,
defaultContent: "\n\n\n> Written with [StackEdit](http://benweet.github.io/stackedit/).",
commitMsg : "Published by http://benweet.github.io/stackedit",
template : ['<!DOCTYPE html>\n',
'<html>\n',
'<head>\n',
'<title><%= documentTitle %></title>\n',
'</head>\n',
'<body><%= documentHTML %></body>\n',
'</html>'].join(""),
sshProxy : SSH_PROXY_URL,
extensionSettings: {}
};
if (_.has(localStorage, "settings")) {
_.extend(core.settings, JSON.parse(localStorage.settings));
}
extensionManager.init(core.settings.extensionSettings);
core.loadSettings = function() {
// Load settings in settings dialog
function loadSettings() {
// Layout orientation
utils.setInputRadio("radio-layout-orientation", core.settings.layoutOrientation);
utils.setInputRadio("radio-layout-orientation", settings.layoutOrientation);
// Theme
utils.setInputValue("#input-settings-theme", localStorage.theme);
// Lazy rendering
utils.setInputChecked("#input-settings-lazy-rendering", core.settings.lazyRendering);
utils.setInputChecked("#input-settings-lazy-rendering", settings.lazyRendering);
// Editor font size
utils.setInputValue("#input-settings-editor-font-size", core.settings.editorFontSize);
utils.setInputValue("#input-settings-editor-font-size", settings.editorFontSize);
// Default content
utils.setInputValue("#textarea-settings-default-content", core.settings.defaultContent);
utils.setInputValue("#textarea-settings-default-content", settings.defaultContent);
// Commit message
utils.setInputValue("#input-settings-publish-commit-msg", core.settings.commitMsg);
utils.setInputValue("#input-settings-publish-commit-msg", settings.commitMsg);
// Template
utils.setInputValue("#textarea-settings-publish-template", core.settings.template);
utils.setInputValue("#textarea-settings-publish-template", settings.template);
// SSH proxy
utils.setInputValue("#input-settings-ssh-proxy", core.settings.sshProxy);
utils.setInputValue("#input-settings-ssh-proxy", settings.sshProxy);
// Load extension settings
extensionManager.onLoadSettings();
};
extensionMgr.onLoadSettings();
}
core.saveSettings = function(event) {
// Save settings from settings dialog
function saveSettings(event) {
var newSettings = {};
// Layout orientation
@ -221,14 +140,14 @@ define([
// Save extension settings
newSettings.extensionSettings = {};
extensionManager.onSaveSettings(newSettings.extensionSettings, event);
extensionMgr.onSaveSettings(newSettings.extensionSettings, event);
if(!event.isPropagationStopped()) {
$.extend(core.settings, newSettings);
localStorage.settings = JSON.stringify(newSettings);
$.extend(settings, newSettings);
localStorage.settings = JSON.stringify(settings);
localStorage.theme = theme;
}
};
}
// Create the layout
var layout = undefined;
@ -250,8 +169,8 @@ define([
center__minWidth : 200,
center__minHeight : 200
};
extensionManager.onLayoutConfigure(layoutGlobalConfig);
if (core.settings.layoutOrientation == "horizontal") {
extensionMgr.onLayoutConfigure(layoutGlobalConfig);
if (settings.layoutOrientation == "horizontal") {
$(".ui-layout-south").remove();
$(".ui-layout-east").addClass("well").prop("id", "wmd-preview");
layout = $('body').layout(
@ -261,7 +180,7 @@ define([
east__minSize : 200
})
);
} else if (core.settings.layoutOrientation == "vertical") {
} else if (settings.layoutOrientation == "vertical") {
$(".ui-layout-east").remove();
$(".ui-layout-south").addClass("well").prop("id", "wmd-preview");
layout = $('body').layout(
@ -282,7 +201,7 @@ define([
layout.allowOverflow('north');
});
extensionManager.onLayoutCreated(layout);
extensionMgr.onLayoutCreated(layout);
};
// Create the PageDown editor
@ -320,7 +239,7 @@ define([
makePreview();
};
};
if(core.settings.lazyRendering === true) {
if(settings.lazyRendering === true) {
var lastRefresh = 0;
previewWrapper = function(makePreview) {
//var debouncedMakePreview = _.debounce(makePreview, 500);
@ -340,8 +259,8 @@ define([
};
};
}
extensionManager.onEditorConfigure(editor);
editor.hooks.chain("onPreviewRefresh", extensionManager.onAsyncPreview);
extensionMgr.onEditorConfigure(editor);
editor.hooks.chain("onPreviewRefresh", extensionMgr.onAsyncPreview);
// Convert email addresses (not managed by pagedown)
converter.hooks.chain("postConversion", function(text) {
@ -374,49 +293,25 @@ define([
$("#wmd-redo-button").append($("<i>").addClass("icon-share-alt"));
};
// Create an centered popup window
core.popupWindow = function(url, title, w, h) {
var left = (screen.width / 2) - (w / 2);
var top = (screen.height / 2) - (h / 2);
return window
.open(
url,
title,
'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width='
+ w
+ ', height='
+ h
+ ', top='
+ top
+ ', left='
+ left);
};
// Keep a reference to the fileManager
core.setFileManager = function(fileManager) {
core.fileManager = fileManager;
runReadyCallbacks();
};
// onReady event callbacks
var readyCallbacks = [];
core.onReady = function(callback) {
readyCallbacks.push(callback);
runReadyCallbacks();
};
var documentLoaded = false;
var ready = false;
core.setReady = function() {
ready = true;
runReadyCallbacks();
};
function runReadyCallbacks() {
if(documentLoaded === true && core.fileManager !== undefined) {
if(ready === true) {
_.each(readyCallbacks, function(callback) {
callback();
});
readyCallbacks = [];
}
}
$(function() {
documentLoaded = true;
runReadyCallbacks();
});
core.onReady(extensionManager.onReady);
core.onReady(function() {
@ -428,7 +323,7 @@ define([
// listen to online/offline events
$(window).on('offline', core.setOffline);
$(window).on('online', core.setOnline);
$(window).on('online', setOnline);
if (navigator.onLine === false) {
core.setOffline();
}
@ -460,10 +355,10 @@ define([
// Settings loading/saving
$(".action-load-settings").click(function() {
core.loadSettings();
loadSettings();
});
$(".action-apply-settings").click(function(e) {
core.saveSettings(e);
saveSettings(e);
if(!e.isPropagationStopped()) {
window.location.reload();
}
@ -487,8 +382,8 @@ define([
// Editor's textarea
$("#wmd-input, #md-section-helper").css({
// Apply editor font size
"font-size": core.settings.editorFontSize + "px",
"line-height": Math.round(core.settings.editorFontSize * (20/14)) + "px"
"font-size": settings.editorFontSize + "px",
"line-height": Math.round(settings.editorFontSize * (20/14)) + "px"
});
// Manage tab key
@ -564,8 +459,8 @@ define([
// Do periodic tasks
intervalId = window.setInterval(function() {
updateCurrentTime();
core.checkWindowUnique();
utils.updateCurrentTime();
checkWindowUnique();
if(isUserActive() === true || viewerMode === true) {
_.each(periodicCallbacks, function(callback) {
callback();

View File

@ -1,4 +1,8 @@
define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
define([
"jquery",
"core",
"async-runner"
], function($, core, asyncRunner) {
var PROVIDER_DOWNLOAD = "download";

View File

@ -1,4 +1,10 @@
define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
define([
"jquery",
"underscore",
"core",
"extension-manager",
"async-runner"
], function($, _, core, extensionMgr, asyncRunner) {
var client = undefined;
var authenticated = false;
@ -50,7 +56,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
var immediate = true;
function localAuthenticate() {
if (immediate === false) {
core.showMessage("Please make sure the Dropbox authorization popup is not blocked by your browser.");
extensionMgr.onMessage("Please make sure the Dropbox authorization popup is not blocked by your browser.");
// If not immediate we add time for user to enter his credentials
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
}
@ -77,7 +83,6 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
}
dropboxHelper.upload = function(path, content, callback) {
callback = callback || core.doNothing;
var result = undefined;
var task = asyncRunner.createTask();
connect(task);
@ -106,7 +111,6 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
};
dropboxHelper.checkChanges = function(lastChangeId, callback) {
callback = callback || core.doNothing;
var changes = [];
var newChangeId = lastChangeId || 0;
var task = asyncRunner.createTask();
@ -143,7 +147,6 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
};
dropboxHelper.downloadMetadata = function(paths, callback) {
callback = callback || core.doNothing;
var result = [];
var task = asyncRunner.createTask();
connect(task);
@ -177,7 +180,6 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
};
dropboxHelper.downloadContent = function(objects, callback) {
callback = callback || core.doNothing;
var result = [];
var task = asyncRunner.createTask();
connect(task);
@ -289,7 +291,6 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
}
dropboxHelper.picker = function(callback) {
callback = callback || core.doNothing;
var paths = [];
var task = asyncRunner.createTask();
// Add some time for user to choose his files
@ -312,7 +313,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
task.chain();
};
Dropbox.choose(options);
core.showMessage("Please make sure the Dropbox chooser popup is not blocked by your browser.");
extensionMgr.onMessage("Please make sure the Dropbox chooser popup is not blocked by your browser.");
});
task.onSuccess(function() {
callback(undefined, paths);

View File

@ -1,4 +1,10 @@
define(["core", "utils", "extension-manager", "dropbox-helper"], function(core, utils, extensionManager, dropboxHelper) {
define([
"underscore",
"utils",
"extension-manager",
"file-manager",
"dropbox-helper"
], function(_, utils, extensionMgr, fileMgr, dropboxHelper) {
var PROVIDER_DROPBOX = "dropbox";
@ -13,7 +19,7 @@ define(["core", "utils", "extension-manager", "dropbox-helper"], function(core,
return undefined;
}
if(!path.match(/^[^\\<>:"\|?\*]+$/)) {
core.showError('"' + path + '" contains invalid characters.');
extensionMgr.onError('"' + path + '" contains invalid characters.');
return undefined;
}
if(path.indexOf("/") !== 0) {
@ -51,11 +57,11 @@ define(["core", "utils", "extension-manager", "dropbox-helper"], function(core,
localStorage[syncAttributes.syncIndex] = utils.serializeAttributes(syncAttributes);
var syncLocations = {};
syncLocations[syncAttributes.syncIndex] = syncAttributes;
var fileDesc = core.fileManager.createFile(file.name, file.content, syncLocations);
core.fileManager.selectFile(fileDesc);
var fileDesc = fileMgr.createFile(file.name, file.content, syncLocations);
fileMgr.selectFile(fileDesc);
fileDescList.push(fileDesc);
});
extensionManager.onSyncImportSuccess(fileDescList, dropboxProvider);
extensionMgr.onSyncImportSuccess(fileDescList, dropboxProvider);
});
});
}
@ -68,9 +74,9 @@ define(["core", "utils", "extension-manager", "dropbox-helper"], function(core,
var importPaths = [];
_.each(paths, function(path) {
var syncIndex = createSyncIndex(path);
var fileDesc = core.fileManager.getFileFromSyncIndex(syncIndex);
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
if(fileDesc !== undefined) {
core.showError('"' + fileDesc.title + '" was already imported');
extensionMgr.onError('"' + fileDesc.title + '" was already imported');
return;
}
importPaths.push(path);
@ -87,10 +93,10 @@ define(["core", "utils", "extension-manager", "dropbox-helper"], function(core,
}
// Check that file is not synchronized with an other one
var syncIndex = createSyncIndex(path);
var fileDesc = core.fileManager.getFileFromSyncIndex(syncIndex);
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
if(fileDesc !== undefined) {
var existingTitle = fileDesc.title;
core.showError('File path is already synchronized with "' + existingTitle + '"');
extensionMgr.onError('File path is already synchronized with "' + existingTitle + '"');
callback(true);
return;
}
@ -143,7 +149,7 @@ define(["core", "utils", "extension-manager", "dropbox-helper"], function(core,
var interestingChanges = [];
_.each(changes, function(change) {
var syncIndex = createSyncIndex(change.path);
var syncAttributes = core.fileManager.getSyncAttributes(syncIndex);
var syncAttributes = fileMgr.getSyncAttributes(syncIndex);
if(syncAttributes === undefined) {
return;
}
@ -164,11 +170,10 @@ define(["core", "utils", "extension-manager", "dropbox-helper"], function(core,
callback(error);
return;
}
var updateFileTitles = false;
_.each(changes, function(change) {
var syncAttributes = change.syncAttributes;
var syncIndex = syncAttributes.syncIndex;
var fileDesc = core.fileManager.getFileFromSyncIndex(syncIndex);
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
// No file corresponding (file may have been deleted locally)
if(fileDesc === undefined) {
return;
@ -176,8 +181,8 @@ define(["core", "utils", "extension-manager", "dropbox-helper"], function(core,
var localTitle = fileDesc.title;
// File deleted
if (change.wasRemoved === true) {
core.showError('"' + localTitle + '" has been removed from Dropbox.');
core.fileManager.removeSync(syncAttributes);
extensionMgr.onError('"' + localTitle + '" has been removed from Dropbox.');
fileMgr.removeSync(syncAttributes);
return;
}
var localContent = localStorage[fileDesc.fileIndex + ".content"];
@ -188,17 +193,16 @@ define(["core", "utils", "extension-manager", "dropbox-helper"], function(core,
var fileContentChanged = localContent != file.content;
// Conflict detection
if (fileContentChanged === true && localContentChanged === true && remoteContentChanged === true) {
core.fileManager.createFile(localTitle + " (backup)", localContent);
updateFileTitles = true;
core.showMessage('Conflict detected on "' + localTitle + '". A backup has been created locally.');
var backupFileDesc = fileMgr.createFile(localTitle + " (backup)", localContent);
extensionMgr.onTitleChanged(backupFileDesc);
extensionMgr.onMessage('Conflict detected on "' + localTitle + '". A backup has been created locally.');
}
// If file content changed
if(fileContentChanged && remoteContentChanged === true) {
localStorage[fileDesc.fileIndex + ".content"] = file.content;
core.showMessage('"' + localTitle + '" has been updated from Dropbox.');
if(core.fileManager.isCurrentFile(fileDesc)) {
updateFileTitles = false; // Done by next function
core.fileManager.selectFile(); // Refresh editor
extensionMgr.onMessage('"' + localTitle + '" has been updated from Dropbox.');
if(fileMgr.isCurrentFile(fileDesc)) {
fileMgr.selectFile(); // Refresh editor
}
}
// Update syncAttributes
@ -206,9 +210,6 @@ define(["core", "utils", "extension-manager", "dropbox-helper"], function(core,
syncAttributes.contentCRC = remoteContentCRC;
localStorage[syncIndex] = utils.serializeAttributes(syncAttributes);
});
if(updateFileTitles) {
extensionManager.onTitleChanged();
}
localStorage[PROVIDER_DROPBOX + ".lastChangeId"] = newChangeId;
callback();
});

View File

@ -1,27 +1,38 @@
define( [
"jquery",
"utils",
"underscore",
"bootstrap",
"utils",
"settings",
"extensions/button-publish",
"extensions/button-share",
"extensions/button-sync",
"extensions/document-selector",
"extensions/document-title",
"extensions/manage-publication",
"extensions/manage-synchronization",
"extensions/working-indicator",
"extensions/notifications",
"extensions/markdown-extra",
"extensions/toc",
"extensions/math-jax",
"extensions/scroll-link"
], function($, utils) {
"extensions/scroll-link",
"lib/bootstrap"
], function($, _, utils, settings) {
var extensionManager = {};
var extensionMgr = {};
// Create a list of extensions
var extensionList = _.chain(arguments)
.map(function(argument) {
var extensionList = _.chain(
arguments
).map(function(argument) {
return _.isObject(argument) && argument.extensionId && argument;
}).compact().value();
// Return every named callbacks implemented in extensions
function getExtensionCallbackList(hookName) {
return _.chain(extensionList)
.map(function(extension) {
return _.chain(
extensionList
).map(function(extension) {
return extension.config.enabled && extension[hookName];
}).compact().value();
}
@ -38,9 +49,9 @@ define( [
};
}
// Add a Hook to the extensionManager
// Add a Hook to the extensionMgr
function addHook(hookName) {
extensionManager[hookName] = createHook(hookName);
extensionMgr[hookName] = createHook(hookName);
}
var accordionTmpl = [
@ -67,17 +78,15 @@ define( [
})));
}
extensionManager.init = function(extensionSettings) {
// Set extension config
extensionSettings = extensionSettings || {};
extensionSettings = settings.extensionSettings || {};
_.each(extensionList, function(extension) {
extension.config = _.extend({}, extension.defaultConfig, extensionSettings[extension.extensionId]);
extension.config.enabled = !extension.optional || extension.config.enabled === undefined || extension.config.enabled === true;
});
// Load/Save extension config from/to settings
extensionManager["onLoadSettings"] = function() {
extensionMgr["onLoadSettings"] = function() {
console.debug("onLoadSettings");
_.each(extensionList, function(extension) {
utils.setInputChecked("#input-enable-extension-" + extension.extensionId, extension.config.enabled);
@ -85,7 +94,7 @@ define( [
onLoadSettingsCallback && onLoadSettingsCallback();
});
};
extensionManager["onSaveSettings"] = function(newExtensionSettings, event) {
extensionMgr["onSaveSettings"] = function(newExtensionSettings, event) {
console.debug("onSaveSettings");
_.each(extensionList, function(extension) {
var newExtensionConfig = extension.defaultConfig || {};
@ -96,25 +105,34 @@ define( [
});
};
addHook("onReady");
addHook("onMessage");
addHook("onError");
addHook("onOfflineChanged");
addHook("onAsyncRunning");
// To store reference to modules that are accessible from extensions
addHook("onFileManagerCreated");
addHook("onFileMgrCreated");
addHook("onSynchronizerCreated");
addHook("onPublisherCreated");
// Operations on files
addHook("onFileSystemLoaded");
addHook("onFileSystemCreated");
addHook("onFileCreated");
addHook("onFileDeleted");
addHook("onFileChanged");
addHook("onFileSelected");
addHook("onTitleChanged");
// Sync events
addHook("onSyncRunning");
addHook("onSyncSuccess");
addHook("onSyncImportSuccess");
addHook("onSyncExportSuccess");
addHook("onSyncRemoved");
// Publish events
addHook("onPublishRunning");
addHook("onPublishSuccess");
addHook("onNewPublishSuccess");
addHook("onPublishRemoved");
@ -128,7 +146,7 @@ define( [
var onPreviewFinished = createHook("onPreviewFinished");
var onAsyncPreviewCallbackList = getExtensionCallbackList("onAsyncPreview");
extensionManager["onAsyncPreview"] = function() {
extensionMgr["onAsyncPreview"] = function() {
console.debug("onAsyncPreview");
// Call onPreviewFinished callbacks when all async preview are finished
var counter = 0;
@ -146,16 +164,10 @@ define( [
tryFinished();
};
// Call onReady callbacks
var onReady = createHook("onReady");
extensionManager["onReady"] = function() {
$(function() {
// Create accordion in settings dialog
_.each(extensionList, createSettings);
});
onReady();
};
};
return extensionManager;
return extensionMgr;
});

View File

@ -0,0 +1,58 @@
define([
"jquery",
"underscore"
], function($, _) {
var buttonPublish = {
extensionId: "buttonPublish",
extensionName: 'Button "Publish"',
optional: true,
settingsBloc: '<p>Adds a "Publish document" button in the navigation bar.</p>'
};
var currentFileDesc = undefined;
var publishRunning = false;
var hasPublications = false;
var isOffline = false;
// Enable/disable the button
function updateButtonState() {
if(publishRunning === true || hasPublications === false || isOffline === true) {
$(".action-force-publish").addClass("disabled");
}
else {
$(".action-force-publish").removeClass("disabled");
}
};
buttonPublish.onPublishRunning = function(isRunning) {
publishRunning = isRunning;
updateButtonState();
};
buttonPublish.onOfflineChanged = function(isOfflineParameter) {
isOffline = isOfflineParameter;
updateButtonState();
};
// Check that current file has publications
var checkPublication = function() {
if(_.size(currentFileDesc.publishLocations) === 0) {
hasPublications = false;
}
else {
hasPublications = true;
}
updateButtonState();
};
buttonPublish.onFileSelected = function(fileDesc) {
currentFileDesc = fileDesc;
checkPublication();
};
buttonPublish.onPublishRemoved = checkPublication;
buttonPublish.onNewPublishSuccess = checkPublication;
return buttonPublish;
});

View File

@ -1,12 +1,13 @@
define( [ "jquery", "underscore" ], function($) {
define([
"jquery",
"underscore"
], function($, _) {
var sharingButton = {
extensionId: "sharingButton",
extensionName: "Sharing button",
var buttonShare = {
extensionId: "buttonShare",
extensionName: 'Button "Share"',
optional: true,
settingsBloc: [
'<p>Adds a "Share document" button in the navigation bar.</p>'
].join("")
settingsBloc: '<p>Adds a "Share document" button in the navigation bar.</p>'
};
var fileDesc = undefined;
@ -14,8 +15,7 @@ define( [ "jquery", "underscore" ], function($) {
'<div class="input-prepend">',
'<a href="<%= link %>" class="add-on" title="Sharing location"><i class="icon-link"></i></a>',
'<input class="span2" type="text" value="<%= link %>" readonly />',
'</div>'
].join("");
'</div>'].join("");
var refreshDocumentSharing = function(fileDescParameter) {
if(fileDescParameter !== undefined && fileDescParameter !== fileDesc) {
return;
@ -39,14 +39,14 @@ define( [ "jquery", "underscore" ], function($) {
});
};
sharingButton.onFileSelected = function(fileDescParameter) {
buttonShare.onFileSelected = function(fileDescParameter) {
fileDesc = fileDescParameter;
refreshDocumentSharing(fileDescParameter);
};
sharingButton.onNewPublishSuccess = refreshDocumentSharing;
sharingButton.onPublishRemoved = refreshDocumentSharing;
buttonShare.onNewPublishSuccess = refreshDocumentSharing;
buttonShare.onPublishRemoved = refreshDocumentSharing;
return sharingButton;
return buttonShare;
});

View File

@ -0,0 +1,55 @@
define([
"jquery",
"underscore"
], function($, _) {
var buttonSync = {
extensionId: "buttonSync",
extensionName: 'Button "Synchronize"',
optional: true,
settingsBloc: '<p>Adds a "Synchronize documents" button in the navigation bar.</p>'
};
var syncRunning = false;
var uploadPending = false;
var isOffline = false;
// Enable/disable the button
function updateButtonState() {
if(syncRunning === true || uploadPending === false || isOffline) {
$(".action-force-sync").addClass("disabled");
}
else {
$(".action-force-sync").removeClass("disabled");
}
};
buttonSync.onSyncRunning = function(isRunning) {
syncRunning = isRunning;
uploadPending = true;
updateButtonState();
};
buttonSync.onSyncSuccess = function() {
uploadPending = false;
updateButtonState();
};
buttonSync.onOfflineChanged = function(isOfflineParameter) {
isOffline = isOfflineParameter;
updateButtonState();
};
// Check that a file has synchronized locations
var checkSynchronization = function(fileDesc) {
if(_.size(fileDesc.syncLocations) !== 0) {
uploadPending = true;
updateButtonState();
}
};
buttonSync.onFileChanged = checkSynchronization;
buttonSync.onTitleChanged = checkSynchronization;
return buttonSync;
});

View File

@ -1,23 +1,26 @@
define( [ "jquery", "underscore" ], function($) {
define([
"jquery",
"underscore"
], function($, _) {
var documentSelector = {
extensionId: "documentSelector",
extensionName: "Document selector",
settingsBloc: [
'<p>Builds the "Open document" dropdown menu.</p>'
].join("")
settingsBloc: '<p>Builds the "Open document" dropdown menu.</p>'
};
var fileSystemDescriptor = undefined;
documentSelector.onFileSystemLoaded = function(fileSystemDescriptorParameter) {
fileSystemDescriptor = fileSystemDescriptorParameter;
var fileSystem = undefined;
documentSelector.onFileSystemCreated = function(fileSystemParameter) {
fileSystem = fileSystemParameter;
};
var fileDesc = undefined;
var updateSelector = function() {
var sortedDescriptor = _.sortBy(fileSystemDescriptor, function(fileDesc) {
return fileDesc.title.toLowerCase();
});
var fileMgr = undefined;
documentSelector.onFileMgrCreated = function(fileMgrParameter) {
fileMgr = fileMgrParameter;
};
var liMap = undefined;
var buildSelector = function() {
function composeTitle(fileDesc) {
var result = [];
@ -25,40 +28,48 @@ define( [ "jquery", "underscore" ], function($) {
var publishAttributesList = _.values(fileDesc.publishLocations);
var attributesList = syncAttributesList.concat(publishAttributesList);
_.chain(attributesList).sortBy(function(attributes) {
return attributes.provider;
return attributes.provider.providerId;
}).each(function(attributes) {
result.push('<i class="icon-' + attributes.provider + '"></i>');
result.push('<i class="icon-' + attributes.provider.providerId + '"></i>');
});
result.push(" ");
result.push(fileDesc.title);
return result.join("");
}
liMap = {};
$("#file-selector li:not(.stick)").empty();
_.each(sortedDescriptor, function(fileDescToPrint) {
var a = $("<a>").html(composeTitle(fileDescToPrint.fileIndex));
var li = $("<li>").append(a);
if (fileDescToPrint === fileDesc) {
li.addClass("disabled");
} else {
a.prop("href", "#").click(function() {
fileManager.selectFile(fileDescToPrint);
});
_.chain(
fileSystem
).sortBy(function(fileDesc) {
return fileDesc.title.toLowerCase();
}).each(function(fileDesc) {
var a = $('<a href="#">').html(composeTitle(fileDesc)).click(function() {
if(liMap[fileDesc.fileIndex].is(".disabled")) {
fileMgr.selectFile(fileDesc);
}
});
var li = $("<li>").append(a);
liMap[fileDesc.fileIndex] = li;
$("#file-selector").append(li);
});
};
documentSelector.onFileSelected = function(fileDescParameter) {
fileDesc = fileDescParameter;
updateSelector();
documentSelector.onFileSelected = function(fileDesc) {
if(liMap === undefined) {
buildSelector();
}
$("#file-selector li:not(.stick)").removeClass("disabled");
liMap[fileDesc.fileIndex].addClass("disabled");
};
documentSelector.onTitleChanged = updateSelector;
documentSelector.onSyncExportSuccess = updateSelector;
documentSelector.onSyncRemoved = updateSelector;
documentSelector.onNewPublishSuccess = updateSelector;
documentSelector.onPublishRemoved = updateSelector;
documentSelector.onFileCreated = buildSelector;
documentSelector.onFileDeleted = buildSelector;
documentSelector.onTitleChanged = buildSelector;
documentSelector.onSyncExportSuccess = buildSelector;
documentSelector.onSyncRemoved = buildSelector;
documentSelector.onNewPublishSuccess = buildSelector;
documentSelector.onPublishRemoved = buildSelector;
return documentSelector;

View File

@ -1,11 +1,12 @@
define( [ "jquery", "underscore" ], function($) {
define([
"jquery",
"underscore"
], function($, _) {
var documentTitle = {
extensionId: "documentTitle",
extensionName: "Document title",
settingsBloc: [
'<p>Responsible for showing the document title in the navigation bar.</p>'
].join("")
settingsBloc: '<p>Responsible for showing the document title in the navigation bar.</p>'
};
var layout = undefined;
@ -15,7 +16,7 @@ define( [ "jquery", "underscore" ], function($) {
var fileDesc = undefined;
var updateTitle = function(fileDescParameter) {
if(fileDescParameter !== undefined && fileDescParameter !== fileDesc) {
if(fileDescParameter !== fileDesc) {
return;
}
@ -25,9 +26,9 @@ define( [ "jquery", "underscore" ], function($) {
var publishAttributesList = _.values(fileDesc.publishLocations);
var attributesList = syncAttributesList.concat(publishAttributesList);
_.chain(attributesList).sortBy(function(attributes) {
return attributes.provider;
return attributes.provider.providerId;
}).each(function(attributes) {
result.push('<i class="icon-' + attributes.provider + '"></i>');
result.push('<i class="icon-' + attributes.provider.providerId + '"></i>');
});
result.push(" ");
result.push(fileDesc.title);

View File

@ -1,16 +1,17 @@
define( [ "jquery", "underscore" ], function($) {
define([
"jquery",
"underscore"
], function($, _) {
var managePublication = {
extensionId: "managePublication",
extensionName: "Manage Publication",
settingsBloc: [
'<p>Populates the "Manage publication" dialog box.</p>'
].join("")
settingsBloc: '<p>Populates the "Manage publication" dialog box.</p>'
};
var fileManager = undefined;
manageSynchronization.onFileManagerCreated = function(fileManagerParameter) {
fileManager = fileManagerParameter;
var fileMgr = undefined;
managePublication.onFileMgrCreated = function(fileMgrParameter) {
fileMgr = fileMgrParameter;
};
var fileDesc = undefined;
@ -46,7 +47,7 @@ define( [ "jquery", "underscore" ], function($) {
publishDesc: publishDesc
}));
lineElement.append($(removeButtonTemplate).click(function() {
fileManager.removePublish(publishAttributes);
fileMgr.removePublish(publishAttributes);
}));
publishList.append(lineElement);
});

View File

@ -1,16 +1,17 @@
define( [ "jquery", "underscore" ], function($) {
define([
"jquery",
"underscore"
], function($, _) {
var manageSynchronization = {
extensionId: "manageSynchronization",
extensionName: "Manage Synchronization",
settingsBloc: [
'<p>Populates the "Manage synchronization" dialog box.</p>'
].join("")
settingsBloc: '<p>Populates the "Manage synchronization" dialog box.</p>'
};
var fileManager = undefined;
manageSynchronization.onFileManagerCreated = function(fileManagerParameter) {
fileManager = fileManagerParameter;
var fileMgr = undefined;
manageSynchronization.onFileMgrCreated = function(fileMgrParameter) {
fileMgr = fileMgrParameter;
};
var fileDesc = undefined;
@ -42,7 +43,7 @@ define( [ "jquery", "underscore" ], function($) {
syncDesc: syncDesc
}));
lineElement.append($(removeButtonTemplate).click(function() {
fileManager.removeSync(syncAttributes);
fileMgr.removeSync(syncAttributes);
}));
syncList.append(lineElement);
});

View File

@ -1,4 +1,7 @@
define( [ "utils", "Markdown.Extra" ], function(utils) {
define([
"utils",
"lib/Markdown.Extra"
], function(utils) {
var markdownExtra = {
extensionId: "markdownExtra",

View File

@ -1,4 +1,6 @@
define( [ "MathJax" ], function($) {
define([
"lib/MathJax"
], function() {
var mathJax = {
extensionId: "mathJax",

View File

@ -1,4 +1,8 @@
define( [ "jquery", "jgrowl", "underscore" ], function($) {
define([
"jquery",
"underscore",
"jgrowl"
], function($, _, jGrowl) {
var notifications = {
extensionId: "notifications",
@ -6,15 +10,15 @@ define( [ "jquery", "jgrowl", "underscore" ], function($) {
defaultConfig: {
showingTime: 5000
},
settingsBloc: "<p>Shows notification messages in the bottom-right corner of the screen.</p>"
settingsBloc: '<p>Shows notification messages in the bottom-right corner of the screen.</p>'
};
notifications.onReady = function() {
// jGrowl configuration
$.jGrowl.defaults.life = notifications.config.showingTime;
$.jGrowl.defaults.closer = false;
$.jGrowl.defaults.closeTemplate = '';
$.jGrowl.defaults.position = 'bottom-right';
jGrowl.defaults.life = notifications.config.showingTime;
jGrowl.defaults.closer = false;
jGrowl.defaults.closeTemplate = '';
jGrowl.defaults.position = 'bottom-right';
};
function showMessage(msg, iconClass, options) {
@ -30,15 +34,22 @@ define( [ "jquery", "jgrowl", "underscore" ], function($) {
}
options = options || {};
iconClass = iconClass || "icon-info-sign";
$.jGrowl("<i class='icon-white " + iconClass + "'></i> " + _.escape(msg), options);
jGrowl("<i class='icon-white " + iconClass + "'></i> " + _.escape(msg), options);
}
notifications.onMessage = function(message) {
console.log(message);
showMessage(message);
};
notifications.onError = function(error) {
console.error(error);
if(_.isString(error)) {
showMessage(error, "icon-warning-sign");
}
else if(_.isObject(error)) {
showMessage(error.message, "icon-warning-sign");
}
};
notifications.onOfflineChanged = function(isOffline) {

View File

@ -1,4 +1,8 @@
define( [ "jquery", "underscore" ], function($) {
define([
"jquery",
"underscore",
"lib/css_browser_selector"
], function($, _) {
var scrollLink = {
extensionId: "scrollLink",

View File

@ -1,25 +1,16 @@
define( [ "jquery", "underscore" ], function($) {
define([
"jquery",
"underscore",
"utils"
], function($, _, utils) {
var toc = {
extensionId: "toc",
extensionName: "Table Of Content",
optional: true,
settingsBloc: [
'<p>Generates tables of content using the marker [TOC].</p>'
].join("")
settingsBloc: '<p>Generates tables of content using the marker [TOC].</p>'
};
// Used to generate an anchor
function slugify(text)
{
return text.toLowerCase()
.replace(/\s+/g, '-') // Replace spaces with -
.replace(/[^\w\-]+/g, '') // Remove all non-word chars
.replace(/\-\-+/g, '-') // Replace multiple - with single -
.replace(/^-+/, '') // Trim - from start of text
.replace(/-+$/, ''); // Trim - from end of text
}
// TOC element description
function TocElement(tagName, anchor, text) {
this.tagName = tagName;
@ -83,7 +74,7 @@ define( [ "jquery", "underscore" ], function($) {
function buildToc() {
var anchorList = {};
function createAnchor(element) {
var id = element.prop("id") || slugify(element.text());
var id = element.prop("id") || utils.slugify(element.text());
var anchor = id;
var index = 0;
while(_.has(anchorList, anchor)) {

View File

@ -0,0 +1,24 @@
define([
"jquery",
"underscore"
], function($, _) {
var workingIndicator = {
extensionId: "workingIndicator",
extensionName: "Working indicator",
settingsBloc: '<p>Displays an animated image when a network operation is running.</p>'
};
workingIndicator.onAsyncRunning = function(isRunning) {
if (isRunning === false) {
$(".working-indicator").removeClass("show");
$("body").removeClass("working");
} else {
$(".working-indicator").addClass("show");
$("body").addClass("working");
}
};
return workingIndicator;
});

View File

@ -1,53 +1,30 @@
define([
"jquery",
"underscore",
"core",
"utils",
"settings",
"extension-manager",
"synchronizer",
"publisher",
"sharing",
"text!../WELCOME.md",
"underscore"
], function($, core, utils, extensionManager, synchronizer, publisher, sharing, welcomeContent) {
"file-system",
"lib/text!../WELCOME.md"
], function($, _, core, utils, settings, extensionMgr, fileSystem, welcomeContent) {
var fileManager = {};
// Load file descriptors from localStorage and store in a map
var fileSystemDescriptor = _.chain(localStorage["file.list"].split(";"))
.compact()
.reduce(function(fileSystemDescriptor, fileIndex) {
var title = localStorage[fileIndex + ".title"];
var fileDesc = {
fileIndex : fileIndex,
title : title,
syncLocations: {},
publishLocations: {}
};
synchronizer.populateSyncLocations(fileDesc),
publisher.populatePublishLocations(fileDesc),
fileSystemDescriptor[fileIndex] = fileDesc;
return fileSystemDescriptor;
}, {})
.value();
extensionManager.onFileSystemLoaded(fileSystemDescriptor);
fileManager.getFileList = function() {
return _.values(fileSystemDescriptor);
};
var fileMgr = {};
// Defines the current file
var currentFile = (function() {
var currentFileIndex = localStorage["file.current"];
if(currentFileIndex !== undefined) {
return fileSystemDescriptor[currentFileIndex];
var fileIndex = localStorage["file.current"];
if(fileIndex !== undefined) {
return fileSystem[fileIndex];
}
})();
fileManager.getCurrentFile = function() {
fileMgr.getCurrentFile = function() {
return currentFile;
};
fileManager.isCurrentFile = function(fileDesc) {
fileMgr.isCurrentFile = function(fileDesc) {
return fileDesc === currentFile;
};
fileManager.setCurrentFile = function(fileDesc) {
fileMgr.setCurrentFile = function(fileDesc) {
currentFile = fileDesc;
if(fileDesc === undefined) {
localStorage.removeItem("file.current");
@ -58,24 +35,21 @@ define([
};
// Caution: this function recreate the editor (reset undo operations)
fileManager.selectFile = function(fileDesc) {
fileMgr.selectFile = function(fileDesc) {
var fileSystemSize = _.size(fileSystem);
// If no file create one
if (_.size(fileSystemDescriptor) === 0) {
fileDesc = fileManager.createFile(WELCOME_DOCUMENT_TITLE, welcomeContent);
if (_.size(fileSystem) === 0) {
fileDesc = fileMgr.createFile(WELCOME_DOCUMENT_TITLE, welcomeContent);
}
if(fileDesc === undefined) {
// If no file is selected take the last created
fileDesc = fileSystemDescriptor[_.keys(fileSystemDescriptor)[fileSystemDescriptor.length - 1]];
fileDesc = fileSystem[_.keys(fileSystem)[fileSystemSize - 1]];
}
fileManager.setCurrentFile(fileDesc);
// Update the file titles
fileManager.updateFileTitles();
publisher.notifyPublish();
fileMgr.setCurrentFile(fileDesc);
// Notify extensions
extensionManager.onFileSelected(fileDesc);
extensionMgr.onFileSelected(fileDesc);
// Hide the viewer pencil button
if(fileDesc.fileIndex == TEMPORARY_FILE_INDEX) {
@ -89,18 +63,18 @@ define([
$("#wmd-input").val(localStorage[fileDesc.fileIndex + ".content"]);
core.createEditor(function() {
// Callback to save content when textarea changes
fileManager.saveFile();
fileMgr.saveFile();
});
};
fileManager.createFile = function(title, content, syncLocations, isTemporary) {
content = content !== undefined ? content : core.settings.defaultContent;
fileMgr.createFile = function(title, content, syncLocations, isTemporary) {
content = content !== undefined ? content : settings.defaultContent;
syncLocations = syncLocations || {};
if (!title) {
// Create a file title
title = DEFAULT_FILE_TITLE;
var indicator = 2;
while(_.some(fileSystemDescriptor, function(fileDesc) {
while(_.some(fileSystem, function(fileDesc) {
return fileDesc.title == title;
})) {
title = DEFAULT_FILE_TITLE + indicator++;
@ -112,7 +86,7 @@ define([
if(!isTemporary) {
do {
fileIndex = "file." + utils.randomString();
} while(_.has(fileSystemDescriptor, fileIndex));
} while(_.has(fileSystem, fileIndex));
}
// Create the file in the localStorage
@ -137,27 +111,27 @@ define([
// Add the index to the file list
if(!isTemporary) {
localStorage["file.list"] += fileIndex + ";";
fileSystemDescriptor[fileIndex] = fileDesc;
extensionManager.onFileCreated(fileDesc);
fileSystem[fileIndex] = fileDesc;
extensionMgr.onFileCreated(fileDesc);
}
return fileDesc;
};
fileManager.deleteFile = function(fileDesc) {
fileDesc = fileDesc || fileManager.getCurrentFile();
if(fileManager.isCurrentFile(fileDesc)) {
fileMgr.deleteFile = function(fileDesc) {
fileDesc = fileDesc || fileMgr.getCurrentFile();
if(fileMgr.isCurrentFile(fileDesc)) {
// Unset the current fileDesc
fileManager.setCurrentFile();
fileMgr.setCurrentFile();
}
// Remove synchronized locations
_.each(fileDesc.syncLocations, function(syncAttributes) {
fileManager.removeSync(syncAttributes, true);
fileMgr.removeSync(syncAttributes, true);
});
// Remove publish locations
_.each(fileDesc.publishLocations, function(publishAttributes) {
fileManager.removePublish(publishAttributes, true);
fileMgr.removePublish(publishAttributes, true);
});
// Remove the index from the file list
@ -168,30 +142,29 @@ define([
localStorage.removeItem(fileIndex + ".content");
localStorage.removeItem(fileIndex + ".sync");
localStorage.removeItem(fileIndex + ".publish");
fileSystemDescriptor.removeItem(fileIndex);
extensionManager.onFileDeleted(fileDesc);
fileSystem.removeItem(fileIndex);
extensionMgr.onFileDeleted(fileDesc);
};
// Save current file in localStorage
fileManager.saveFile = function() {
fileMgr.saveFile = function() {
var content = $("#wmd-input").val();
var fileDesc = fileManager.getCurrentFile();
var fileDesc = fileMgr.getCurrentFile();
localStorage[fileDesc.fileIndex + ".content"] = content;
extensionManager.onFileChanged(fileDesc);
synchronizer.notifyChange(fileDesc);
extensionMgr.onFileChanged(fileDesc);
};
// Add a synchronized location to a file
fileManager.addSync = function(fileDesc, syncAttributes) {
fileMgr.addSync = function(fileDesc, syncAttributes) {
localStorage[fileDesc.fileIndex + ".sync"] += syncAttributes.syncIndex + ";";
fileDesc.syncLocations[syncAttributes.syncIndex] = syncAttributes;
// addSync is only used for export, not for import
extensionManager.onSyncExportSuccess(fileDesc, syncAttributes);
extensionMgr.onSyncExportSuccess(fileDesc, syncAttributes);
};
// Remove a synchronized location
fileManager.removeSync = function(syncAttributes, skipExtensions) {
var fileDesc = fileManager.getFileFromSyncIndex(syncAttributes.syncIndex);
fileMgr.removeSync = function(syncAttributes, skipExtensions) {
var fileDesc = fileMgr.getFileFromSyncIndex(syncAttributes.syncIndex);
if(fileDesc !== undefined) {
localStorage[fileDesc.fileIndex + ".sync"] = localStorage[fileDesc.fileIndex + ".sync"].replace(";"
+ syncAttributes.syncIndex + ";", ";");
@ -200,26 +173,26 @@ define([
localStorage.removeItem(syncAttributes.syncIndex);
fileDesc.syncLocations.removeItem(syncIndex);
if(!skipExtensions) {
extensionManager.onSyncRemoved(fileDesc, syncAttributes);
extensionMgr.onSyncRemoved(fileDesc, syncAttributes);
}
};
// Get the file descriptor associated to a syncIndex
fileManager.getFileFromSyncIndex = function(syncIndex) {
return _.find(fileSystemDescriptor, function(fileDesc) {
fileMgr.getFileFromSyncIndex = function(syncIndex) {
return _.find(fileSystem, function(fileDesc) {
return _.has(fileDesc.syncLocations, syncIndex);
});
};
// Get syncAttributes from syncIndex
fileManager.getSyncAttributes = function(syncIndex) {
var fileDesc = fileManager.getFileFromSyncIndex(syncIndex);
fileMgr.getSyncAttributes = function(syncIndex) {
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
return fileDesc && fileDesc.syncLocations[syncIndex];
};
// Returns true if provider has locations to synchronize
fileManager.hasSync = function(provider) {
return _.some(fileSystemDescriptor, function(fileDesc) {
fileMgr.hasSync = function(provider) {
return _.some(fileSystem, function(fileDesc) {
return _.some(fileDesc.syncLocations, function(syncAttributes) {
syncAttributes.provider == provider.providerId;
});
@ -227,33 +200,30 @@ define([
};
// Add a publishIndex (publish location) to a file
fileManager.addPublish = function(fileDesc, publishAttributes) {
fileMgr.addPublish = function(fileDesc, publishAttributes) {
localStorage[fileDesc.fileIndex + ".publish"] += publishAttributes.publishIndex + ";";
fileDesc.publishLocations[publishAttributes.publishIndex] = publishAttributes;
extensionManager.onNewPublishSuccess(fileDesc, publishAttributes);
extensionMgr.onNewPublishSuccess(fileDesc, publishAttributes);
};
// Remove a publishIndex (publish location)
fileManager.removePublish = function(publishAttributes, skipExtensions) {
var fileDesc = fileManager.getFileFromPublish(publishAttributes.publishIndex);
fileMgr.removePublish = function(publishAttributes, skipExtensions) {
var fileDesc = fileMgr.getFileFromPublish(publishAttributes.publishIndex);
if(fileDesc !== undefined) {
localStorage[fileDesc.fileIndex + ".publish"] = localStorage[fileDesc.fileIndex + ".publish"].replace(";"
+ publishAttributes.publishIndex + ";", ";");
if(fileManager.isCurrentFile(fileDesc)) {
publisher.notifyPublish();
}
}
// Remove publish attributes
localStorage.removeItem(publishAttributes.publishIndex);
fileDesc.publishLocations.removeItem(publishIndex);
if(!skipExtensions) {
extensionManager.onPublishRemoved(fileDesc, publishAttributes);
extensionMgr.onPublishRemoved(fileDesc, publishAttributes);
}
};
// Get the file descriptor associated to a publishIndex
fileManager.getFileFromPublish = function(publishIndex) {
return _.find(fileSystemDescriptor, function(fileDesc) {
fileMgr.getFileFromPublish = function(publishIndex) {
return _.find(fileSystem, function(fileDesc) {
return _.has(fileDesc.publishLocations, publishIndex);
});
};
@ -276,11 +246,12 @@ define([
}
core.onReady(function() {
fileManager.selectFile();
fileMgr.selectFile();
$(".action-create-file").click(function() {
var fileDesc = fileManager.createFile();
fileManager.selectFile(fileDesc);
var fileDesc = fileMgr.createFile();
fileMgr.selectFile(fileDesc);
var wmdInput = $("#wmd-input").focus().get(0);
if(wmdInput.setSelectionRange) {
wmdInput.setSelectionRange(0, 0);
@ -288,8 +259,8 @@ define([
$("#file-title").click();
});
$(".action-remove-file").click(function() {
fileManager.deleteFile();
fileManager.selectFile();
fileMgr.deleteFile();
fileMgr.selectFile();
});
$("#file-title").click(function() {
if(viewerMode === true) {
@ -305,15 +276,13 @@ define([
input.hide();
$("#file-title").show();
var title = $.trim(input.val());
var fileDesc = fileManager.getCurrentFile();
var fileDesc = fileMgr.getCurrentFile();
var fileIndexTitle = fileDesc.fileIndex + ".title";
if (title) {
if (title != localStorage[fileIndexTitle]) {
localStorage[fileIndexTitle] = title;
fileDesc.title = title;
fileManager.updateFileTitles();
synchronizer.notifyChange(fileDesc);
extensionManager.onTitleChanged(fileDesc);
extensionMgr.onTitleChanged(fileDesc);
}
}
input.val(localStorage[fileIndexTitle]);
@ -346,33 +315,17 @@ define([
});
$(".action-edit-document").click(function() {
var content = $("#wmd-input").val();
var title = fileManager.getCurrentFile().title;
var fileDesc = fileManager.createFile(title, content);
fileManager.selectFile(fileDesc);
var title = fileMgr.getCurrentFile().title;
var fileDesc = fileMgr.createFile(title, content);
fileMgr.selectFile(fileDesc);
window.location.href = ".";
});
$(".action-download-md").click(function() {
var content = $("#wmd-input").val();
var title = fileManager.getCurrentFile().title;
core.saveFile(content, title + ".md");
});
$(".action-download-html").click(function() {
var content = $("#wmd-preview").html();
var title = fileManager.getCurrentFile().title;
core.saveFile(content, title + ".html");
});
$(".action-download-template").click(function() {
var content = publisher.applyTemplate();
var title = fileManager.getCurrentFile().title;
core.saveFile(content, title + ".txt");
});
$(".action-welcome-file").click(function() {
var fileDesc = fileManager.createFile(WELCOME_DOCUMENT_TITLE, welcomeContent);
fileManager.selectFile(fileDesc);
var fileDesc = fileMgr.createFile(WELCOME_DOCUMENT_TITLE, welcomeContent);
fileMgr.selectFile(fileDesc);
});
});
core.setFileManager(fileManager);
extensionManager.onFileManagerCreated(fileManager);
return fileManager;
extensionMgr.onFileMgrCreated(fileMgr);
return fileMgr;
});

22
js/file-system.js Normal file
View File

@ -0,0 +1,22 @@
define([
"underscore",
"extension-manager"
], function(_, extensionMgr) {
var fileSystem = {};
// Load file descriptors from localStorage
_.chain(
localStorage["file.list"].split(";")
).compact().each(function(fileIndex) {
fileSystem[fileIndex] = {
fileIndex : fileIndex,
title : localStorage[fileIndex + ".title"],
syncLocations: {},
publishLocations: {}
};
});
extensionMgr.onFileSystemCreated(fileSystem);
return fileSystem;
});

View File

@ -1,4 +1,11 @@
define(["core", "utils", "extension-manager", "google-helper", "underscore"], function(core, utils, extensionManager, googleHelper) {
define([
"underscore",
"core",
"utils",
"extension-manager",
"file-manager",
"google-helper"
], function(_, core, utils, extensionMgr, fileMgr, googleHelper) {
var PROVIDER_GDRIVE = "gdrive";
@ -39,11 +46,11 @@ define(["core", "utils", "extension-manager", "google-helper", "underscore"], fu
localStorage[syncAttributes.syncIndex] = utils.serializeAttributes(syncAttributes);
var syncLocations = {};
syncLocations[syncAttributes.syncIndex] = syncAttributes;
var fileDesc = core.fileManager.createFile(file.title, file.content, syncLocations);
core.fileManager.selectFile(fileDesc);
var fileDesc = fileMgr.createFile(file.title, file.content, syncLocations);
fileMgr.selectFile(fileDesc);
fileDescList.push(fileDesc);
});
extensionManager.onSyncImportSuccess(fileDescList, gdriveProvider);
extensionMgr.onSyncImportSuccess(fileDescList, gdriveProvider);
});
});
};
@ -56,9 +63,9 @@ define(["core", "utils", "extension-manager", "google-helper", "underscore"], fu
var importIds = [];
_.each(ids, function(id) {
var syncIndex = createSyncIndex(id);
var fileDesc = core.fileManager.getFileFromSyncIndex(syncIndex);
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
if(fileDesc !== undefined) {
core.showError('"' + fileDesc.title + '" was already imported');
extensionMgr.onError('"' + fileDesc.title + '" was already imported');
return;
}
importIds.push(id);
@ -87,9 +94,9 @@ define(["core", "utils", "extension-manager", "google-helper", "underscore"], fu
}
// Check that file is not synchronized with an other one
var syncIndex = createSyncIndex(id);
var fileDesc = core.fileManager.getFileFromSyncIndex(syncIndex);
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
if(fileDesc !== undefined) {
core.showError('File ID is already synchronized with "' + fileDesc.title + '"');
extensionMgr.onError('File ID is already synchronized with "' + fileDesc.title + '"');
callback(true);
return;
}
@ -134,7 +141,7 @@ define(["core", "utils", "extension-manager", "google-helper", "underscore"], fu
var interestingChanges = [];
_.each(changes, function(change) {
var syncIndex = createSyncIndex(change.fileId);
var syncAttributes = core.fileManager.getSyncAttributes(syncIndex);
var syncAttributes = fileMgr.getSyncAttributes(syncIndex);
if(syncAttributes === undefined) {
return;
}
@ -155,11 +162,10 @@ define(["core", "utils", "extension-manager", "google-helper", "underscore"], fu
callback(error);
return;
}
var updateFileTitles = false;
_.each(changes, function(change) {
var syncAttributes = change.syncAttributes;
var syncIndex = syncAttributes.syncIndex;
var fileDesc = core.fileManager.getFileFromSyncIndex(syncIndex);
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
// No file corresponding (file may have been deleted locally)
if(fileDesc === undefined) {
return;
@ -167,8 +173,8 @@ define(["core", "utils", "extension-manager", "google-helper", "underscore"], fu
var localTitle = fileDesc.title;
// File deleted
if (change.deleted === true) {
core.showError('"' + localTitle + '" has been removed from Google Drive.');
core.fileManager.removeSync(syncAttributes);
extensionMgr.onError('"' + localTitle + '" has been removed from Google Drive.');
fileMgr.removeSync(syncAttributes);
return;
}
var localTitleChanged = syncAttributes.titleCRC != utils.crc32(localTitle);
@ -184,24 +190,23 @@ define(["core", "utils", "extension-manager", "google-helper", "underscore"], fu
// Conflict detection
if ((fileTitleChanged === true && localTitleChanged === true && remoteTitleChanged === true)
|| (fileContentChanged === true && localContentChanged === true && remoteContentChanged === true)) {
core.fileManager.createFile(localTitle + " (backup)", localContent);
updateFileTitles = true;
core.showMessage('Conflict detected on "' + localTitle + '". A backup has been created locally.');
var backupFileDesc = fileMgr.createFile(localTitle + " (backup)", localContent);
extensionMgr.onTitleChanged(backupFileDesc);
extensionMgr.onMessage('Conflict detected on "' + localTitle + '". A backup has been created locally.');
}
// If file title changed
if(fileTitleChanged && remoteTitleChanged === true) {
localStorage[fileDesc.fileIndex + ".title"] = file.title;
fileDesc.title = file.title;
updateFileTitles = true;
core.showMessage('"' + localTitle + '" has been renamed to "' + file.title + '" on Google Drive.');
extensionMgr.onTitleChanged(fileDesc);
extensionMgr.onMessage('"' + localTitle + '" has been renamed to "' + file.title + '" on Google Drive.');
}
// If file content changed
if(fileContentChanged && remoteContentChanged === true) {
localStorage[fileDesc.fileIndex + ".content"] = file.content;
core.showMessage('"' + file.title + '" has been updated from Google Drive.');
if(core.fileManager.isCurrentFile(fileDesc)) {
updateFileTitles = false; // Done by next function
core.fileManager.selectFile(); // Refresh editor
extensionMgr.onMessage('"' + file.title + '" has been updated from Google Drive.');
if(fileMgr.isCurrentFile(fileDesc)) {
fileMgr.selectFile(); // Refresh editor
}
}
// Update syncAttributes
@ -210,9 +215,6 @@ define(["core", "utils", "extension-manager", "google-helper", "underscore"], fu
syncAttributes.titleCRC = remoteTitleCRC;
localStorage[syncIndex] = utils.serializeAttributes(syncAttributes);
});
if(updateFileTitles) {
extensionManager.onTitleChanged();
}
localStorage[PROVIDER_GDRIVE + ".lastChangeId"] = newChangeId;
callback();
});
@ -264,18 +266,18 @@ define(["core", "utils", "extension-manager", "google-helper", "underscore"], fu
localStorage[syncAttributes.syncIndex] = utils.serializeAttributes(syncAttributes);
var syncLocations = {};
syncLocations[syncAttributes.syncIndex] = syncAttributes;
var fileDesc = core.fileManager.createFile(file.title, file.content, syncAttributes);
core.fileManager.selectFile(fileDesc);
core.showMessage('"' + file.title + '" created successfully on Google Drive.');
var fileDesc = fileMgr.createFile(file.title, file.content, syncAttributes);
fileMgr.selectFile(fileDesc);
extensionMgr.onMessage('"' + file.title + '" created successfully on Google Drive.');
});
}
else if (state.action == "open") {
var importIds = [];
_.each(state.ids, function(id) {
var syncIndex = createSyncIndex(id);
var fileDesc = core.fileManager.getFileFromSyncIndex(syncIndex);
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
if(fileDesc !== undefined) {
core.fileManager.selectFile(fileDesc);
fileMgr.selectFile(fileDesc);
}
else {
importIds.push(id);

View File

@ -1,4 +1,7 @@
define(["utils", "github-helper"], function(utils, githubHelper) {
define([
"utils",
"github-helper"
], function(utils, githubHelper) {
var PROVIDER_GIST = "gist";

View File

@ -1,4 +1,10 @@
define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
define([
"jquery",
"core",
"utils",
"extension-manager",
"async-runner"
], function($, core, utils, extensionMgr, asyncRunner) {
var connected = undefined;
var github = undefined;
@ -51,14 +57,14 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
task.chain();
return;
}
core.showMessage("Please make sure the Github authorization popup is not blocked by your browser.");
extensionMgr.onMessage("Please make sure the Github authorization popup is not blocked by your browser.");
var errorMsg = "Failed to retrieve a token from GitHub.";
// We add time for user to enter his credentials
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
var code = undefined;
function getCode() {
localStorage.removeItem("githubCode");
authWindow = core.popupWindow(
authWindow = utils.popupWindow(
'github-oauth-client.html?client_id=' + GITHUB_CLIENT_ID,
'stackedit-github-oauth', 960, 600);
authWindow.focus();
@ -106,7 +112,6 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
}
githubHelper.upload = function(reponame, branch, path, content, commitMsg, callback) {
callback = callback || core.doNothing;
var task = asyncRunner.createTask();
connect(task);
authenticate(task);
@ -145,7 +150,6 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
};
githubHelper.uploadGist = function(gistId, filename, isPublic, title, content, callback) {
callback = callback || core.doNothing;
var task = asyncRunner.createTask();
connect(task);
authenticate(task);
@ -184,7 +188,6 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
};
githubHelper.downloadGist = function(gistId, filename, callback) {
callback = callback || core.doNothing;
var task = asyncRunner.createTask();
connect(task);
// No need for authentication

View File

@ -1,4 +1,8 @@
define(["core", "utils", "github-helper"], function(core, utils, githubHelper) {
define([
"utils",
"settings",
"github-helper"
], function(utils, settings, githubHelper) {
var PROVIDER_GITHUB = "github";
@ -9,7 +13,7 @@ define(["core", "utils", "github-helper"], function(core, utils, githubHelper) {
};
githubProvider.publish = function(publishAttributes, title, content, callback) {
var commitMsg = core.settings.commitMsg;
var commitMsg = settings.commitMsg;
githubHelper.upload(publishAttributes.repository, publishAttributes.branch,
publishAttributes.path, content, commitMsg, callback);
};

View File

@ -1,4 +1,10 @@
define(["jquery", "core", "utils", "async-runner"], function($, core, utils, asyncRunner) {
define([
"jquery",
"core",
"utils",
"extension-manager",
"async-runner"
], function($, core, utils, extensionMgr, asyncRunner) {
var connected = false;
var authenticated = false;
@ -44,7 +50,7 @@ define(["jquery", "core", "utils", "async-runner"], function($, core, utils, asy
var immediate = true;
function localAuthenticate() {
if (immediate === false) {
core.showMessage("Please make sure the Google authorization popup is not blocked by your browser.");
extensionMgr.onMessage("Please make sure the Google authorization popup is not blocked by your browser.");
// If not immediate we add time for user to enter his credentials
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
}
@ -74,7 +80,6 @@ define(["jquery", "core", "utils", "async-runner"], function($, core, utils, asy
}
googleHelper.upload = function(fileId, parentId, title, content, etag, callback) {
callback = callback || core.doNothing;
var result = undefined;
var task = asyncRunner.createTask();
connect(task);
@ -151,7 +156,6 @@ define(["jquery", "core", "utils", "async-runner"], function($, core, utils, asy
};
googleHelper.checkChanges = function(lastChangeId, callback) {
callback = callback || core.doNothing;
var changes = [];
var newChangeId = lastChangeId || 0;
var task = asyncRunner.createTask();
@ -202,7 +206,6 @@ define(["jquery", "core", "utils", "async-runner"], function($, core, utils, asy
};
googleHelper.downloadMetadata = function(ids, callback, skipAuth) {
callback = callback || core.doNothing;
var result = [];
var task = asyncRunner.createTask();
connect(task);
@ -255,7 +258,6 @@ define(["jquery", "core", "utils", "async-runner"], function($, core, utils, asy
};
googleHelper.downloadContent = function(objects, callback, skipAuth) {
callback = callback || core.doNothing;
var result = [];
var task = asyncRunner.createTask();
// Add some time for user to choose his files
@ -378,7 +380,6 @@ define(["jquery", "core", "utils", "async-runner"], function($, core, utils, asy
}
googleHelper.picker = function(callback) {
callback = callback || core.doNothing;
var ids = [];
var picker = undefined;
function hidePicker() {

View File

View File

@ -1,5 +1,5 @@
/** vim: et:ts=4:sw=4:sts=4
* @license RequireJS 2.1.5 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
* @license RequireJS 2.1.6 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
@ -12,7 +12,7 @@ var requirejs, require, define;
(function (global) {
var req, s, head, baseElement, dataMain, src,
interactiveScript, currentlyAddingScript, mainScript, subPath,
version = '2.1.5',
version = '2.1.6',
commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
jsSuffixRegExp = /\.js$/,
@ -22,7 +22,7 @@ var requirejs, require, define;
hasOwn = op.hasOwnProperty,
ap = Array.prototype,
apsp = ap.splice,
isBrowser = !!(typeof window !== 'undefined' && navigator && document),
isBrowser = !!(typeof window !== 'undefined' && navigator && window.document),
isWebWorker = !isBrowser && typeof importScripts !== 'undefined',
//PS3 indicates loaded and complete, but need to wait for complete
//specifically. Sequence is 'loading', 'loaded', execution,
@ -134,6 +134,10 @@ var requirejs, require, define;
return document.getElementsByTagName('script');
}
function defaultOnError(err) {
throw err;
}
//Allow getting a global that expressed in
//dot notation, like 'a.b.c'.
function getGlobal(value) {
@ -500,7 +504,12 @@ var requirejs, require, define;
fn(defined[id]);
}
} else {
getModule(depMap).on(name, fn);
mod = getModule(depMap);
if (mod.error && name === 'error') {
fn(mod.error);
} else {
mod.on(name, fn);
}
}
}
@ -571,7 +580,13 @@ var requirejs, require, define;
id: mod.map.id,
uri: mod.map.url,
config: function () {
return (config.config && getOwn(config.config, mod.map.id)) || {};
var c,
pkg = getOwn(config.pkgs, mod.map.id);
// For packages, only support config targeted
// at the main module.
c = pkg ? getOwn(config.config, mod.map.id + '/' + pkg.main) :
getOwn(config.config, mod.map.id);
return c || {};
},
exports: defined[mod.map.id]
});
@ -840,8 +855,13 @@ var requirejs, require, define;
if (this.depCount < 1 && !this.defined) {
if (isFunction(factory)) {
//If there is an error listener, favor passing
//to that instead of throwing an error.
if (this.events.error) {
//to that instead of throwing an error. However,
//only do it for define()'d modules. require
//errbacks should not be called for failures in
//their callbacks (#699). However if a global
//onError is set, use that.
if ((this.events.error && this.map.isDefine) ||
req.onError !== defaultOnError) {
try {
exports = context.execCb(id, factory, depExports, exports);
} catch (e) {
@ -869,8 +889,8 @@ var requirejs, require, define;
if (err) {
err.requireMap = this.map;
err.requireModules = [this.map.id];
err.requireType = 'define';
err.requireModules = this.map.isDefine ? [this.map.id] : null;
err.requireType = this.map.isDefine ? 'define' : 'require';
return onError((this.error = err));
}
@ -1093,7 +1113,7 @@ var requirejs, require, define;
}));
if (this.errback) {
on(depMap, 'error', this.errback);
on(depMap, 'error', bind(this, this.errback));
}
}
@ -1605,7 +1625,7 @@ var requirejs, require, define;
},
/**
* Executes a module callack function. Broken out as a separate function
* Executes a module callback function. Broken out as a separate function
* solely to allow the build system to sequence the files in the built
* layer in the right sequence.
*
@ -1643,7 +1663,7 @@ var requirejs, require, define;
onScriptError: function (evt) {
var data = getScriptData(evt);
if (!hasPathFallback(data.id)) {
return onError(makeError('scripterror', 'Script error', evt, [data.id]));
return onError(makeError('scripterror', 'Script error for: ' + data.id, evt, [data.id]));
}
}
};
@ -1772,9 +1792,7 @@ var requirejs, require, define;
* function. Intercept/override it if you want custom error handling.
* @param {Error} err the error object.
*/
req.onError = function (err) {
throw err;
};
req.onError = defaultOnError;
/**
* Does the request to load a module for the browser case.
@ -1906,24 +1924,31 @@ var requirejs, require, define;
//baseUrl, if it is not already set.
dataMain = script.getAttribute('data-main');
if (dataMain) {
//Preserve dataMain in case it is a path (i.e. contains '?')
mainScript = dataMain;
//Set final baseUrl if there is not already an explicit one.
if (!cfg.baseUrl) {
//Pull off the directory of data-main for use as the
//baseUrl.
src = dataMain.split('/');
src = mainScript.split('/');
mainScript = src.pop();
subPath = src.length ? src.join('/') + '/' : './';
cfg.baseUrl = subPath;
dataMain = mainScript;
}
//Strip off any trailing .js since dataMain is now
//Strip off any trailing .js since mainScript is now
//like a module name.
dataMain = dataMain.replace(jsSuffixRegExp, '');
mainScript = mainScript.replace(jsSuffixRegExp, '');
//If mainScript is still a path, fall back to dataMain
if (req.jsExtRegExp.test(mainScript)) {
mainScript = dataMain;
}
//Put the data-main script in the files to load.
cfg.deps = cfg.deps ? cfg.deps.concat(dataMain) : [dataMain];
cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript];
return true;
}
@ -1951,12 +1976,13 @@ var requirejs, require, define;
//This module may not have dependencies
if (!isArray(deps)) {
callback = deps;
deps = [];
deps = null;
}
//If no name, and callback is a function, then figure out if it a
//CommonJS thing with dependencies.
if (!deps.length && isFunction(callback)) {
if (!deps && isFunction(callback)) {
deps = [];
//Remove comments from the callback string,
//look for require calls, and pull them into the dependencies,
//but only if there are function args.

286
js/main-min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -2,19 +2,34 @@
requirejs.config({
waitSeconds: 0,
paths: {
MathJax: '../lib/MathJax/MathJax.js?config=TeX-AMS_HTML'
"jquery": "lib/jquery",
"underscore": "lib/underscore",
"jgrowl": "lib/jgrowl",
"lib/MathJax": '../lib/MathJax/MathJax.js?config=TeX-AMS_HTML'
},
shim: {
'jquery-ui': ['jquery'],
'bootstrap': ['jquery'],
'jgrowl': ['jquery'],
'layout': ['jquery-ui'],
'Markdown.Extra': ['Markdown.Converter', 'prettify'],
'Markdown.Editor': ['Markdown.Converter']
'lib/underscore': {
exports: '_'
},
'lib/jgrowl': {
deps: ['lib/jquery'],
exports: 'jQuery.jGrowl'
},
'lib/jquery-ui': ['lib/jquery'],
'lib/bootstrap': ['lib/jquery'],
'lib/layout': ['lib/jquery-ui'],
'lib/Markdown.Extra': ['lib/Markdown.Converter', 'lib/prettify'],
'lib/Markdown.Editor': ['lib/Markdown.Converter']
}
});
require(["jquery", "file-manager", "synchronizer", "publisher"], function($) {
require([
"jquery",
"core",
"synchronizer",
"publisher"
], function($, core) {
$(function() {
// If browser has detected a new application cache.
if (window.applicationCache) {
@ -25,5 +40,8 @@ require(["jquery", "file-manager", "synchronizer", "publisher"], function($) {
}
}, false);
}
core.setReady();
});
});

View File

@ -1,8 +1,12 @@
define([
"jquery",
"underscore",
"core",
"utils",
"settings",
"extension-manager",
"file-system",
"file-manager",
"sharing",
"blogger-provider",
"dropbox-provider",
@ -11,59 +15,44 @@ define([
"gdrive-provider",
"ssh-provider",
"tumblr-provider",
"wordpress-provider",
"underscore"
], function($, core, utils, extensionManager, sharing) {
"wordpress-provider"
], function($, _, core, utils, settings, extensionMgr, fileSystem, fileMgr, sharing) {
var publisher = {};
// Create a map with providerId: providerObject
var providerMap = _.chain(arguments)
.map(function(argument) {
// Create a map with providerId: providerModule
var providerMap = _.chain(
arguments
).map(function(argument) {
return argument && argument.providerId && [argument.providerId, argument];
}).compact().object().value();
// Used to know if the current file has publications
var hasPublications = false;
// Allows external modules to update hasPublications flag
publisher.notifyPublish = function() {
var fileDesc = core.fileManager.getCurrentFile();
// Check that file has publications
if(_.size(fileDesc.publishLocations) === 0) {
hasPublications = false;
}
else {
hasPublications = true;
}
publisher.updatePublishButton();
};
// Used to enable/disable the publish button
publisher.updatePublishButton = function() {
if(publishRunning === true || hasPublications === false || core.isOffline) {
$(".action-force-publish").addClass("disabled");
}
else {
$(".action-force-publish").removeClass("disabled");
}
};
// Run updatePublishButton function on online/offline event
core.addOfflineListener(publisher.updatePublishButton);
// Retrieve publish locations from localStorage
_.each(fileSystem, function(fileDesc) {
_.chain(
localStorage[fileDesc.fileIndex + ".publish"].split(";")
).compact().each(function(publishIndex) {
var publishAttributes = JSON.parse(localStorage[publishIndex]);
// Store publishIndex
publishAttributes.publishIndex = publishIndex;
// Replace provider ID by provider module in attributes
publishAttributes.provider = providerMap[publishAttributes.provider];
fileDesc.publishLocations[publishIndex] = publishAttributes;
});
});
// Apply template to the current document
publisher.applyTemplate = function(publishAttributes) {
var fileDesc = core.fileManager.getCurrentFile();
var fileDesc = fileMgr.getCurrentFile();
try {
return _.template(core.settings.template, {
return _.template(settings.template, {
documentTitle: fileDesc.title,
documentMarkdown: $("#wmd-input").val(),
documentHTML: $("#wmd-preview").html(),
publishAttributes: publishAttributes
});
} catch(e) {
core.showError(e);
extensionMgr.onError(e);
throw e;
}
};
@ -105,7 +94,7 @@ define([
if(error !== undefined) {
var errorMsg = error.toString();
if(errorMsg.indexOf("|removePublish") !== -1) {
core.fileManager.removePublish(publishAttributes);
fileMgr.removePublish(publishAttributes);
}
if(errorMsg.indexOf("|stopPublish") !== -1) {
callback(error);
@ -124,15 +113,15 @@ define([
}
publishRunning = true;
publisher.updatePublishButton();
var fileDesc = fileManager.getCurrentFile();
extensionMgr.onPublishRunning(true);
var fileDesc = fileMgr.getCurrentFile();
publishTitle = fileDesc.title;
publishAttributesList = _.values(fileDesc.publishLocations);
publishLocation(function(errorFlag) {
publishRunning = false;
publisher.updatePublishButton();
extensionMgr.onPublishRunning(false);
if(errorFlag === undefined) {
extensionManager.onPublishSuccess(fileDesc);
extensionMgr.onPublishSuccess(fileDesc);
}
});
};
@ -144,8 +133,8 @@ define([
publishIndex = "publish." + utils.randomString();
} while(_.has(localStorage, publishIndex));
publishAttributes.publishIndex = publishIndex;
localStorage[publishIndex] = JSON.stringify(publishAttributes);
core.fileManager.addPublish(fileDesc, publishAttributes);
localStorage[publishIndex] = utils.serializeAttributes(publishAttributes);
fileMgr.addPublish(fileDesc, publishAttributes);
}
// Initialize the "New publication" dialog
@ -185,7 +174,7 @@ define([
}
// Perform provider's publishing
var fileDesc = core.fileManager.getCurrentFile();
var fileDesc = fileMgr.getCurrentFile();
var title = fileDesc.title;
var content = getPublishContent(publishAttributes);
provider.publish(publishAttributes, title, content, function(error) {
@ -193,8 +182,6 @@ define([
publishAttributes.provider = provider.providerId;
sharing.createLink(publishAttributes, function() {
createPublishIndex(fileDesc, publishAttributes);
publisher.notifyPublish();
core.fileManager.updateFileTitles();
});
}
});
@ -210,9 +197,9 @@ define([
// Retrieve file's publish locations from localStorage
publisher.populatePublishLocations = function(fileDesc) {
_.chain(localStorage[fileDesc.fileIndex + ".publish"].split(";"))
.compact()
.each(function(publishIndex) {
_.chain(
localStorage[fileDesc.fileIndex + ".publish"].split(";")
).compact().each(function(publishIndex) {
var publishAttributes = JSON.parse(localStorage[publishIndex]);
// Store publishIndex
publishAttributes.publishIndex = publishIndex;
@ -249,8 +236,25 @@ define([
publisher.publish();
}
});
// Save As menu items
$(".action-download-md").click(function() {
var content = $("#wmd-input").val();
var title = fileMgr.getCurrentFile().title;
utils.saveAs(content, title + ".md");
});
$(".action-download-html").click(function() {
var content = $("#wmd-preview").html();
var title = fileMgr.getCurrentFile().title;
utils.saveAs(content, title + ".html");
});
$(".action-download-template").click(function() {
var content = publisher.applyTemplate();
var title = fileMgr.getCurrentFile().title;
utils.saveAs(content, title + ".txt");
});
});
extensionManager.onPublisherCreated(publisher);
extensionMgr.onPublisherCreated(publisher);
return publisher;
});

28
js/settings.js Normal file
View File

@ -0,0 +1,28 @@
define([
"underscore"
], function(_) {
var settings = {
layoutOrientation : "horizontal",
lazyRendering : true,
editorFontSize : 14,
defaultContent: "\n\n\n> Written with [StackEdit](http://benweet.github.io/stackedit/).",
commitMsg : "Published by http://benweet.github.io/stackedit",
template : [
'<!DOCTYPE html>\n',
'<html>\n',
'<head>\n',
'<title><%= documentTitle %></title>\n',
'</head>\n',
'<body><%= documentHTML %></body>\n',
'</html>'].join(""),
sshProxy : SSH_PROXY_URL,
extensionSettings: {}
};
if (_.has(localStorage, "settings")) {
_.extend(settings, JSON.parse(localStorage.settings));
}
return settings;
});

View File

@ -1,9 +1,22 @@
define(["jquery", "core", "utils", "async-runner", "download-provider", "gist-provider", "underscore"], function($, core, utils, asyncRunner) {
define([
"jquery",
"underscore",
"core",
"utils",
"extension-manager",
"file-system",
"file-manager",
"async-runner",
"download-provider",
"gist-provider"
], function($, _, core, utils, extensionMgr, fileMgr, asyncRunner) {
var sharing = {};
// Create a map with providerId: providerObject
var providerMap = _.chain(arguments)
.map(function(argument) {
// Create a map with providerId: providerModule
var providerMap = _.chain(
arguments
).map(function(argument) {
return argument && argument.providerId && [argument.providerId, argument];
}).compact().object().value();
@ -52,11 +65,12 @@ define(["jquery", "core", "utils", "async-runner", "download-provider", "gist-pr
url.push('=');
url.push(encodeURIComponent(attributes[attributeName]));
});
url = url.join("");
$.getJSON(
"https://api-ssl.bitly.com/v3/shorten",
{
"access_token": BITLY_ACCESS_TOKEN,
"longUrl": url.join("")
"longUrl": url
},
function(response)
{
@ -64,46 +78,22 @@ define(["jquery", "core", "utils", "async-runner", "download-provider", "gist-pr
shortUrl = response.data.url;
attributes.sharingLink = shortUrl;
}
else {
extensionMgr.onError("An error occured while creating sharing link.");
attributes.sharingLink = url;
}
task.chain();
}
);
});
function onFinish() {
if(shortUrl === undefined) {
localStorage["missingSharingLink"] = true;
}
callback(shortUrl);
callback();
}
task.onSuccess(onFinish);
task.onError(onFinish);
asyncRunner.addTask(task);
};
// Create the possible missing links
function checkMissingLinks() {
if(core.isOffline === true) {
return;
}
if(!_.has(localStorage, "missingSharingLink")) {
return;
}
localStorage.removeItem("missingSharingLink");
var fileDescList = core.fileManager.getFileList();
_.each(fileDescList, function(fileDesc) {
_.each(fileDescList.publishLocations, function(publishAttributes, publishIndex) {
sharing.createLink(publishAttributes, function(shortUrl) {
if(shortUrl !== undefined) {
localStorage[publishIndex] = utils.serializeAttributes(attributes);
}
});
});
});
}
// Periodically check that links are not missing
if(viewerMode === false) {
core.addPeriodicCallback(checkMissingLinks);
}
core.onReady(function() {
if(viewerMode === false) {
return;
@ -135,8 +125,8 @@ define(["jquery", "core", "utils", "async-runner", "download-provider", "gist-pr
if(error) {
return;
}
var fileDesc = core.fileManager.createFile(title, content, undefined, true);
core.fileManager.selectFile(fileDesc);
var fileDesc = fileMgr.createFile(title, content, undefined, true);
fileMgr.selectFile(fileDesc);
});
});

View File

@ -1,4 +1,8 @@
define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
define([
"jquery",
"core",
"async-runner"
], function($, core, asyncRunner) {
var sshHelper = {};
@ -14,7 +18,6 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
}
sshHelper.upload = function(host, port, username, password, path, title, content, callback) {
callback = callback || core.doNothing;
var task = asyncRunner.createTask();
connect(task);
task.onRun(function() {

View File

@ -1,4 +1,7 @@
define([ "utils", "ssh-helper" ], function(utils, sshHelper) {
define([
"utils",
"ssh-helper"
], function(utils, sshHelper) {
var PROVIDER_SSH = "ssh";

View File

@ -1,5 +1,7 @@
// Setup an empty localStorage or upgrade an existing one
define( [ "underscore" ], function() {
// Setup an empty localStorage or upgrade an existing one
define([
"underscore"
], function(_) {
// Create the file system if not exist
if (localStorage["file.list"] === undefined) {
@ -122,8 +124,6 @@ define( [ "underscore" ], function() {
}
});
});
// Force creation of sharing links
localStorage["missingSharingLink"] = true;
version = "v6";
}

View File

@ -1,44 +1,37 @@
define([
"jquery",
"underscore",
"core",
"utils",
"extension-manager",
"file-system",
"file-manager",
"dropbox-provider",
"gdrive-provider",
"underscore"
], function($, core, utils, extensionManager) {
"gdrive-provider"
], function($, _, core, utils, extensionMgr, fileSystem, fileMgr) {
var synchronizer = {};
// Create a map with providerId: providerObject
var providerMap = _.chain(arguments)
.map(function(argument) {
// Create a map with providerId: providerModule
var providerMap = _.chain(
arguments
).map(function(argument) {
return argument && argument.providerId && [argument.providerId, argument];
}).compact().object().value();
// Used to know if user can force synchronization
var uploadPending = false;
// Allows external modules to update uploadPending flag
synchronizer.notifyChange = function(fileDesc) {
// Check that file has synchronized locations
if(_.size(fileDesc.syncLocations) !== 0) {
uploadPending = true;
synchronizer.updateSyncButton();
}
};
// Used to enable/disable the synchronization button
synchronizer.updateSyncButton = function() {
if(syncRunning === true || uploadPending === false || core.isOffline) {
$(".action-force-sync").addClass("disabled");
}
else {
$(".action-force-sync").removeClass("disabled");
}
};
// Run updateSyncButton on online/offline event
core.addOfflineListener(synchronizer.updateSyncButton);
// Retrieve sync locations from localStorage
_.each(fileSystem, function(fileDesc) {
_.chain(
localStorage[fileDesc.fileIndex + ".sync"].split(";")
).compact().each(function(syncIndex) {
var syncAttributes = JSON.parse(localStorage[syncIndex]);
// Store syncIndex
syncAttributes.syncIndex = syncIndex;
// Replace provider ID by provider module in attributes
syncAttributes.provider = providerMap[syncAttributes.provider];
fileDesc.syncLocations[syncIndex] = syncAttributes;
});
});
// Force the synchronization
synchronizer.forceSync = function() {
@ -73,8 +66,6 @@ define([
if(uploadFlag === true) {
// If uploadFlag is true, request another upload cycle
uploadCycle = true;
// When page is refreshed, this flag is false but should be true here
uploadPending = true;
}
if(error) {
callback(error);
@ -121,7 +112,7 @@ define([
if(uploadCycle === true) {
// New upload cycle
uploadCycle = false;
uploadFileList = core.fileManager.getFileList();
uploadFileList = fileMgr.getFileList();
fileUp(callback);
}
else {
@ -139,7 +130,7 @@ define([
var provider = providerList.pop();
// Check that provider has files to sync
if(!core.fileManager.hasSync(provider)) {
if(!fileMgr.hasSync(provider)) {
providerDown(callback);
return;
}
@ -165,18 +156,18 @@ define([
var lastSync = 0;
synchronizer.sync = function() {
// If sync is already running or timeout is not reached or offline
if (syncRunning || lastSync + SYNC_PERIOD > core.currentTime || core.isOffline) {
if (syncRunning || lastSync + SYNC_PERIOD > utils.currentTime || core.isOffline) {
return;
}
syncRunning = true;
extensionMgr.onSyncRunning(true);
uploadCycle = true;
lastSync = core.currentTime;
synchronizer.updateSyncButton();
lastSync = utils.currentTime;
function isError(error) {
if(error !== undefined) {
syncRunning = false;
synchronizer.updateSyncButton();
extensionMgr.onSyncRunning(false);
return true;
}
return false;
@ -191,7 +182,8 @@ define([
return;
}
syncRunning = false;
uploadPending = false;
extensionMgr.onSyncRunning(false);
extensionMgr.onSyncSuccess();
});
});
};
@ -200,20 +192,6 @@ define([
core.addPeriodicCallback(synchronizer.sync);
}
// Retrieve file's sync locations from localStorage
publisher.populateSyncLocations = function(fileDesc) {
_.chain(localStorage[fileDesc.fileIndex + ".sync"].split(";"))
.compact()
.each(function(syncIndex) {
var syncAttributes = JSON.parse(localStorage[syncIndex]);
// Store syncIndex
syncAttributes.syncIndex = syncIndex;
// Replace provider ID by provider module in attributes
syncAttributes.provider = providerMap[syncAttributes.provider];
fileDesc.syncLocations[syncIndex] = syncAttributes;
});
};
// Initialize the export dialog
function initExportDialog(provider) {
@ -247,14 +225,14 @@ define([
$(".action-sync-export-" + provider.providerId).click(function(event) {
// Perform the provider's export
var fileDesc = core.fileManager.getCurrentFile();
var fileDesc = fileMgr.getCurrentFile();
var title = fileDesc.title;
var content = localStorage[fileDesc.fileIndex + ".content"];
provider.exportFile(event, title, content, function(error, syncAttributes) {
if(error) {
return;
}
core.fileManager.addSync(fileDesc, syncAttributes);
fileMgr.addSync(fileDesc, syncAttributes);
});
// Store input values as preferences for next time we open the export dialog
@ -266,19 +244,18 @@ define([
});
// Provider's manual export button
$(".action-sync-manual-" + provider.providerId).click(function(event) {
var fileDesc = core.fileManager.getCurrentFile();
var fileDesc = fileMgr.getCurrentFile();
var title = fileDesc.title;
var content = localStorage[fileDesc.fileIndex + ".content"];
provider.exportManual(event, title, content, function(error, syncAttributes) {
if(error) {
return;
}
core.fileManager.addSync(fileDesc, syncAttributes);
fileMgr.addSync(fileDesc, syncAttributes);
});
});
});
synchronizer.updateSyncButton();
$(".action-force-sync").click(function() {
if(!$(this).hasClass("disabled")) {
synchronizer.forceSync();
@ -286,6 +263,6 @@ define([
});
});
extensionManager.onSynchronizerCreated(synchronizer);
extensionMgr.onSynchronizerCreated(synchronizer);
return synchronizer;
});

View File

@ -1,4 +1,10 @@
define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
define([
"jquery",
"core",
"utils",
"extension-manager",
"async-runner"
], function($, core, utils, extensionMgr, asyncRunner) {
var oauthParams = undefined;
@ -30,7 +36,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
task.chain();
return;
}
core.showMessage("Please make sure the Tumblr authorization popup is not blocked by your browser.");
extensionMgr.onMessage("Please make sure the Tumblr authorization popup is not blocked by your browser.");
var errorMsg = "Failed to retrieve a token from Tumblr.";
// We add time for user to enter his credentials
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
@ -48,7 +54,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
}
function getVerifier() {
localStorage.removeItem("tumblrVerifier");
authWindow = core.popupWindow(
authWindow = utils.popupWindow(
'tumblr-oauth-client.html?oauth_token=' + oauth_object.oauth_token,
'stackedit-tumblr-oauth', 800, 600);
authWindow.focus();
@ -92,7 +98,6 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
}
tumblrHelper.upload = function(blogHostname, postId, tags, format, title, content, callback) {
callback = callback || core.doNothing;
var task = asyncRunner.createTask();
connect(task);
authenticate(task);

View File

@ -1,4 +1,7 @@
define(["utils", "tumblr-helper"], function(utils, tumblrHelper) {
define([
"utils",
"tumblr-helper"
], function(utils, tumblrHelper) {
var PROVIDER_TUMBLR = "tumblr";

View File

@ -1,4 +1,8 @@
define([ "jquery", "underscore" ], function($) {
define([
"jquery",
"underscore",
"lib/FileSaver"
], function($, _) {
var utils = {};
@ -107,6 +111,16 @@ define([ "jquery", "underscore" ], function($) {
return $.trim(str);
};
// Slug function
utils.slugify = function(text) {
return text.toLowerCase()
.replace(/\s+/g, '-') // Replace spaces with -
.replace(/[^\w\-]+/g, '') // Remove all non-word chars
.replace(/\-\-+/g, '-') // Replace multiple - with single -
.replace(/^-+/, '') // Trim - from start of text
.replace(/-+$/, ''); // Trim - from end of text
};
// Check an URL
utils.checkUrl = function(url, addSlash) {
if(!url) {
@ -242,11 +256,48 @@ define([ "jquery", "underscore" ], function($) {
return crc.toString(16);
};
// Create an centered popup window
utils.popupWindow = function(url, title, width, height) {
var left = (screen.width / 2) - (width / 2);
var top = (screen.height / 2) - (height / 2);
return window.open(
url,
title,
'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width='
+ width
+ ', height='
+ height
+ ', top='
+ top
+ ', left='
+ left);
};
// Export data on disk
utils.saveAs = function(content, filename) {
if(saveAs !== undefined) {
var blob = new Blob([content], {type: "text/plain;charset=utf-8"});
saveAs(blob, filename);
}
else {
var uriContent = "data:application/octet-stream;base64,"
+ utils.encodeBase64(content);
window.open(uriContent, 'file');
}
};
// Generates a random string
utils.randomString = function() {
return _.random(4294967296).toString(36);
};
// Time shared by others modules
utils.updateCurrentTime = function() {
utils.currentTime = new Date().getTime();
};
utils.updateCurrentTime();
// Serialize sync/publish attributes
utils.serializeAttributes = function(attributes) {
// Don't store sync/publish index

View File

@ -1,4 +1,10 @@
define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
define([
"jquery",
"core",
"utils",
"extension-manager",
"async-runner"
], function($, core, utils, extensionMgr, asyncRunner) {
var token = undefined;
@ -25,14 +31,14 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
task.chain();
return;
}
core.showMessage("Please make sure the Wordpress authorization popup is not blocked by your browser.");
extensionMgr.onMessage("Please make sure the Wordpress authorization popup is not blocked by your browser.");
var errorMsg = "Failed to retrieve a token from Wordpress.";
// We add time for user to enter his credentials
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
var code = undefined;
function getCode() {
localStorage.removeItem("wordpressCode");
authWindow = core.popupWindow(
authWindow = utils.popupWindow(
'wordpress-oauth-client.html?client_id=' + WORDPRESS_CLIENT_ID,
'stackedit-wordpress-oauth', 960, 600);
authWindow.focus();
@ -76,7 +82,6 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
}
wordpressHelper.upload = function(site, postId, tags, title, content, callback) {
callback = callback || core.doNothing;
var task = asyncRunner.createTask();
connect(task);
authenticate(task);

View File

@ -1,4 +1,7 @@
define(["utils", "wordpress-helper"], function(utils, wordpressHelper) {
define([
"utils",
"wordpress-helper"
], function(utils, wordpressHelper) {
var PROVIDER_WORDPRESS = "wordpress";

View File

@ -24,7 +24,7 @@
var require = { baseUrl : "js", deps : [ "main" + suffix ] };
var viewerMode = true;
</script>
<script src="js/require.js"></script>
<script src="js/lib/require.js"></script>
</head>
<body class="viewer">
<div id="navbar" class="navbar navbar-fixed-top ui-layout-north">