New extension pattern

This commit is contained in:
benweet 2013-05-29 20:55:23 +01:00
parent c6c06373da
commit d7304444a1
44 changed files with 5801 additions and 5349 deletions

View File

@ -327,7 +327,6 @@ hr {
div.dropdown-menu {
padding: 5px 20px;
white-space: normal;
}
div.dropdown-menu p,
@ -335,12 +334,17 @@ div.dropdown-menu blockquote {
margin: 10px 0;
}
div.dropdown-menu .stat {
margin-bottom: 10px;
}
div.dropdown-menu i {
margin-right: 0;
}
#link-container {
min-width: 210px;
white-space: normal;
}
#link-container .link-list {
@ -518,6 +522,10 @@ div.dropdown-menu i {
text-align: left;
}
#modal-settings .accordion-inner .form-inline .label-text {
margin: 0 10px;
}
.accordion-toggle {
cursor: help;
}

BIN
doc/img/architecture.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -50,15 +50,15 @@ define([
};
/**
* chain() calls the next onRun callback or the onSuccess callbacks when
* finished. The optional callback parameter can be used to pass an onRun
* callback during execution.
* finished. The optional callback parameter can be used to pass an
* onRun callback during execution.
*/
task.chain = function(callback) {
if (task.finished === true) {
if(task.finished === true) {
return;
}
// If first execution
if (task.queue === undefined) {
if(task.queue === undefined) {
// Create a copy of the onRun callbacks
task.queue = task.runCallbacks.slice();
}
@ -68,7 +68,7 @@ define([
return;
}
// If all callbacks have been run
if (task.queue.length === 0) {
if(task.queue.length === 0) {
// Run the onSuccess callbacks
runSafe(task, task.successCallbacks);
return;
@ -78,11 +78,11 @@ define([
runCallback();
};
/**
* error() calls the onError callbacks passing the error parameter and ends
* the task by throwing an exception.
* error() calls the onError callbacks passing the error parameter and
* ends the task by throwing an exception.
*/
task.error = function(error) {
if (task.finished === true) {
if(task.finished === true) {
return;
}
error = error || new Error("Unknown error");
@ -97,12 +97,12 @@ define([
* retry() can be called in an onRun callback to restart the task
*/
task.retry = function(error, maxRetryCounter) {
if (task.finished === true) {
if(task.finished === true) {
return;
}
maxRetryCounter = maxRetryCounter || 5;
task.queue = undefined;
if (task.retryCounter >= maxRetryCounter) {
if(task.retryCounter >= maxRetryCounter) {
task.error(error);
return;
}
@ -121,17 +121,17 @@ define([
_.defer(function() {
// If there is a task currently running
if (currentTaskRunning === true) {
if(currentTaskRunning === true) {
// If the current task takes too long
if (currentTaskStartTime + currentTask.timeout < utils.currentTime) {
if(currentTaskStartTime + currentTask.timeout < utils.currentTime) {
currentTask.error(new Error("A timeout occurred."));
}
return;
}
if (currentTask === undefined) {
if(currentTask === undefined) {
// If no task in the queue
if (taskQueue.length === 0) {
if(taskQueue.length === 0) {
return;
}
@ -145,7 +145,7 @@ define([
}
// Run the task
if (currentTaskStartTime <= utils.currentTime) {
if(currentTaskStartTime <= utils.currentTime) {
currentTaskRunning = true;
currentTask.chain();
}
@ -162,14 +162,15 @@ define([
}
finally {
task.finished = true;
if (currentTask === task) {
if(currentTask === task) {
currentTask = undefined;
currentTaskRunning = false;
}
if (taskQueue.length === 0) {
if(taskQueue.length === 0) {
asyncRunning = false;
extensionMgr.onAsyncRunning(false);
} else {
}
else {
asyncRunner.runTask();
}
}
@ -183,7 +184,7 @@ define([
// Change current task timeout
asyncRunner.setCurrentTaskTimeout = function(timeout) {
if (currentTask !== undefined) {
if(currentTask !== undefined) {
currentTask.timeout = timeout;
}
};

View File

@ -10,18 +10,13 @@ define([
providerId: PROVIDER_BLOGGER,
providerName: "Blogger",
defaultPublishFormat: "html",
publishPreferencesInputIds: ["blogger-url"]
publishPreferencesInputIds: [
"blogger-url"
]
};
bloggerProvider.publish = function(publishAttributes, title, content, callback) {
googleHelper.uploadBlogger(
publishAttributes.blogUrl,
publishAttributes.blogId,
publishAttributes.postId,
publishAttributes.labelList,
title,
content,
function(error, blogId, postId) {
googleHelper.uploadBlogger(publishAttributes.blogUrl, publishAttributes.blogId, publishAttributes.postId, publishAttributes.labelList, title, content, function(error, blogId, postId) {
if(error) {
callback(error);
return;
@ -29,8 +24,7 @@ define([
publishAttributes.blogId = blogId;
publishAttributes.postId = postId;
callback();
}
);
});
};
bloggerProvider.newPublishAttributes = function(event) {
@ -43,9 +37,7 @@ define([
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,8 +1,10 @@
var MAIN_URL = "http://benweet.github.io/stackedit/";
var GOOGLE_API_KEY = "AIzaSyAeCU8CGcSkn0z9js6iocHuPBX4f_mMWkw";
var GOOGLE_SCOPES = [ "https://www.googleapis.com/auth/drive.install",
var GOOGLE_SCOPES = [
"https://www.googleapis.com/auth/drive.install",
"https://www.googleapis.com/auth/drive",
"https://www.googleapis.com/auth/blogger" ];
"https://www.googleapis.com/auth/blogger"
];
var GOOGLE_DRIVE_APP_ID = "241271498917";
var DROPBOX_APP_KEY = "lq6mwopab8wskas";
var DROPBOX_APP_SECRET = "851fgnucpezy84t";
@ -25,7 +27,7 @@ var SSH_PROXY_URL = "http://stackedit-ssh-proxy.herokuapp.com/";
// Use by Google's client.js
var delayedFunction = undefined;
function runDelayedFunction() {
if (delayedFunction !== undefined) {
if(delayedFunction !== undefined) {
delayedFunction();
}
}

View File

@ -29,10 +29,10 @@ define([
userReal = true;
userActive = true;
userLastActivity = utils.currentTime;
};
}
function isUserActive() {
if(userActive === true
&& utils.currentTime - userLastActivity > USER_IDLE_THRESHOLD) {
if(userActive === true && utils.currentTime - userLastActivity > USER_IDLE_THRESHOLD) {
userActive = false;
}
return userActive && windowUnique;
@ -80,13 +80,13 @@ define([
}
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 < utils.currentTime) {
if(core.isOffline === true && navigator.onLine === true && 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"
url: "//www.google.com/jsapi",
timeout: AJAX_TIMEOUT,
dataType: "script"
}).done(function() {
setOnline();
});
@ -156,47 +156,41 @@ define([
return;
}
var layoutGlobalConfig = {
closable : true,
resizable : false,
slidable : false,
livePaneResizing : true,
enableCursorHotkey : false,
spacing_open : 15,
spacing_closed : 15,
togglerLength_open : 90,
togglerLength_closed : 90,
stateManagement__enabled : false,
center__minWidth : 200,
center__minHeight : 200
closable: true,
resizable: false,
slidable: false,
livePaneResizing: true,
enableCursorHotkey: false,
spacing_open: 15,
spacing_closed: 15,
togglerLength_open: 90,
togglerLength_closed: 90,
stateManagement__enabled: false,
center__minWidth: 200,
center__minHeight: 200
};
extensionMgr.onLayoutConfigure(layoutGlobalConfig);
if (settings.layoutOrientation == "horizontal") {
if(settings.layoutOrientation == "horizontal") {
$(".ui-layout-south").remove();
$(".ui-layout-east").addClass("well").prop("id", "wmd-preview");
layout = $('body').layout(
$.extend(layoutGlobalConfig, {
east__resizable : true,
east__size : .5,
east__minSize : 200
})
);
} else if (settings.layoutOrientation == "vertical") {
layout = $('body').layout($.extend(layoutGlobalConfig, {
east__resizable: true,
east__size: .5,
east__minSize: 200
}));
}
else if(settings.layoutOrientation == "vertical") {
$(".ui-layout-east").remove();
$(".ui-layout-south").addClass("well").prop("id", "wmd-preview");
layout = $('body').layout(
$.extend(layoutGlobalConfig, {
south__resizable : true,
south__size : .5,
south__minSize : 200
})
);
layout = $('body').layout($.extend(layoutGlobalConfig, {
south__resizable: true,
south__size: .5,
south__minSize: 200
}));
}
$(".ui-layout-toggler-north").addClass("btn").append(
$("<b>").addClass("caret"));
$(".ui-layout-toggler-south").addClass("btn").append(
$("<b>").addClass("caret"));
$(".ui-layout-toggler-east").addClass("btn").append(
$("<b>").addClass("caret"));
$(".ui-layout-toggler-north").addClass("btn").append($("<b>").addClass("caret"));
$(".ui-layout-toggler-south").addClass("btn").append($("<b>").addClass("caret"));
$(".ui-layout-toggler-east").addClass("btn").append($("<b>").addClass("caret"));
$("#navbar").click(function() {
layout.allowOverflow('north');
});
@ -210,7 +204,7 @@ define([
var converter = new Markdown.Converter();
var editor = new Markdown.Editor(converter);
// Custom insert link dialog
editor.hooks.set("insertLinkDialog", function (callback) {
editor.hooks.set("insertLinkDialog", function(callback) {
insertLinkCallback = callback;
utils.resetModalInputs();
$("#modal-insert-link").modal();
@ -220,7 +214,7 @@ define([
return true;
});
// Custom insert image dialog
editor.hooks.set("insertImageDialog", function (callback) {
editor.hooks.set("insertImageDialog", function(callback) {
insertLinkCallback = callback;
utils.resetModalInputs();
$("#modal-insert-image").modal();
@ -270,8 +264,7 @@ define([
firstChange = false;
// Hide default buttons
$(".wmd-button-row").addClass("btn-group").find("li:not(.wmd-spacer)")
.addClass("btn").css("left", 0).find("span").hide();
$(".wmd-button-row").addClass("btn-group").find("li:not(.wmd-spacer)").addClass("btn").css("left", 0).find("span").hide();
// Add customized buttons
$("#wmd-bold-button").append($("<i>").addClass("icon-bold"));
@ -319,7 +312,7 @@ define([
// listen to online/offline events
$(window).on('offline', core.setOffline);
$(window).on('online', setOnline);
if (navigator.onLine === false) {
if(navigator.onLine === false) {
core.setOffline();
}
@ -378,7 +371,7 @@ define([
$("#wmd-input, #md-section-helper").css({
// Apply editor font size
"font-size": settings.editorFontSize + "px",
"line-height": Math.round(settings.editorFontSize * (20/14)) + "px"
"line-height": Math.round(settings.editorFontSize * (20 / 14)) + "px"
});
// Manage tab key
@ -398,17 +391,6 @@ define([
});
// Tooltips
$(".tooltip-scroll-link").tooltip({
html: true,
container: '#modal-settings',
placement: 'right',
title: ['Scroll Link is a feature that binds together editor and preview scrollbars. ',
'It allows you to keep an eye on the preview while scrolling the editor and vice versa. ',
'<br><br>',
'The mapping between Markdown and HTML is based on the position of the title elements (h1, h2, ...) in the page. ',
'Therefore, if your document does not contain any title, the mapping will be linear and consequently less efficient.',
].join("")
});
$(".tooltip-lazy-rendering").tooltip({
container: '#modal-settings',
placement: 'right',
@ -425,18 +407,22 @@ define([
container: '#modal-settings',
placement: 'right',
trigger: 'manual',
title: ['Available variables:<br>',
'<ul><li><b>documentTitle</b>: document title</li>',
'<li><b>documentMarkdown</b>: document in Markdown format</li>',
'<li><b>documentHTML</b>: document in HTML format</li>',
'<li><b>publishAttributes</b>: attributes of the publish location (undefined when using "Save")</li></ul>',
'Examples:<br>',
title: [
'Available variables:<br>',
'<ul>',
' <li><b>documentTitle</b>: document title</li>',
' <li><b>documentMarkdown</b>: document in Markdown format</li>',
' <li><b>documentHTML</b>: document in HTML format</li>',
' <li><b>publishAttributes</b>: attributes of the publish location (undefined when using "Save")</li>',
'</ul>',
'Examples:<br />',
_.escape('<title><%= documentTitle %></title>'),
'<br>',
'<br />',
_.escape('<div><%- documentHTML %></div>'),
'<br>',
'<br />',
_.escape('<% if(publishAttributes.provider == "github") print(documentMarkdown); %>'),
'<br><br><a target="_blank" href="http://underscorejs.org/#template">More info</a>',
'<br /><br />',
'<a target="_blank" href="http://underscorejs.org/#template">More info</a>',
].join("")
}).click(function(e) {
$(this).tooltip('show');
@ -467,4 +453,3 @@ define([
return core;
});

View File

@ -8,7 +8,9 @@ define([
var downloadProvider = {
providerId: PROVIDER_DOWNLOAD,
sharingAttributes: ["url"]
sharingAttributes: [
"url"
]
};
downloadProvider.importPublic = function(importParameters, callback) {
@ -24,10 +26,10 @@ define([
}
title = url.substring(slashUrl + 1);
$.ajax({
url : DOWNLOAD_PROXY_URL + "download?url=" + url,
url: DOWNLOAD_PROXY_URL + "download?url=" + url,
type: "GET",
dataType : "text",
timeout : AJAX_TIMEOUT
dataType: "text",
timeout: AJAX_TIMEOUT
}).done(function(result, textStatus, jqXHR) {
content = result;
task.chain();

View File

@ -19,13 +19,14 @@ define([
task.error(new Error("Operation not available in offline mode.|stopPublish"));
return;
}
if (client !== undefined) {
if(client !== undefined) {
task.chain();
return;
}
$.ajax({
url : "lib/dropbox.min.js",
dataType : "script", timeout : AJAX_TIMEOUT
url: "lib/dropbox.min.js",
dataType: "script",
timeout: AJAX_TIMEOUT
}).done(function() {
client = new Dropbox.Client({
key: DROPBOX_APP_KEY,
@ -49,27 +50,30 @@ define([
// Try to authenticate with Oauth
function authenticate(task) {
task.onRun(function() {
if (authenticated === true) {
if(authenticated === true) {
task.chain();
return;
}
var immediate = true;
function localAuthenticate() {
if (immediate === false) {
if(immediate === false) {
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
// If not immediate we add time for user to enter his
// credentials
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
}
client.reset();
client.authenticate({interactive: !immediate}, function(error, client) {
client.authenticate({
interactive: !immediate
}, function(error, client) {
// Success
if (client.authState === Dropbox.Client.DONE) {
if(client.authState === Dropbox.Client.DONE) {
authenticated = true;
task.chain();
return;
}
// If immediate did not work retry without immediate flag
if (immediate === true) {
if(immediate === true) {
immediate = false;
task.chain(localAuthenticate);
return;
@ -89,7 +93,7 @@ define([
authenticate(task);
task.onRun(function() {
client.writeFile(path, content, function(error, stat) {
if (!error) {
if(!error) {
result = stat;
task.chain();
return;
@ -119,7 +123,7 @@ define([
task.onRun(function() {
function retrievePageOfChanges() {
client.pullChanges(newChangeId, function(error, pullChanges) {
if (error) {
if(error) {
handleError(error, task);
return;
}
@ -128,9 +132,10 @@ define([
if(pullChanges.changes !== undefined) {
changes = changes.concat(pullChanges.changes);
}
if (pullChanges.shouldPullAgain) {
if(pullChanges.shouldPullAgain) {
task.chain(retrievePageOfChanges);
} else {
}
else {
task.chain();
}
});
@ -229,26 +234,26 @@ define([
function handleError(error, task) {
var errorMsg = true;
if (error) {
if(error) {
logger.error(error);
// Try to analyze the error
if (typeof error === "string") {
if(typeof error === "string") {
errorMsg = error;
}
else {
errorMsg = "Dropbox error ("
+ error.status + ": " + error.responseText + ").";
errorMsg = "Dropbox error (" + error.status + ": " + error.responseText + ").";
if (error.status === 401 || error.status === 403) {
if(error.status === 401 || error.status === 403) {
authenticated = false;
errorMsg = "Access to Dropbox account is not authorized.";
task.retry(new Error(errorMsg), 1);
return;
} else if(error.status === 400 && error.responseText
.indexOf("oauth_nonce") !== -1) {
}
else if(error.status === 400 && error.responseText.indexOf("oauth_nonce") !== -1) {
// A bug I guess...
_.each(_.keys(localStorage), function(key) {
// We have to remove the Oauth cache from the localStorage
// We have to remove the Oauth cache from the
// localStorage
if(key.indexOf("dropbox-auth") === 0) {
localStorage.removeItem(key);
}
@ -256,7 +261,8 @@ define([
authenticated = false;
task.retry(new Error(errorMsg), 1);
return;
} else if (error.status <= 0) {
}
else if(error.status <= 0) {
client = undefined;
authenticated = false;
core.setOffline();
@ -270,13 +276,14 @@ define([
var pickerLoaded = false;
function loadPicker(task) {
task.onRun(function() {
if (pickerLoaded === true) {
if(pickerLoaded === true) {
task.chain();
return;
}
$.ajax({
url : "https://www.dropbox.com/static/api/1/dropbox.js",
dataType : "script", timeout : AJAX_TIMEOUT
url: "https://www.dropbox.com/static/api/1/dropbox.js",
dataType: "script",
timeout: AJAX_TIMEOUT
}).done(function() {
pickerLoaded = true;
task.chain();
@ -302,7 +309,7 @@ define([
options.multiselect = true;
options.linkType = "direct";
options.success = function(files) {
for(var i=0; i<files.length; i++) {
for ( var i = 0; i < files.length; i++) {
var path = files[i].link;
path = path.replace(/.*\/view\/[^\/]*/, "");
paths.push(decodeURI(path));

View File

@ -101,7 +101,7 @@ define([
return;
}
dropboxHelper.upload(path, content, function(error, result) {
if (error) {
if(error) {
callback(error);
return;
}
@ -141,7 +141,7 @@ define([
dropboxProvider.syncDown = function(callback) {
var lastChangeId = localStorage[PROVIDER_DROPBOX + ".lastChangeId"];
dropboxHelper.checkChanges(lastChangeId, function(error, changes, newChangeId) {
if (error) {
if(error) {
callback(error);
return;
}
@ -165,7 +165,7 @@ define([
}
});
dropboxHelper.downloadContent(interestingChanges, function(error, changes) {
if (error) {
if(error) {
callback(error);
return;
}
@ -173,31 +173,32 @@ define([
var syncAttributes = change.syncAttributes;
var syncIndex = syncAttributes.syncIndex;
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
// No file corresponding (file may have been deleted locally)
// No file corresponding (file may have been deleted
// locally)
if(fileDesc === undefined) {
return;
}
var localTitle = fileDesc.title;
// File deleted
if (change.wasRemoved === true) {
if(change.wasRemoved === true) {
extensionMgr.onError('"' + localTitle + '" has been removed from Dropbox.');
fileMgr.removeSync(syncAttributes);
return;
}
var localContent = fileDesc.getContent();
var localContent = fileDesc.content;
var localContentChanged = syncAttributes.contentCRC != utils.crc32(localContent);
var file = change.stat;
var remoteContentCRC = utils.crc32(file.content);
var remoteContentChanged = syncAttributes.contentCRC != remoteContentCRC;
var fileContentChanged = localContent != file.content;
// Conflict detection
if (fileContentChanged === true && localContentChanged === true && remoteContentChanged === true) {
if(fileContentChanged === true && localContentChanged === true && remoteContentChanged === true) {
fileMgr.createFile(localTitle + " (backup)", localContent);
extensionMgr.onMessage('Conflict detected on "' + localTitle + '". A backup has been created locally.');
}
// If file content changed
if(fileContentChanged && remoteContentChanged === true) {
fileDesc.setContent(file.content);
fileDesc.content = file.content;
extensionMgr.onMessage('"' + localTitle + '" has been updated from Dropbox.');
if(fileMgr.isCurrentFile(fileDesc)) {
fileMgr.selectFile(); // Refresh editor

View File

@ -1,4 +1,4 @@
define( [
define([
"jquery",
"underscore",
"utils",
@ -24,17 +24,13 @@ define( [
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();
}
@ -75,7 +71,7 @@ define( [
extensionMgr["onSaveSettings"] = function(newExtensionSettings, event) {
logger.debug("onSaveSettings");
_.each(extensionList, function(extension) {
var newExtensionConfig = extension.defaultConfig || {};
var newExtensionConfig = _.extend({}, extension.defaultConfig);
newExtensionConfig.enabled = utils.getInputChecked("#input-enable-extension-" + extension.extensionId);
var onSaveSettingsCallback = extension.onSaveSettings;
onSaveSettingsCallback && onSaveSettingsCallback(newExtensionConfig, event);
@ -143,18 +139,19 @@ define( [
var accordionTmpl = [
'<div class="accordion-group">',
'<div class="accordion-heading">',
'<label class="checkbox pull-right">',
'<input id="input-enable-extension-<%= extensionId %>" type="checkbox" <% if(!optional) { %> disabled <% } %>> enabled',
'</label>',
'<a id="accordion-toggle-test" data-toggle="collapse" data-parent="#accordion-extensions" class="accordion-toggle" href="#collapse-<%= extensionId %>">',
'<%= extensionName %>',
'</a>',
'</div>',
'<div id="collapse-<%= extensionId %>" class="accordion-body collapse">',
'<div class="accordion-inner"><%= settingsBloc %></div>',
'</div>',
'</div>'].join("");
' <div class="accordion-heading">',
' <label class="checkbox pull-right">',
' <input id="input-enable-extension-<%= extensionId %>" type="checkbox" <% if(!optional) { %> disabled <% } %>> enabled',
' </label>',
' <a id="accordion-toggle-test" data-toggle="collapse" data-parent="#accordion-extensions" class="accordion-toggle" href="#collapse-<%= extensionId %>">',
' <%= extensionName %>',
' </a>',
' </div>',
' <div id="collapse-<%= extensionId %>" class="accordion-body collapse">',
' <div class="accordion-inner"><%= settingsBloc %></div>',
' </div>',
'</div>'
].join("");
function createSettings(extension) {
$("#accordion-extensions").append($(_.template(accordionTmpl, {
@ -167,9 +164,7 @@ define( [
$(function() {
// Create accordion in settings dialog
_.chain(
extensionList
).sortBy(function(extension) {
_.chain(extensionList).sortBy(function(extension) {
return extension.extensionName.toLowerCase();
}).each(createSettings);

View File

@ -25,7 +25,8 @@ define([
else {
button.removeClass("disabled");
}
};
}
;
var publisher = undefined;
buttonPublish.onPublisherCreated = function(publisherParameter) {
@ -35,9 +36,9 @@ define([
buttonPublish.onCreateButton = function() {
button = $([
'<button class="btn" title="Publish this document">',
'<i class="icon-share"></i>',
'</button>'].join("")
).click(function() {
' <i class="icon-share"></i>',
'</button>'
].join("")).click(function() {
if(!$(this).hasClass("disabled")) {
publisher.publish();
}

View File

@ -13,29 +13,31 @@ define([
buttonShare.onCreateButton = function() {
return $([
'<button class="btn dropdown-toggle" data-toggle="dropdown" title="Share this document">',
'<i class="icon-link"></i>',
' <i class="icon-link"></i>',
'</button>',
'<div id="link-container" class="dropdown-menu pull-right">',
'<div class="link-list"></div>',
'<p class="no-link">To share this document you need first to ',
'<a href="#" class="action-publish-gist">publish it as a Gist</a>',
' <h3 class="muted">Sharing</h3>',
' <div class="link-list"></div>',
' <p class="no-link">To share this document you need first to ',
' <a href="#" class="action-publish-gist">publish it as a Gist</a>',
' in Markdown format.',
'</p>',
'<blockquote class="muted">',
'<b>NOTE:</b> You can open any URL within StackEdit using ',
'<a href="viewer.html?url=https://raw.github.com/benweet/stackedit/master/README.md"',
'title="Sharing example">viewer.html?url=...</a>',
'</blockquote>',
'</div>'].join("")
);
' </p>',
' <blockquote class="muted">',
' <b>NOTE:</b> You can open any URL within StackEdit using',
' <a href="viewer.html?url=https://raw.github.com/benweet/stackedit/master/README.md"',
' title="Sharing example">viewer.html?url=...</a>',
' </blockquote>',
'</div>'
].join(""));
};
var fileDesc = undefined;
var lineTemplate = [
'<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("");
' <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("");
var refreshDocumentSharing = function(fileDescParameter) {
if(fileDescParameter !== undefined && fileDescParameter !== fileDesc) {
return;

View File

@ -1,72 +1,78 @@
define([
"jquery",
"underscore"
], function($, _) {
"underscore",
"utils"
], function($, _, utils) {
var buttonStat = {
extensionId: "buttonStat",
extensionName: 'Button "Statistics"',
optional: true,
settingsBloc: '<p>Adds a "Document statistics" button in the navigation bar.</p>'
defaultConfig: {
name1: "Words",
value1: "\\S+",
name2: "Characters",
value2: "\\S",
name3: "Paragraphs",
value3: ".+",
},
settingsBloc: [
'<p>Adds a "Document statistics" button in the navigation bar.</p>',
'<p><div class="form-inline">',
' <label class="label-text" for="input-stat-name1">Title</label>',
' <input id="input-stat-name1" type="text" class="input-small">',
' <label class="label-text" for="input-stat-value1">RegExp</label>',
' <input id="input-stat-value1" type="text" class="span2">',
'</div></p>',
'<p><div class="form-inline">',
' <label class="label-text" for="input-stat-name2">Title</label>',
' <input id="input-stat-name2" type="text" class="input-small">',
' <label class="label-text" for="input-stat-value2">RegExp</label>',
' <input id="input-stat-value2" type="text" class="span2">',
'</div></p>',
'<p><div class="form-inline">',
' <label class="label-text" for="input-stat-name3">Title</label>',
' <input id="input-stat-name3" type="text" class="input-small">',
' <label class="label-text" for="input-stat-value3">RegExp</label>',
' <input id="input-stat-value3" type="text" class="span2">',
'</div></p>'].join("")
};
buttonStat.onLoadSettings = function() {
_.each(buttonStat.defaultConfig, function(value, key) {
utils.setInputValue("#input-stat-" + key, buttonStat.config[key]);
});
};
buttonStat.onSaveSettings = function(newConfig, event) {
_.each(buttonStat.defaultConfig, function(value, key) {
newConfig[key] = utils.getInputTextValue("#input-stat-" + key, event);
});
};
buttonStat.onCreateButton = function() {
return $([
'<button class="btn dropdown-toggle" data-toggle="dropdown" title="Document statistics">',
'<i class="icon-stat"></i>',
' <i class="icon-stat"></i>',
'</button>',
'<div id="statistics-container" class="dropdown-menu pull-right">',
'<div class="link-list"></div>',
'<p class="no-link">To share this document you need first to <a',
'href="#" class="action-publish-gist">publish it as a Gist</a> in',
'Markdown format.',
'</p>',
'<blockquote class="muted">',
'<b>NOTE:</b> You can open any URL within StackEdit using <a',
'href="viewer.html?url=https://raw.github.com/benweet/stackedit/master/README.md"',
'title="Sharing example">viewer.html?url=...</a>',
'</blockquote>',
'</div>'].join("")
);
' <h3 class="muted">Statistics</h3>',
' <div class="stat">',
' <div>' + buttonStat.config.name1 + ': <span id="span-stat-value1"></span></div>',
' <div>' + buttonStat.config.name2 + ': <span id="span-stat-value2"></span></div>',
' <div>' + buttonStat.config.name3 + ': <span id="span-stat-value3"></span></div>',
' </div>',
'</div>'
].join(""));
};
var fileDesc = undefined;
var lineTemplate = [
'<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("");
var refreshDocumentSharing = function(fileDescParameter) {
if(fileDescParameter !== undefined && fileDescParameter !== fileDesc) {
return;
}
var linkList = $("#link-container .link-list").empty();
$("#link-container .no-link").show();
var attributesList = _.values(fileDesc.publishLocations);
_.each(attributesList, function(attributes) {
if(attributes.sharingLink) {
var lineElement = $(_.template(lineTemplate, {
link: attributes.sharingLink
}));
lineElement.click(function(event) {
event.stopPropagation();
});
linkList.append(lineElement);
$("#link-container .no-link").hide();
}
});
buttonStat.onPreviewFinished = function() {
var text = $("#wmd-preview").text();
$("#span-stat-value1").text(text.match(new RegExp(buttonStat.config.value1, "g")).length);
$("#span-stat-value2").text(text.match(new RegExp(buttonStat.config.value2, "g")).length);
$("#span-stat-value3").text(text.match(new RegExp(buttonStat.config.value3, "g")).length);
};
buttonStat.onFileSelected = function(fileDescParameter) {
fileDesc = fileDescParameter;
refreshDocumentSharing(fileDescParameter);
};
buttonStat.onNewPublishSuccess = refreshDocumentSharing;
buttonStat.onPublishRemoved = refreshDocumentSharing;
return buttonStat;
});

View File

@ -34,9 +34,9 @@ define([
buttonSync.onCreateButton = function() {
button = $([
'<button class="btn" title="Synchronize all documents">',
'<i class="icon-refresh"></i>',
'</button>'].join("")
).click(function() {
' <i class="icon-refresh"></i>',
'</button>'
].join("")).click(function() {
if(!$(this).hasClass("disabled")) {
synchronizer.forceSync();
}

View File

@ -35,9 +35,7 @@ define([
liMap = {};
$("#file-selector li:not(.stick)").empty();
_.chain(
fileSystem
).sortBy(function(fileDesc) {
_.chain(fileSystem).sortBy(function(fileDesc) {
return fileDesc.title.toLowerCase();
}).each(function(fileDesc) {
var a = $('<a href="#">').html(composeTitle(fileDesc)).click(function() {
@ -67,6 +65,37 @@ define([
documentSelector.onNewPublishSuccess = buildSelector;
documentSelector.onPublishRemoved = buildSelector;
// Filter for search input in file selector
function filterFileSelector(filter) {
var liList = $("#file-selector li:not(.stick)");
liList.show();
if(filter) {
var words = filter.toLowerCase().split(/\s+/);
liList.each(function() {
var fileTitle = $(this).text().toLowerCase();
if(_.some(words, function(word) {
return fileTitle.indexOf(word) === -1;
})) {
$(this).hide();
}
});
}
}
documentSelector.onReady = function() {
$(".action-open-file").click(function() {
filterFileSelector();
_.defer(function() {
$("#file-search").val("").focus();
});
});
$("#file-search").keyup(function() {
filterFileSelector($(this).val());
}).click(function(event) {
event.stopPropagation();
});
};
return documentSelector;
});

View File

@ -17,4 +17,3 @@ define(function() {
return emailConverter;
});

View File

@ -17,11 +17,12 @@ define([
var fileDesc = undefined;
var lineTemplate = [
'<div class="input-prepend input-append">',
'<span class="add-on" title="<%= provider.providerName %>">',
'<i class="icon-<%= provider.providerId %>"></i>',
'</span>',
'<input class="span5" type="text" value="<%= publishDesc %>" disabled />',
'</div>'].join("");
' <span class="add-on" title="<%= provider.providerName %>">',
' <i class="icon-<%= provider.providerId %>"></i>',
' </span>',
' <input class="span5" type="text" value="<%= publishDesc %>" disabled />',
'</div>'
].join("");
var removeButtonTemplate = '<a class="btn" title="Remove this location"><i class="icon-trash"></i></a>';
var refreshDialog = function(fileDescParameter) {
if(fileDescParameter !== undefined && fileDescParameter !== fileDesc) {
@ -31,9 +32,10 @@ define([
var publishAttributesList = _.values(fileDesc.publishLocations);
$(".msg-no-publish, .msg-publish-list").addClass("hide");
var publishList = $("#manage-publish-list").empty();
if (publishAttributesList.length > 0) {
if(publishAttributesList.length > 0) {
$(".msg-publish-list").removeClass("hide");
} else {
}
else {
$(".msg-no-publish").removeClass("hide");
}
_.each(publishAttributesList, function(publishAttributes) {

View File

@ -17,11 +17,12 @@ define([
var fileDesc = undefined;
var lineTemplate = [
'<div class="input-prepend input-append">',
'<span class="add-on" title="<%= provider.providerName %>">',
'<i class="icon-<%= provider.providerId %>"></i>',
'</span>',
'<input class="span5" type="text" value="<%= syncDesc %>" disabled />',
'</div>'].join("");
' <span class="add-on" title="<%= provider.providerName %>">',
' <i class="icon-<%= provider.providerId %>"></i>',
' </span>',
' <input class="span5" type="text" value="<%= syncDesc %>" disabled />',
'</div>'
].join("");
var removeButtonTemplate = '<a class="btn" title="Remove this location"><i class="icon-trash"></i></a>';
var refreshDialog = function(fileDescParameter) {
if(fileDescParameter !== undefined && fileDescParameter !== fileDesc) {
@ -31,9 +32,10 @@ define([
var syncAttributesList = _.values(fileDesc.syncLocations);
$(".msg-no-sync, .msg-sync-list").addClass("hide");
var syncList = $("#manage-sync-list").empty();
if (syncAttributesList.length > 0) {
if(syncAttributesList.length > 0) {
$(".msg-sync-list").removeClass("hide");
} else {
}
else {
$(".msg-no-sync").removeClass("hide");
}
_.each(syncAttributesList, function(syncAttributes) {

View File

@ -13,12 +13,12 @@ define([
settingsBloc: [
'<p>Adds extra features to the original Markdown syntax.</p>',
'<div class="form-horizontal">',
'<div class="control-group">',
'<label class="control-label" for="input-markdownextra-prettify">Prettify syntax highlighting</label>',
'<div class="controls">',
'<input type="checkbox" id="input-markdownextra-prettify">',
'</div>',
'</div>',
' <div class="control-group">',
' <label class="control-label" for="input-markdownextra-prettify">Prettify syntax highlighting</label>',
' <div class="controls">',
' <input type="checkbox" id="input-markdownextra-prettify">',
' </div>',
' </div>',
'</div>'
].join("")
};

View File

@ -14,13 +14,13 @@ define([
settingsBloc: [
'<p>Shows notification messages in the bottom-right corner of the screen.</p>',
'<div class="form-horizontal">',
'<div class="control-group">',
'<label class="control-label" for="input-notifications-timeout">Timeout</label>',
'<div class="controls">',
'<input type="text" id="input-notifications-timeout" class="input-mini">',
'<span class="help-inline">ms</span>',
'</div>',
'</div>',
' <div class="control-group">',
' <label class="control-label" for="input-notifications-timeout">Timeout</label>',
' <div class="controls">',
' <input type="text" id="input-notifications-timeout" class="input-mini">',
' <span class="help-inline">ms</span>',
' </div>',
' </div>',
'</div>'
].join("")
};
@ -75,14 +75,14 @@ define([
notifications.onOfflineChanged = function(isOffline) {
if(isOffline === true) {
showMessage("You are offline.", "icon-exclamation-sign msg-offline", {
sticky : true,
close : function() {
sticky: true,
close: function() {
showMessage("You are back online!", "icon-signal");
}
});
} else {
$(".msg-offline").parents(".jGrowl-notification").trigger(
'jGrowl.beforeClose');
}
else {
$(".msg-offline").parents(".jGrowl-notification").trigger('jGrowl.beforeClose');
}
};

View File

@ -11,8 +11,8 @@ define([
settingsBloc: [
'<p>Binds together editor and preview scrollbars.</p>',
'<blockquote class="muted"><b>NOTE:</b> ',
'The mapping between Markdown and HTML is based on the position of the title elements (h1, h2, ...) in the page. ',
'Therefore, if your document does not contain any title, the mapping will be linear and consequently less accurate.',
' The mapping between Markdown and HTML is based on the position of the title elements (h1, h2, ...) in the page. ',
' Therefore, if your document does not contain any title, the mapping will be linear and consequently less accurate.',
'</bloquote>'
].join("")
};
@ -20,7 +20,7 @@ define([
var mdSectionList = [];
var htmlSectionList = [];
function pxToFloat(px) {
return parseFloat(px.substring(0, px.length-2));
return parseFloat(px.substring(0, px.length - 2));
}
var buildSections = _.debounce(function() {
@ -51,25 +51,23 @@ define([
}
// Create MD sections by finding title patterns (excluding gfm blocs)
var text = editorElt.val() + "\n\n";
text.replace(/^```.*\n[\s\S]*?\n```|(^.+[ \t]*\n=+[ \t]*\n+|^.+[ \t]*\n-+[ \t]*\n+|^\#{1,6}[ \t]*.+?[ \t]*\#*\n+)/gm,
function(match, title, matchOffset) {
text.replace(/^```.*\n[\s\S]*?\n```|(^.+[ \t]*\n=+[ \t]*\n+|^.+[ \t]*\n-+[ \t]*\n+|^\#{1,6}[ \t]*.+?[ \t]*\#*\n+)/gm, function(match, title, matchOffset) {
if(title) {
// We just found a title which means end of the previous section
// Exclude last \n of the section
var sectionText = undefined;
if(matchOffset > offset) {
sectionText = text.substring(offset, matchOffset-1);
sectionText = text.substring(offset, matchOffset - 1);
}
addMdSection(sectionText);
offset = matchOffset;
}
return "";
}
);
});
// Last section
// Consider wmd-input bottom padding and exclude \n\n previously added
padding += pxToFloat(editorElt.css('padding-bottom'));
addMdSection(text.substring(offset, text.length-2));
addMdSection(text.substring(offset, text.length - 2));
// Try to find corresponding sections in the preview
var previewElt = $("#wmd-preview");
@ -129,12 +127,17 @@ define([
var posInSection = (srcScrollTop - srcSection.startOffset) / srcSection.height;
var destSection = destSectionList[sectionIndex];
var destScrollTop = destSection.startOffset + destSection.height * posInSection;
destScrollTop = _.min([destScrollTop, destElt.prop('scrollHeight') - destElt.outerHeight()]);
destScrollTop = _.min([
destScrollTop,
destElt.prop('scrollHeight') - destElt.outerHeight()
]);
if(Math.abs(destScrollTop - lastDestScrollTop) < 5) {
// Skip the animation in case it's not necessary
return;
}
destElt.animate({scrollTop: destScrollTop}, 600, function() {
destElt.animate({
scrollTop: destScrollTop
}, 600, function() {
callback(destScrollTop);
});
}

View File

@ -77,7 +77,7 @@ define([
var id = element.prop("id") || utils.slugify(element.text());
var anchor = id;
var index = 0;
while(_.has(anchorList, anchor)) {
while (_.has(anchorList, anchor)) {
anchor = id + "-" + (++index);
}
anchorList[anchor] = true;
@ -87,17 +87,8 @@ define([
}
var elementList = [];
$("#wmd-preview > h1," +
"#wmd-preview > h2," +
"#wmd-preview > h3," +
"#wmd-preview > h4," +
"#wmd-preview > h5," +
"#wmd-preview > h6").each(function() {
elementList.push(new TocElement(
$(this).prop("tagName"),
createAnchor($(this)),
$(this).text()
));
$("#wmd-preview > h1," + "#wmd-preview > h2," + "#wmd-preview > h3," + "#wmd-preview > h4," + "#wmd-preview > h5," + "#wmd-preview > h6").each(function() {
elementList.push(new TocElement($(this).prop("tagName"), createAnchor($(this)), $(this).text()));
});
elementList = groupTags(elementList);
return '<div class="toc"><ul>' + elementList.toString() + '</ul></div>';
@ -115,4 +106,3 @@ define([
return toc;
});

View File

@ -10,10 +10,11 @@ define([
};
workingIndicator.onAsyncRunning = function(isRunning) {
if (isRunning === false) {
if(isRunning === false) {
$(".working-indicator").removeClass("show");
$("body").removeClass("working");
} else {
}
else {
$(".working-indicator").addClass("show");
$("body").addClass("working");
}

View File

@ -14,27 +14,28 @@ define([
// Defines a file descriptor in the file system (fileDesc objects)
function FileDescriptor(fileIndex, title, syncLocations, publishLocations) {
this.fileIndex = fileIndex;
this.title = title;
this._title = title;
this.__defineGetter__("title", function() {
return this._title;
});
this.__defineSetter__("title", function(title) {
this._title = title;
localStorage[this.fileIndex + ".title"] = title;
extensionMgr.onTitleChanged(this);
});
this.__defineGetter__("content", function() {
return localStorage[this.fileIndex + ".content"];
});
this.__defineSetter__("content", function(content) {
localStorage[this.fileIndex + ".content"] = content;
extensionMgr.onContentChanged(this);
});
this.syncLocations = syncLocations || {};
this.publishLocations = publishLocations || {};
}
FileDescriptor.prototype.getContent = function() {
return localStorage[this.fileIndex + ".content"];
};
FileDescriptor.prototype.setContent = function(content) {
localStorage[this.fileIndex + ".content"] = content;
extensionMgr.onContentChanged(this);
};
FileDescriptor.prototype.setTitle = function(title) {
this.title = title;
localStorage[this.fileIndex + ".title"] = title;
extensionMgr.onTitleChanged(this);
};
// Load file descriptors from localStorage
_.chain(
localStorage["file.list"].split(";")
).compact().each(function(fileIndex) {
_.chain(localStorage["file.list"].split(";")).compact().each(function(fileIndex) {
fileSystem[fileIndex] = new FileDescriptor(fileIndex, localStorage[fileIndex + ".title"]);
});
@ -63,7 +64,7 @@ define([
if(fileDesc === undefined) {
var fileSystemSize = _.size(fileSystem);
// If fileSystem empty create one file
if (fileSystemSize === 0) {
if(fileSystemSize === 0) {
fileDesc = fileMgr.createFile(WELCOME_DOCUMENT_TITLE, welcomeContent);
}
else {
@ -92,7 +93,7 @@ define([
}
// Recreate the editor
$("#wmd-input").val(fileDesc.getContent());
$("#wmd-input").val(fileDesc.content);
core.createEditor(function() {
// Callback to save content when textarea changes
fileMgr.saveFile();
@ -101,11 +102,11 @@ define([
fileMgr.createFile = function(title, content, syncLocations, isTemporary) {
content = content !== undefined ? content : settings.defaultContent;
if (!title) {
if(!title) {
// Create a file title
title = DEFAULT_FILE_TITLE;
var indicator = 2;
while(_.some(fileSystem, function(fileDesc) {
while (_.some(fileSystem, function(fileDesc) {
return fileDesc.title == title;
})) {
title = DEFAULT_FILE_TITLE + indicator++;
@ -117,7 +118,7 @@ define([
if(!isTemporary) {
do {
fileIndex = "file." + utils.randomString();
} while(_.has(fileSystem, fileIndex));
} while (_.has(fileSystem, fileIndex));
}
// syncIndex associations
@ -164,8 +165,7 @@ define([
// Remove the index from the file list
var fileIndex = fileDesc.fileIndex;
localStorage["file.list"] = localStorage["file.list"].replace(";"
+ fileIndex + ";", ";");
localStorage["file.list"] = localStorage["file.list"].replace(";" + fileIndex + ";", ";");
localStorage.removeItem(fileIndex + ".title");
localStorage.removeItem(fileIndex + ".content");
@ -178,9 +178,8 @@ define([
// Save current file in localStorage
fileMgr.saveFile = function() {
var content = $("#wmd-input").val();
var fileDesc = fileMgr.getCurrentFile();
fileDesc.setContent(content);
fileDesc.content = $("#wmd-input").val();
};
// Add a synchronized location to a file
@ -195,8 +194,7 @@ define([
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 + ";", ";");
localStorage[fileDesc.fileIndex + ".sync"] = localStorage[fileDesc.fileIndex + ".sync"].replace(";" + syncAttributes.syncIndex + ";", ";");
}
// Remove sync attributes
localStorage.removeItem(syncAttributes.syncIndex);
@ -239,8 +237,7 @@ define([
fileMgr.removePublish = function(publishAttributes, skipExtensions) {
var fileDesc = fileMgr.getFileFromPublishIndex(publishAttributes.publishIndex);
if(fileDesc !== undefined) {
localStorage[fileDesc.fileIndex + ".publish"] = localStorage[fileDesc.fileIndex + ".publish"].replace(";"
+ publishAttributes.publishIndex + ";", ";");
localStorage[fileDesc.fileIndex + ".publish"] = localStorage[fileDesc.fileIndex + ".publish"].replace(";" + publishAttributes.publishIndex + ";", ";");
}
// Remove publish attributes
localStorage.removeItem(publishAttributes.publishIndex);
@ -257,23 +254,6 @@ define([
});
};
// Filter for search input in file selector
function filterFileSelector(filter) {
var liList = $("#file-selector li:not(.stick)");
liList.show();
if(filter) {
var words = filter.toLowerCase().split(/\s+/);
liList.each(function() {
var fileTitle = $(this).text().toLowerCase();
if(_.some(words, function(word) {
return fileTitle.indexOf(word) === -1;
})) {
$(this).hide();
}
});
}
}
core.onReady(function() {
fileMgr.selectFile();
@ -305,8 +285,8 @@ define([
$("#file-title").show();
var title = $.trim(input.val());
var fileDesc = fileMgr.getCurrentFile();
if (title && title != fileDesc.title) {
fileDesc.setTitle(title);
if(title && title != fileDesc.title) {
fileDesc.title = title;
}
input.val(fileDesc.title);
$("#wmd-input").focus();
@ -314,25 +294,14 @@ define([
$("#file-title-input").blur(function() {
applyTitle($(this));
}).keyup(function(e) {
if (e.keyCode == 13) {
if(e.keyCode == 13) {
applyTitle($(this));
}
if (e.keyCode == 27) {
if(e.keyCode == 27) {
$(this).val("");
applyTitle($(this));
}
});
$(".action-open-file").click(function() {
filterFileSelector();
_.defer(function() {
$("#file-search").val("").focus();
});
});
$("#file-search").keyup(function() {
filterFileSelector($(this).val());
}).click(function(event) {
event.stopPropagation();
});
$(".action-open-stackedit").click(function() {
window.location.href = ".";
});

View File

@ -13,7 +13,9 @@ define([
providerId: PROVIDER_GDRIVE,
providerName: "Google Drive",
defaultPublishFormat: "template",
exportPreferencesInputIds: ["gdrive-parentid"]
exportPreferencesInputIds: [
"gdrive-parentid"
]
};
function createSyncIndex(id) {
@ -53,7 +55,8 @@ define([
extensionMgr.onSyncImportSuccess(fileDescList, gdriveProvider);
});
});
};
}
;
gdriveProvider.importFiles = function() {
googleHelper.picker(function(error, ids) {
@ -77,7 +80,7 @@ define([
gdriveProvider.exportFile = function(event, title, content, callback) {
var parentId = utils.getInputTextValue("#input-sync-export-gdrive-parentid");
googleHelper.upload(undefined, parentId, title, content, undefined, function(error, result) {
if (error) {
if(error) {
callback(error);
return;
}
@ -100,7 +103,7 @@ define([
return;
}
googleHelper.upload(id, undefined, title, content, undefined, function(error, result) {
if (error) {
if(error) {
callback(error);
return;
}
@ -132,7 +135,7 @@ define([
gdriveProvider.syncDown = function(callback) {
var lastChangeId = parseInt(localStorage[PROVIDER_GDRIVE + ".lastChangeId"]);
googleHelper.checkChanges(lastChangeId, function(error, changes, newChangeId) {
if (error) {
if(error) {
callback(error);
return;
}
@ -156,7 +159,7 @@ define([
}
});
googleHelper.downloadContent(interestingChanges, function(error, changes) {
if (error) {
if(error) {
callback(error);
return;
}
@ -164,19 +167,20 @@ define([
var syncAttributes = change.syncAttributes;
var syncIndex = syncAttributes.syncIndex;
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
// No file corresponding (file may have been deleted locally)
// No file corresponding (file may have been deleted
// locally)
if(fileDesc === undefined) {
return;
}
var localTitle = fileDesc.title;
// File deleted
if (change.deleted === true) {
if(change.deleted === true) {
extensionMgr.onError('"' + localTitle + '" has been removed from Google Drive.');
fileMgr.removeSync(syncAttributes);
return;
}
var localTitleChanged = syncAttributes.titleCRC != utils.crc32(localTitle);
var localContent = fileDesc.getContent();
var localContent = fileDesc.content;
var localContentChanged = syncAttributes.contentCRC != utils.crc32(localContent);
var file = change.file;
var remoteTitleCRC = utils.crc32(file.title);
@ -186,19 +190,18 @@ define([
var remoteContentChanged = syncAttributes.contentCRC != remoteContentCRC;
var fileContentChanged = localContent != file.content;
// Conflict detection
if ((fileTitleChanged === true && localTitleChanged === true && remoteTitleChanged === true)
|| (fileContentChanged === true && localContentChanged === true && remoteContentChanged === true)) {
if((fileTitleChanged === true && localTitleChanged === true && remoteTitleChanged === true) || (fileContentChanged === true && localContentChanged === true && remoteContentChanged === true)) {
fileMgr.createFile(localTitle + " (backup)", localContent);
extensionMgr.onMessage('Conflict detected on "' + localTitle + '". A backup has been created locally.');
}
// If file title changed
if(fileTitleChanged && remoteTitleChanged === true) {
fileDesc.setTitle(file.title);
fileDesc.title = file.title;
extensionMgr.onMessage('"' + localTitle + '" has been renamed to "' + file.title + '" on Google Drive.');
}
// If file content changed
if(fileContentChanged && remoteContentChanged === true) {
fileDesc.setContent(file.content);
fileDesc.content = file.content;
extensionMgr.onMessage('"' + file.title + '" has been updated from Google Drive.');
if(fileMgr.isCurrentFile(fileDesc)) {
fileMgr.selectFile(); // Refresh editor
@ -217,21 +220,14 @@ define([
};
gdriveProvider.publish = function(publishAttributes, title, content, callback) {
googleHelper.upload(
publishAttributes.id,
undefined,
publishAttributes.fileName || title,
content,
undefined,
function(error, result) {
googleHelper.upload(publishAttributes.id, undefined, publishAttributes.fileName || title, content, undefined, function(error, result) {
if(error) {
callback(error);
return;
}
publishAttributes.id = result.id;
callback();
}
);
});
};
gdriveProvider.newPublishAttributes = function(event) {
@ -251,9 +247,8 @@ define([
}
localStorage.removeItem(PROVIDER_GDRIVE + ".state");
state = JSON.parse(state);
if (state.action == "create") {
googleHelper.upload(undefined, state.folderId, GDRIVE_DEFAULT_FILE_TITLE,
"", undefined, function(error, file) {
if(state.action == "create") {
googleHelper.upload(undefined, state.folderId, GDRIVE_DEFAULT_FILE_TITLE, "", undefined, function(error, file) {
if(error) {
return;
}
@ -265,7 +260,7 @@ define([
extensionMgr.onMessage('"' + file.title + '" created successfully on Google Drive.');
});
}
else if (state.action == "open") {
else if(state.action == "open") {
var importIds = [];
_.each(state.ids, function(id) {
var syncIndex = createSyncIndex(id);

View File

@ -8,20 +8,21 @@ define([
var gistProvider = {
providerId: PROVIDER_GIST,
providerName: "Gist",
sharingAttributes: ["gistId", "filename"]
sharingAttributes: [
"gistId",
"filename"
]
};
gistProvider.publish = function(publishAttributes, title, content, callback) {
githubHelper.uploadGist(publishAttributes.gistId, publishAttributes.filename, publishAttributes.isPublic,
title, content, function(error, gistId) {
githubHelper.uploadGist(publishAttributes.gistId, publishAttributes.filename, publishAttributes.isPublic, title, content, function(error, gistId) {
if(error) {
callback(error);
return;
}
publishAttributes.gistId = gistId;
callback();
}
);
});
};
gistProvider.newPublishAttributes = function(event) {

View File

@ -19,13 +19,14 @@ define([
task.error(new Error("Operation not available in offline mode.|stopPublish"));
return;
}
if (connected === true) {
if(connected === true) {
task.chain();
return;
}
$.ajax({
url : "lib/github.js",
dataType : "script", timeout : AJAX_TIMEOUT
url: "lib/github.js",
dataType: "script",
timeout: AJAX_TIMEOUT
}).done(function() {
connected = true;
task.chain();
@ -44,7 +45,7 @@ define([
var authWindow = undefined;
var intervalId = undefined;
task.onRun(function() {
if (github !== undefined) {
if(github !== undefined) {
task.chain();
return;
}
@ -64,9 +65,7 @@ define([
var code = undefined;
function getCode() {
localStorage.removeItem("githubCode");
authWindow = utils.popupWindow(
'github-oauth-client.html?client_id=' + GITHUB_CLIENT_ID,
'stackedit-github-oauth', 960, 600);
authWindow = utils.popupWindow('github-oauth-client.html?client_id=' + GITHUB_CLIENT_ID, 'stackedit-github-oauth', 960, 600);
authWindow.focus();
intervalId = setInterval(function() {
if(authWindow.closed === true) {
@ -156,7 +155,9 @@ define([
task.onRun(function() {
var gist = github.getGist(gistId);
var files = {};
files[filename] = {content: content};
files[filename] = {
content: content
};
githubFunction = gist.update;
if(gistId === undefined) {
githubFunction = gist.create;
@ -223,21 +224,22 @@ define([
function handleError(error, task) {
var errorMsg = undefined;
if (error) {
if(error) {
logger.error(error);
// Try to analyze the error
if (typeof error === "string") {
if(typeof error === "string") {
errorMsg = error;
}
else {
errorMsg = "Could not publish on GitHub.";
if (error.error === 401 || error.error === 403) {
if(error.error === 401 || error.error === 403) {
github = undefined;
localStorage.removeItem("githubToken");
errorMsg = "Access to GitHub account is not authorized.";
task.retry(new Error(errorMsg), 1);
return;
} else if (error.error <= 0) {
}
else if(error.error <= 0) {
connected = false;
github = undefined;
core.setOffline();

View File

@ -9,13 +9,15 @@ define([
var githubProvider = {
providerId: PROVIDER_GITHUB,
providerName: "GitHub",
publishPreferencesInputIds: ["github-reponame", "github-branch"]
publishPreferencesInputIds: [
"github-reponame",
"github-branch"
]
};
githubProvider.publish = function(publishAttributes, title, content, callback) {
var commitMsg = settings.commitMsg;
githubHelper.upload(publishAttributes.repository, publishAttributes.branch,
publishAttributes.path, content, commitMsg, callback);
githubHelper.upload(publishAttributes.repository, publishAttributes.branch, publishAttributes.path, content, commitMsg, callback);
};
githubProvider.newPublishAttributes = function(event) {

View File

@ -19,7 +19,7 @@ define([
task.error(new Error("Operation not available in offline mode.|stopPublish"));
return;
}
if (connected === true) {
if(connected === true) {
task.chain();
return;
}
@ -28,8 +28,9 @@ define([
task.chain();
};
$.ajax({
url : "https://apis.google.com/js/client.js?onload=runDelayedFunction",
dataType : "script", timeout : AJAX_TIMEOUT
url: "https://apis.google.com/js/client.js?onload=runDelayedFunction",
dataType: "script",
timeout: AJAX_TIMEOUT
}).fail(function(jqXHR) {
var error = {
code: jqXHR.status,
@ -43,24 +44,28 @@ define([
// Try to authenticate with Oauth
function authenticate(task) {
task.onRun(function() {
if (authenticated === true) {
if(authenticated === true) {
task.chain();
return;
}
var immediate = true;
function localAuthenticate() {
if (immediate === false) {
if(immediate === false) {
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
// If not immediate we add time for user to enter his
// credentials
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
}
gapi.auth.authorize({ 'client_id' : GOOGLE_CLIENT_ID,
'scope' : GOOGLE_SCOPES, 'immediate' : immediate }, function(
authResult) {
gapi.auth.authorize({
'client_id': GOOGLE_CLIENT_ID,
'scope': GOOGLE_SCOPES,
'immediate': immediate
}, function(authResult) {
gapi.client.load('drive', 'v2', function() {
if (!authResult || authResult.error) {
// If immediate did not work retry without immediate flag
if (connected === true && immediate === true) {
if(!authResult || authResult.error) {
// If immediate did not work retry without immediate
// flag
if(connected === true && immediate === true) {
immediate = false;
task.chain(localAuthenticate);
return;
@ -89,43 +94,49 @@ define([
var delimiter = "\r\n--" + boundary + "\r\n";
var close_delim = "\r\n--" + boundary + "--";
var contentType = 'text/x-markdown';
var metadata = { title : title, mimeType : contentType };
if (parentId !== undefined) {
var metadata = {
title: title,
mimeType: contentType
};
if(parentId !== undefined) {
// Specify the directory
metadata.parents = [ { kind : 'drive#fileLink',
id : parentId } ];
metadata.parents = [
{
kind: 'drive#fileLink',
id: parentId
}
];
}
var path = '/upload/drive/v2/files';
var method = 'POST';
if (fileId !== undefined) {
if(fileId !== undefined) {
// If it's an update
path += "/" + fileId;
method = 'PUT';
}
var headers = { 'Content-Type' : 'multipart/mixed; boundary="'
+ boundary + '"', };
var headers = {
'Content-Type': 'multipart/mixed; boundary="' + boundary + '"',
};
if(etag !== undefined) {
// Sometimes we have error 412 from Google even with the correct etag
//headers["If-Match"] = etag;
// Sometimes we have error 412 from Google even with the correct
// etag
// headers["If-Match"] = etag;
}
var base64Data = utils.encodeBase64(content);
var multipartRequestBody = delimiter
+ 'Content-Type: application/json\r\n\r\n'
+ JSON.stringify(metadata) + delimiter + 'Content-Type: '
+ contentType + '\r\n'
+ 'Content-Transfer-Encoding: base64\r\n' + '\r\n'
+ base64Data + close_delim;
var multipartRequestBody = delimiter + 'Content-Type: application/json\r\n\r\n' + JSON.stringify(metadata) + delimiter + 'Content-Type: ' + contentType + '\r\n' + 'Content-Transfer-Encoding: base64\r\n' + '\r\n' + base64Data + close_delim;
var request = gapi.client
.request({
'path' : path,
'method' : method,
'params' : { 'uploadType' : 'multipart', },
'headers' : headers,
'body' : multipartRequestBody, });
var request = gapi.client.request({
'path': path,
'method': method,
'params': {
'uploadType': 'multipart',
},
'headers': headers,
'body': multipartRequestBody,
});
request.execute(function(response) {
if (response && response.id) {
if(response && response.id) {
// Upload success
result = response;
task.chain();
@ -166,16 +177,18 @@ define([
function retrievePageOfChanges() {
var request = undefined;
if(nextPageToken === undefined) {
request = gapi.client.drive.changes
.list({ 'startChangeId' : newChangeId + 1 });
request = gapi.client.drive.changes.list({
'startChangeId': newChangeId + 1
});
}
else {
request = gapi.client.drive.changes
.list({ 'pageToken' : nextPageToken });
request = gapi.client.drive.changes.list({
'pageToken': nextPageToken
});
}
request.execute(function(response) {
if (!response || !response.largestChangeId) {
if(!response || !response.largestChangeId) {
// Handle error
handleError(response.error, task);
return;
@ -183,10 +196,10 @@ define([
// Retrieve success
newChangeId = response.largestChangeId;
nextPageToken = response.nextPageToken;
if (response.items !== undefined) {
if(response.items !== undefined) {
changes = changes.concat(response.items);
}
if (nextPageToken !== undefined) {
if(nextPageToken !== undefined) {
task.chain(retrievePageOfChanges);
}
else {
@ -225,11 +238,13 @@ define([
headers.Authorization = "Bearer " + token.access_token;
}
$.ajax({
url : "https://www.googleapis.com/drive/v2/files/" + id,
headers : headers,
data : {key: GOOGLE_API_KEY},
dataType : "json",
timeout : AJAX_TIMEOUT
url: "https://www.googleapis.com/drive/v2/files/" + id,
headers: headers,
data: {
key: GOOGLE_API_KEY
},
dataType: "json",
timeout: AJAX_TIMEOUT
}).done(function(data, textStatus, jqXHR) {
result.push(data);
ids.shift();
@ -294,11 +309,13 @@ define([
headers.Authorization = "Bearer " + token.access_token;
}
$.ajax({
url : file.downloadUrl,
headers : headers,
data : {key: GOOGLE_API_KEY},
dataType : "text",
timeout : AJAX_TIMEOUT
url: file.downloadUrl,
headers: headers,
data: {
key: GOOGLE_API_KEY
},
dataType: "text",
timeout: AJAX_TIMEOUT
}).done(function(data, textStatus, jqXHR) {
file.content = data;
objects.shift();
@ -325,25 +342,26 @@ define([
function handleError(error, task) {
var errorMsg = undefined;
if (error) {
if(error) {
logger.error(error);
// Try to analyze the error
if (typeof error === "string") {
if(typeof error === "string") {
errorMsg = error;
}
else {
errorMsg = "Google error (" + error.code + ": "
+ error.message + ").";
if (error.code >= 500 && error.code < 600) {
errorMsg = "Google error (" + error.code + ": " + error.message + ").";
if(error.code >= 500 && error.code < 600) {
// Retry as described in Google's best practices
task.retry(new Error(errorMsg));
return;
} else if (error.code === 401 || error.code === 403) {
}
else if(error.code === 401 || error.code === 403) {
authenticated = false;
errorMsg = "Access to Google account is not authorized.";
task.retry(new Error(errorMsg), 1);
return;
} else if (error.code <= 0) {
}
else if(error.code <= 0) {
connected = false;
authenticated = false;
core.setOffline();
@ -357,17 +375,21 @@ define([
var pickerLoaded = false;
function loadPicker(task) {
task.onRun(function() {
if (pickerLoaded === true) {
if(pickerLoaded === true) {
task.chain();
return;
}
$.ajax({
url : "//www.google.com/jsapi",
data : {key: GOOGLE_API_KEY},
dataType : "script",
timeout : AJAX_TIMEOUT
url: "//www.google.com/jsapi",
data: {
key: GOOGLE_API_KEY
},
dataType: "script",
timeout: AJAX_TIMEOUT
}).done(function() {
google.load('picker', '1', {callback: task.chain});
google.load('picker', '1', {
callback: task.chain
});
pickerLoaded = true;
}).fail(function(jqXHR) {
var error = {
@ -405,10 +427,9 @@ define([
pickerBuilder.addView(view);
pickerBuilder.addView(new google.picker.DocsUploadView());
pickerBuilder.setCallback(function(data) {
if (data.action == google.picker.Action.PICKED ||
data.action == google.picker.Action.CANCEL) {
if(data.action == google.picker.Action.PICKED || data.action == google.picker.Action.CANCEL) {
if(data.action == google.picker.Action.PICKED) {
for(var i=0; i<data.docs.length; i++) {
for ( var i = 0; i < data.docs.length; i++) {
ids.push(data.docs[i].id);
}
}
@ -447,7 +468,9 @@ define([
var url = "https://www.googleapis.com/blogger/v3/blogs/" + blogId + "/posts/";
var data = {
kind: "blogger#post",
blog: { id: blogId },
blog: {
id: blogId
},
labels: labelList,
title: title,
content: content
@ -460,13 +483,13 @@ define([
type = "PUT";
}
$.ajax({
url : url,
url: url,
data: JSON.stringify(data),
headers : headers,
headers: headers,
type: type,
contentType: "application/json",
dataType : "json",
timeout : AJAX_TIMEOUT
dataType: "json",
timeout: AJAX_TIMEOUT
}).done(function(post, textStatus, jqXHR) {
postId = post.id;
task.chain();
@ -488,11 +511,13 @@ define([
return;
}
$.ajax({
url : "https://www.googleapis.com/blogger/v3/blogs/byurl",
data: { url: blogUrl },
headers : headers,
dataType : "json",
timeout : AJAX_TIMEOUT
url: "https://www.googleapis.com/blogger/v3/blogs/byurl",
data: {
url: blogUrl
},
headers: headers,
dataType: "json",
timeout: AJAX_TIMEOUT
}).done(function(blog, textStatus, jqXHR) {
blogId = blog.id;
task.chain(publish);

View File

@ -21,17 +21,16 @@ define([
var publisher = {};
// Create a map with providerId: providerModule
var providerMap = _.chain(
arguments
).map(function(argument) {
return argument && argument.providerId && [argument.providerId, argument];
var providerMap = _.chain(arguments).map(function(argument) {
return argument && argument.providerId && [
argument.providerId,
argument
];
}).compact().object().value();
// Retrieve publish locations from localStorage
_.each(fileSystem, 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;
@ -51,7 +50,8 @@ define([
documentHTML: $("#wmd-preview").html(),
publishAttributes: publishAttributes
});
} catch(e) {
}
catch (e) {
extensionMgr.onError(e);
throw e;
}
@ -79,7 +79,7 @@ define([
function publishLocation(callback, errorFlag) {
// No more publish location for this document
if (publishAttributesList.length === 0) {
if(publishAttributesList.length === 0) {
callback(errorFlag);
return;
}
@ -100,7 +100,7 @@ define([
return;
}
}
publishLocation(callback, errorFlag || error );
publishLocation(callback, errorFlag || error);
});
}
@ -130,7 +130,7 @@ define([
var publishIndex = undefined;
do {
publishIndex = "publish." + utils.randomString();
} while(_.has(localStorage, publishIndex));
} while (_.has(localStorage, publishIndex));
publishAttributes.publishIndex = publishIndex;
utils.storeAttributes(publishAttributes);
fileMgr.addPublish(fileDesc, publishAttributes);
@ -185,7 +185,8 @@ define([
}
});
// Store input values as preferences for next time we open the publish dialog
// Store input values as preferences for next time we open the publish
// dialog
var publishPreferences = {};
_.each(provider.publishPreferencesInputIds, function(inputId) {
publishPreferences[inputId] = $("#input-publish-" + inputId).val();
@ -196,9 +197,7 @@ 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;
@ -213,15 +212,9 @@ define([
var publishMenu = $("#publish-menu");
_.each(providerMap, function(provider) {
// Provider's publish button
publishMenu.append(
$("<li>").append(
$('<a href="#"><i class="icon-' + provider.providerId + '"></i> ' + provider.providerName + '</a>')
.click(function() {
publishMenu.append($("<li>").append($('<a href="#"><i class="icon-' + provider.providerId + '"></i> ' + provider.providerName + '</a>').click(function() {
initNewLocation(provider);
}
)
)
);
})));
// Action links (if any)
$(".action-publish-" + provider.providerId).click(function() {
initNewLocation(provider);

View File

@ -4,24 +4,25 @@ define([
], function(_) {
var settings = {
layoutOrientation : "horizontal",
lazyRendering : true,
editorFontSize : 14,
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 : [
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,
'</html>'
].join(""),
sshProxy: SSH_PROXY_URL,
extensionSettings: {}
};
if (_.has(localStorage, "settings")) {
if(_.has(localStorage, "settings")) {
_.extend(settings, JSON.parse(localStorage.settings));
}

View File

@ -14,17 +14,20 @@ define([
var sharing = {};
// Create a map with providerId: providerModule
var providerMap = _.chain(
arguments
).map(function(argument) {
return argument && argument.providerId && [argument.providerId, argument];
var providerMap = _.chain(arguments).map(function(argument) {
return argument && argument.providerId && [
argument.providerId,
argument
];
}).compact().object().value();
// Used to populate the "Sharing" dropdown box
var lineTemplate = ['<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("");
var lineTemplate = [
'<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("");
sharing.refreshDocumentSharing = function(attributesList) {
var linkList = $("#link-container .link-list").empty();
$("#link-container .no-link").show();
@ -44,7 +47,8 @@ define([
sharing.createLink = function(attributes, callback) {
var provider = providerMap[attributes.provider];
// Don't create link if link already exists or provider is not compatible for sharing
// Don't create link if link already exists or provider is not
// compatible for sharing
if(attributes.sharingLink !== undefined || provider === undefined
// Or document is not published in markdown format
|| attributes.format != "markdown") {
@ -58,7 +62,11 @@ define([
task.chain();
return;
}
var url = [MAIN_URL, 'viewer.html?provider=', attributes.provider];
var url = [
MAIN_URL,
'viewer.html?provider=',
attributes.provider
];
_.each(provider.sharingAttributes, function(attributeName) {
url.push('&');
url.push(attributeName);
@ -66,14 +74,10 @@ define([
url.push(encodeURIComponent(attributes[attributeName]));
});
url = url.join("");
$.getJSON(
"https://api-ssl.bitly.com/v3/shorten",
{
$.getJSON("https://api-ssl.bitly.com/v3/shorten", {
"access_token": BITLY_ACCESS_TOKEN,
"longUrl": url
},
function(response)
{
}, function(response) {
if(response.data) {
shortUrl = response.data.url;
attributes.sharingLink = shortUrl;
@ -83,8 +87,7 @@ define([
attributes.sharingLink = url;
}
task.chain();
}
);
});
});
function onFinish() {
callback();

View File

@ -32,11 +32,11 @@ define([
content: content
};
$.ajax({
url : url,
url: url,
data: data,
type: "POST",
dataType : "json",
timeout : AJAX_TIMEOUT
dataType: "json",
timeout: AJAX_TIMEOUT
}).done(function(response, textStatus, jqXHR) {
if(response.error === undefined) {
task.chain();
@ -62,15 +62,15 @@ define([
function handleError(error, task) {
var errorMsg = undefined;
if (error) {
if(error) {
logger.error(error);
// Try to analyze the error
if (typeof error === "string") {
if(typeof error === "string") {
errorMsg = "SSH error: " + error + ".";
}
else {
errorMsg = "Could not publish on SSH server.";
if (error.code <= 0) {
if(error.code <= 0) {
core.setOffline();
errorMsg = "|stopPublish";
}

View File

@ -6,39 +6,28 @@ define([
var PROVIDER_SSH = "ssh";
var sshProvider = {
providerId : PROVIDER_SSH,
providerName : "SSH server",
publishPreferencesInputIds: ["ssh-host", "ssh-port", "ssh-username", "ssh-password"]
providerId: PROVIDER_SSH,
providerName: "SSH server",
publishPreferencesInputIds: [
"ssh-host",
"ssh-port",
"ssh-username",
"ssh-password"
]
};
sshProvider.publish = function(publishAttributes, title, content, callback) {
sshHelper.upload(
publishAttributes.host,
publishAttributes.port,
publishAttributes.username,
publishAttributes.password,
publishAttributes.path,
title,
content,
callback);
sshHelper.upload(publishAttributes.host, publishAttributes.port, publishAttributes.username, publishAttributes.password, publishAttributes.path, title, content, callback);
};
sshProvider.newPublishAttributes = function(event) {
var publishAttributes = {};
publishAttributes.host = utils
.getInputTextValue(
"#input-publish-ssh-host",
event,
/^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/);
publishAttributes.port = utils.getInputIntValue(
"#input-publish-ssh-port", undefined, 0);
publishAttributes.username = utils.getInputTextValue(
"#input-publish-ssh-username", event);
publishAttributes.password = utils.getInputTextValue(
"#input-publish-ssh-password", event);
publishAttributes.path = utils.getInputTextValue(
"#input-publish-file-path", event);
if (event.isPropagationStopped()) {
publishAttributes.host = utils.getInputTextValue("#input-publish-ssh-host", event, /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/);
publishAttributes.port = utils.getInputIntValue("#input-publish-ssh-port", undefined, 0);
publishAttributes.username = utils.getInputTextValue("#input-publish-ssh-username", event);
publishAttributes.password = utils.getInputTextValue("#input-publish-ssh-password", event);
publishAttributes.path = utils.getInputTextValue("#input-publish-file-path", event);
if(event.isPropagationStopped()) {
return undefined;
}
return publishAttributes;

View File

@ -4,7 +4,7 @@ define([
], function(_) {
// Create the file system if not exist
if (localStorage["file.list"] === undefined) {
if(localStorage["file.list"] === undefined) {
localStorage["file.list"] = ";";
}
var fileIndexList = _.compact(localStorage["file.list"].split(";"));
@ -55,14 +55,14 @@ define([
var syncIndexList = _.compact(localStorage[fileIndex + ".sync"].split(";"));
_.each(syncIndexList, function(syncIndex) {
var syncAttributes = {};
if (syncIndex.indexOf(SYNC_PROVIDER_GDRIVE) === 0) {
if(syncIndex.indexOf(SYNC_PROVIDER_GDRIVE) === 0) {
syncAttributes.provider = PROVIDER_GDRIVE;
syncAttributes.id = syncIndex.substring(SYNC_PROVIDER_GDRIVE.length);
syncAttributes.etag = localStorage[syncIndex + ".etag"];
syncAttributes.contentCRC = localStorage[syncIndex + ".contentCRC"];
syncAttributes.titleCRC = localStorage[syncIndex + ".titleCRC"];
}
else if (syncIndex.indexOf(SYNC_PROVIDER_DROPBOX) === 0) {
else if(syncIndex.indexOf(SYNC_PROVIDER_DROPBOX) === 0) {
syncAttributes.provider = PROVIDER_DROPBOX;
syncAttributes.path = decodeURIComponent(syncIndex.substring(SYNC_PROVIDER_DROPBOX.length));
syncAttributes.version = localStorage[syncIndex + ".version"];
@ -85,8 +85,7 @@ define([
localStorage.removeItem(fileIndex + ".title");
localStorage.removeItem(fileIndex + ".publish");
localStorage.removeItem(fileIndex + ".content");
localStorage["file.list"] = localStorage["file.list"].replace(";"
+ fileIndex + ";", ";");
localStorage["file.list"] = localStorage["file.list"].replace(";" + fileIndex + ";", ";");
}
});
version = "v3";
@ -95,9 +94,7 @@ define([
// Upgrade from v3 to v4
if(version == "v3") {
var currentFileIndex = localStorage["file.current"];
if(currentFileIndex !== undefined &&
localStorage["file.list"].indexOf(";" + currentFileIndex + ";") === -1)
{
if(currentFileIndex !== undefined && localStorage["file.list"].indexOf(";" + currentFileIndex + ";") === -1) {
localStorage.removeItem("file.current");
}
version = "v4";

View File

@ -13,17 +13,16 @@ define([
var synchronizer = {};
// Create a map with providerId: providerModule
var providerMap = _.chain(
arguments
).map(function(argument) {
return argument && argument.providerId && [argument.providerId, argument];
var providerMap = _.chain(arguments).map(function(argument) {
return argument && argument.providerId && [
argument.providerId,
argument
];
}).compact().object().value();
// Retrieve sync locations from localStorage
_.each(fileSystem, function(fileDesc) {
_.chain(
localStorage[fileDesc.fileIndex + ".sync"].split(";")
).compact().each(function(syncIndex) {
_.chain(localStorage[fileDesc.fileIndex + ".sync"].split(";")).compact().each(function(syncIndex) {
var syncAttributes = JSON.parse(localStorage[syncIndex]);
// Store syncIndex
syncAttributes.syncIndex = syncIndex;
@ -48,7 +47,7 @@ define([
function locationUp(callback) {
// No more synchronized location for this document
if (uploadSyncAttributesList.length === 0) {
if(uploadSyncAttributesList.length === 0) {
fileUp(callback);
return;
}
@ -56,13 +55,7 @@ define([
// Dequeue a synchronized location
var syncAttributes = uploadSyncAttributesList.pop();
// Use the specified provider to perform the upload
syncAttributes.provider.syncUp(
uploadContent,
uploadContentCRC,
uploadTitle,
uploadTitleCRC,
syncAttributes,
function(error, uploadFlag) {
syncAttributes.provider.syncUp(uploadContent, uploadContentCRC, uploadTitle, uploadTitleCRC, syncAttributes, function(error, uploadFlag) {
if(uploadFlag === true) {
// If uploadFlag is true, request another upload cycle
uploadCycle = true;
@ -76,8 +69,7 @@ define([
utils.storeAttributes(syncAttributes);
}
locationUp(callback);
}
);
});
}
// Recursive function to upload multiple files
@ -85,7 +77,7 @@ define([
function fileUp(callback) {
// No more fileDesc to synchronize
if (uploadFileList.length === 0) {
if(uploadFileList.length === 0) {
syncUp(callback);
return;
}
@ -99,7 +91,7 @@ define([
}
// Get document title/content
uploadContent = fileDesc.getContent();
uploadContent = fileDesc.content;
uploadContentCRC = utils.crc32(uploadContent);
uploadTitle = fileDesc.title;
uploadTitleCRC = utils.crc32(uploadTitle);
@ -149,14 +141,15 @@ define([
function syncDown(callback) {
providerList = _.values(providerMap);
providerDown(callback);
};
}
;
// Main entry point for synchronization
var syncRunning = false;
var lastSync = 0;
synchronizer.sync = function() {
// If sync is already running or timeout is not reached or offline
if (syncRunning || lastSync + SYNC_PERIOD > utils.currentTime || core.isOffline) {
if(syncRunning || lastSync + SYNC_PERIOD > utils.currentTime || core.isOffline) {
return;
}
syncRunning = true;
@ -226,14 +219,15 @@ define([
// Perform the provider's export
var fileDesc = fileMgr.getCurrentFile();
provider.exportFile(event, fileDesc.title, fileDesc.getContent(), function(error, syncAttributes) {
provider.exportFile(event, fileDesc.title, fileDesc.content, function(error, syncAttributes) {
if(error) {
return;
}
fileMgr.addSync(fileDesc, syncAttributes);
});
// Store input values as preferences for next time we open the export dialog
// Store input values as preferences for next time we open the
// export dialog
var exportPreferences = {};
_.each(provider.exportPreferencesInputIds, function(inputId) {
exportPreferences[inputId] = $("#input-sync-export-" + inputId).val();
@ -243,7 +237,7 @@ define([
// Provider's manual export button
$(".action-sync-manual-" + provider.providerId).click(function(event) {
var fileDesc = fileMgr.getCurrentFile();
provider.exportManual(event, fileDesc.title, fileDesc.getContent(), function(error, syncAttributes) {
provider.exportManual(event, fileDesc.title, fileDesc.content, function(error, syncAttributes) {
if(error) {
return;
}

View File

@ -26,7 +26,7 @@ define([
var authWindow = undefined;
var intervalId = undefined;
task.onRun(function() {
if (oauthParams !== undefined) {
if(oauthParams !== undefined) {
task.chain();
return;
}
@ -54,9 +54,7 @@ define([
}
function getVerifier() {
localStorage.removeItem("tumblrVerifier");
authWindow = utils.popupWindow(
'tumblr-oauth-client.html?oauth_token=' + oauth_object.oauth_token,
'stackedit-tumblr-oauth', 800, 600);
authWindow = utils.popupWindow('tumblr-oauth-client.html?oauth_token=' + oauth_object.oauth_token, 'stackedit-tumblr-oauth', 800, 600);
authWindow.focus();
intervalId = setInterval(function() {
if(authWindow.closed === true) {
@ -111,11 +109,11 @@ define([
content: content
}, oauthParams);
$.ajax({
url : TUMBLR_PROXY_URL + "post",
url: TUMBLR_PROXY_URL + "post",
data: data,
type: "POST",
dataType : "json",
timeout : AJAX_TIMEOUT
dataType: "json",
timeout: AJAX_TIMEOUT
}).done(function(post, textStatus, jqXHR) {
postId = post.id;
task.chain();
@ -142,21 +140,22 @@ define([
function handleError(error, task) {
var errorMsg = undefined;
if (error) {
if(error) {
logger.error(error);
// Try to analyze the error
if (typeof error === "string") {
if(typeof error === "string") {
errorMsg = error;
}
else {
errorMsg = "Could not publish on Tumblr.";
if (error.code === 401 || error.code === 403) {
if(error.code === 401 || error.code === 403) {
oauthParams = undefined;
localStorage.removeItem("tumblrOauthParams");
errorMsg = "Access to Tumblr account is not authorized.";
task.retry(new Error(errorMsg), 1);
return;
} else if (error.code <= 0) {
}
else if(error.code <= 0) {
core.setOffline();
errorMsg = "|stopPublish";
}

View File

@ -8,35 +8,25 @@ define([
var tumblrProvider = {
providerId: PROVIDER_TUMBLR,
providerName: "Tumblr",
publishPreferencesInputIds: ["tumblr-hostname"]
publishPreferencesInputIds: [
"tumblr-hostname"
]
};
tumblrProvider.publish = function(publishAttributes, title, content, callback) {
tumblrHelper.upload(
publishAttributes.blogHostname,
publishAttributes.postId,
publishAttributes.tags,
publishAttributes.format == "markdown" ? "markdown" : "html",
title,
content,
function(error, postId) {
tumblrHelper.upload(publishAttributes.blogHostname, publishAttributes.postId, publishAttributes.tags, publishAttributes.format == "markdown" ? "markdown" : "html", title, content, function(error, postId) {
if(error) {
callback(error);
return;
}
publishAttributes.postId = postId;
callback();
}
);
});
};
tumblrProvider.newPublishAttributes = function(event) {
var publishAttributes = {};
publishAttributes.blogHostname = utils
.getInputTextValue(
"#input-publish-tumblr-hostname",
event,
/^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/);
publishAttributes.blogHostname = utils.getInputTextValue("#input-publish-tumblr-hostname", event, /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/);
publishAttributes.postId = utils.getInputTextValue("#input-publish-postid");
publishAttributes.tags = utils.getInputTextValue("#input-publish-tags");
if(event.isPropagationStopped()) {

View File

@ -11,7 +11,8 @@ define([
var regex = new RegExp(name + "=(.+?)(&|$)");
try {
return decodeURIComponent(regex.exec(location.search)[1]);
} catch (e) {
}
catch (e) {
return undefined;
}
};
@ -48,14 +49,13 @@ define([
utils.getInputTextValue = function(element, event, validationRegex) {
element = jqElt(element);
var value = element.val();
if (value === undefined) {
if(value === undefined) {
inputError(element, event);
return undefined;
}
// trim
value = utils.trim(value);
if((value.length === 0)
|| (validationRegex !== undefined && !value.match(validationRegex))) {
if((value.length === 0) || (validationRegex !== undefined && !value.match(validationRegex))) {
inputError(element, event);
return undefined;
}
@ -70,9 +70,7 @@ define([
return undefined;
}
value = parseInt(value);
if((value === NaN)
|| (min !== undefined && value < min)
|| (max !== undefined && value > max)) {
if((value === NaN) || (min !== undefined && value < min) || (max !== undefined && value > max)) {
inputError(element, event);
return undefined;
}
@ -113,8 +111,7 @@ define([
// Slug function
utils.slugify = function(text) {
return text.toLowerCase()
.replace(/\s+/g, '-') // Replace spaces with -
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
@ -135,9 +132,66 @@ define([
return url;
};
// 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
].join(""));
};
// 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 and store it in the fileStorage
utils.storeAttributes = function(attributes) {
var storeIndex = attributes.syncIndex || attributes.publishIndex;
// Don't store sync/publish index
attributes = _.omit(attributes, "syncIndex", "publishIndex");
// Store providerId instead of provider
attributes.provider = attributes.provider.providerId;
localStorage[storeIndex] = JSON.stringify(attributes);
};
// Base64 conversion
utils.encodeBase64 = function(str) {
if (str.length === 0) {
if(str.length === 0) {
return "";
}
@ -151,9 +205,10 @@ define([
char = str[offset];
offset += 1;
if ('%' !== char) {
if('%' !== char) {
bytes.push(char.charCodeAt(0));
} else {
}
else {
char = str[offset] + str[offset + 1];
bytes.push(parseInt(char, 16));
offset += 2;
@ -170,7 +225,7 @@ define([
var imax = bytes.length - bytes.length % 3;
for (i = 0; i < imax; i += 3) {
b10 = (bytes[i] << 16) | (bytes[i+1] << 8) | bytes[i+2];
b10 = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
x.push(alpha.charAt(b10 >> 18));
x.push(alpha.charAt((b10 >> 12) & 0x3F));
x.push(alpha.charAt((b10 >> 6) & 0x3f));
@ -179,70 +234,275 @@ define([
switch (bytes.length - imax) {
case 1:
b10 = bytes[i] << 16;
x.push(alpha.charAt(b10 >> 18) + alpha.charAt((b10 >> 12) & 0x3F) +
padchar + padchar);
x.push(alpha.charAt(b10 >> 18) + alpha.charAt((b10 >> 12) & 0x3F) + padchar + padchar);
break;
case 2:
b10 = (bytes[i] << 16) | (bytes[i+1] << 8);
x.push(alpha.charAt(b10 >> 18) + alpha.charAt((b10 >> 12) & 0x3F) +
alpha.charAt((b10 >> 6) & 0x3f) + padchar);
b10 = (bytes[i] << 16) | (bytes[i + 1] << 8);
x.push(alpha.charAt(b10 >> 18) + alpha.charAt((b10 >> 12) & 0x3F) + alpha.charAt((b10 >> 6) & 0x3f) + padchar);
break;
}
return x.join('');
};
// CRC32 algorithm
var mHash = [ 0, 1996959894, 3993919788, 2567524794, 124634137,
1886057615, 3915621685, 2657392035, 249268274, 2044508324,
3772115230, 2547177864, 162941995, 2125561021, 3887607047,
2428444049, 498536548, 1789927666, 4089016648, 2227061214,
450548861, 1843258603, 4107580753, 2211677639, 325883990,
1684777152, 4251122042, 2321926636, 335633487, 1661365465,
4195302755, 2366115317, 997073096, 1281953886, 3579855332,
2724688242, 1006888145, 1258607687, 3524101629, 2768942443,
901097722, 1119000684, 3686517206, 2898065728, 853044451,
1172266101, 3705015759, 2882616665, 651767980, 1373503546,
3369554304, 3218104598, 565507253, 1454621731, 3485111705,
3099436303, 671266974, 1594198024, 3322730930, 2970347812,
795835527, 1483230225, 3244367275, 3060149565, 1994146192,
31158534, 2563907772, 4023717930, 1907459465, 112637215,
2680153253, 3904427059, 2013776290, 251722036, 2517215374,
3775830040, 2137656763, 141376813, 2439277719, 3865271297,
1802195444, 476864866, 2238001368, 4066508878, 1812370925,
453092731, 2181625025, 4111451223, 1706088902, 314042704,
2344532202, 4240017532, 1658658271, 366619977, 2362670323,
4224994405, 1303535960, 984961486, 2747007092, 3569037538,
1256170817, 1037604311, 2765210733, 3554079995, 1131014506,
879679996, 2909243462, 3663771856, 1141124467, 855842277,
2852801631, 3708648649, 1342533948, 654459306, 3188396048,
3373015174, 1466479909, 544179635, 3110523913, 3462522015,
1591671054, 702138776, 2966460450, 3352799412, 1504918807,
783551873, 3082640443, 3233442989, 3988292384, 2596254646,
62317068, 1957810842, 3939845945, 2647816111, 81470997, 1943803523,
3814918930, 2489596804, 225274430, 2053790376, 3826175755,
2466906013, 167816743, 2097651377, 4027552580, 2265490386,
503444072, 1762050814, 4150417245, 2154129355, 426522225,
1852507879, 4275313526, 2312317920, 282753626, 1742555852,
4189708143, 2394877945, 397917763, 1622183637, 3604390888,
2714866558, 953729732, 1340076626, 3518719985, 2797360999,
1068828381, 1219638859, 3624741850, 2936675148, 906185462,
1090812512, 3747672003, 2825379669, 829329135, 1181335161,
3412177804, 3160834842, 628085408, 1382605366, 3423369109,
3138078467, 570562233, 1426400815, 3317316542, 2998733608,
733239954, 1555261956, 3268935591, 3050360625, 752459403,
1541320221, 2607071920, 3965973030, 1969922972, 40735498,
2617837225, 3943577151, 1913087877, 83908371, 2512341634,
3803740692, 2075208622, 213261112, 2463272603, 3855990285,
2094854071, 198958881, 2262029012, 4057260610, 1759359992,
534414190, 2176718541, 4139329115, 1873836001, 414664567,
2282248934, 4279200368, 1711684554, 285281116, 2405801727,
4167216745, 1634467795, 376229701, 2685067896, 3608007406,
1308918612, 956543938, 2808555105, 3495958263, 1231636301,
1047427035, 2932959818, 3654703836, 1088359270, 936918000,
2847714899, 3736837829, 1202900863, 817233897, 3183342108,
3401237130, 1404277552, 615818150, 3134207493, 3453421203,
1423857449, 601450431, 3009837614, 3294710456, 1567103746,
711928724, 3020668471, 3272380065, 1510334235, 755167117 ];
var mHash = [
0,
1996959894,
3993919788,
2567524794,
124634137,
1886057615,
3915621685,
2657392035,
249268274,
2044508324,
3772115230,
2547177864,
162941995,
2125561021,
3887607047,
2428444049,
498536548,
1789927666,
4089016648,
2227061214,
450548861,
1843258603,
4107580753,
2211677639,
325883990,
1684777152,
4251122042,
2321926636,
335633487,
1661365465,
4195302755,
2366115317,
997073096,
1281953886,
3579855332,
2724688242,
1006888145,
1258607687,
3524101629,
2768942443,
901097722,
1119000684,
3686517206,
2898065728,
853044451,
1172266101,
3705015759,
2882616665,
651767980,
1373503546,
3369554304,
3218104598,
565507253,
1454621731,
3485111705,
3099436303,
671266974,
1594198024,
3322730930,
2970347812,
795835527,
1483230225,
3244367275,
3060149565,
1994146192,
31158534,
2563907772,
4023717930,
1907459465,
112637215,
2680153253,
3904427059,
2013776290,
251722036,
2517215374,
3775830040,
2137656763,
141376813,
2439277719,
3865271297,
1802195444,
476864866,
2238001368,
4066508878,
1812370925,
453092731,
2181625025,
4111451223,
1706088902,
314042704,
2344532202,
4240017532,
1658658271,
366619977,
2362670323,
4224994405,
1303535960,
984961486,
2747007092,
3569037538,
1256170817,
1037604311,
2765210733,
3554079995,
1131014506,
879679996,
2909243462,
3663771856,
1141124467,
855842277,
2852801631,
3708648649,
1342533948,
654459306,
3188396048,
3373015174,
1466479909,
544179635,
3110523913,
3462522015,
1591671054,
702138776,
2966460450,
3352799412,
1504918807,
783551873,
3082640443,
3233442989,
3988292384,
2596254646,
62317068,
1957810842,
3939845945,
2647816111,
81470997,
1943803523,
3814918930,
2489596804,
225274430,
2053790376,
3826175755,
2466906013,
167816743,
2097651377,
4027552580,
2265490386,
503444072,
1762050814,
4150417245,
2154129355,
426522225,
1852507879,
4275313526,
2312317920,
282753626,
1742555852,
4189708143,
2394877945,
397917763,
1622183637,
3604390888,
2714866558,
953729732,
1340076626,
3518719985,
2797360999,
1068828381,
1219638859,
3624741850,
2936675148,
906185462,
1090812512,
3747672003,
2825379669,
829329135,
1181335161,
3412177804,
3160834842,
628085408,
1382605366,
3423369109,
3138078467,
570562233,
1426400815,
3317316542,
2998733608,
733239954,
1555261956,
3268935591,
3050360625,
752459403,
1541320221,
2607071920,
3965973030,
1969922972,
40735498,
2617837225,
3943577151,
1913087877,
83908371,
2512341634,
3803740692,
2075208622,
213261112,
2463272603,
3855990285,
2094854071,
198958881,
2262029012,
4057260610,
1759359992,
534414190,
2176718541,
4139329115,
1873836001,
414664567,
2282248934,
4279200368,
1711684554,
285281116,
2405801727,
4167216745,
1634467795,
376229701,
2685067896,
3608007406,
1308918612,
956543938,
2808555105,
3495958263,
1231636301,
1047427035,
2932959818,
3654703836,
1088359270,
936918000,
2847714899,
3736837829,
1202900863,
817233897,
3183342108,
3401237130,
1404277552,
615818150,
3134207493,
3453421203,
1423857449,
601450431,
3009837614,
3294710456,
1567103746,
711928724,
3020668471,
3272380065,
1510334235,
755167117
];
utils.crc32 = function(str) {
var n = 0, crc = -1;
for ( var i = 0; i < str.length; i++) {
@ -250,64 +510,11 @@ define([
crc = (crc >>> 8) ^ mHash[n];
}
crc = crc ^ (-1);
if (crc < 0) {
if(crc < 0) {
crc = 0xFFFFFFFF + crc + 1;
}
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 and store it in the fileStorage
utils.storeAttributes = function(attributes) {
var storeIndex = attributes.syncIndex || attributes.publishIndex;
// Don't store sync/publish index
attributes = _.omit(attributes, "syncIndex", "publishIndex");
// Store providerId instead of provider
attributes.provider = attributes.provider.providerId;
localStorage[storeIndex] = JSON.stringify(attributes);
};
return utils;
});

View File

@ -38,9 +38,7 @@ define([
var code = undefined;
function getCode() {
localStorage.removeItem("wordpressCode");
authWindow = utils.popupWindow(
'wordpress-oauth-client.html?client_id=' + WORDPRESS_CLIENT_ID,
'stackedit-wordpress-oauth', 960, 600);
authWindow = utils.popupWindow('wordpress-oauth-client.html?client_id=' + WORDPRESS_CLIENT_ID, 'stackedit-wordpress-oauth', 960, 600);
authWindow.focus();
intervalId = setInterval(function() {
if(authWindow.closed === true) {
@ -96,11 +94,11 @@ define([
content: content
};
$.ajax({
url : url,
url: url,
data: data,
type: "POST",
dataType : "json",
timeout : AJAX_TIMEOUT
dataType: "json",
timeout: AJAX_TIMEOUT
}).done(function(response, textStatus, jqXHR) {
if(response.body.ID) {
postId = response.body.ID;
@ -116,7 +114,7 @@ define([
if(error.message == "unknown_blog") {
error = 'Site "' + site + '" not found on WordPress.|removePublish';
}
else if(error.message == "unknown_post"){
else if(error.message == "unknown_post") {
error = 'Post ' + postId + ' not found on WordPress.|removePublish';
}
}
@ -140,20 +138,21 @@ define([
function handleError(error, task) {
var errorMsg = undefined;
if (error) {
if(error) {
logger.error(error);
// Try to analyze the error
if (typeof error === "string") {
if(typeof error === "string") {
errorMsg = error;
}
else {
errorMsg = "Could not publish on WordPress.";
if ((error.code === 400 && error.message == "invalid_token") || error.code === 401 || error.code === 403) {
if((error.code === 400 && error.message == "invalid_token") || error.code === 401 || error.code === 403) {
localStorage.removeItem("wordpressToken");
errorMsg = "Access to WordPress account is not authorized.";
task.retry(new Error(errorMsg), 1);
return;
} else if (error.code <= 0) {
}
else if(error.code <= 0) {
core.setOffline();
errorMsg = "|stopPublish";
}

View File

@ -9,34 +9,25 @@ define([
providerId: PROVIDER_WORDPRESS,
providerName: "WordPress",
defaultPublishFormat: "html",
publishPreferencesInputIds: ["wordpress-site"]
publishPreferencesInputIds: [
"wordpress-site"
]
};
wordpressProvider.publish = function(publishAttributes, title, content, callback) {
wordpressHelper.upload(
publishAttributes.site,
publishAttributes.postId,
publishAttributes.tags,
title,
content,
function(error, postId) {
wordpressHelper.upload(publishAttributes.site, publishAttributes.postId, publishAttributes.tags, title, content, function(error, postId) {
if(error) {
callback(error);
return;
}
publishAttributes.postId = postId;
callback();
}
);
});
};
wordpressProvider.newPublishAttributes = function(event) {
var publishAttributes = {};
publishAttributes.site = utils
.getInputTextValue(
"#input-publish-wordpress-site",
event,
/^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/);
publishAttributes.site = utils.getInputTextValue("#input-publish-wordpress-site", event, /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/);
publishAttributes.postId = utils.getInputTextValue("#input-publish-postid");
publishAttributes.tags = utils.getInputTextValue("#input-publish-tags");
if(event.isPropagationStopped()) {

View File

@ -0,0 +1,267 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="11">
<profile kind="CodeFormatterProfile" name="JsFormatter" version="11">
<setting id="org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.indent_empty_lines" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_compact_if" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_annotation" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.format_header" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.format_block_comments" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_object_initializer" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.blank_lines_between_type_declarations" value="0"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_assignment" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.tabulation.size" value="4"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_else_in_if_statement" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.align_type_members_on_columns" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.continuation_indentation_for_objlit_initializer" value="1"/>
<setting id="org.eclipse.wst.jsdt.core.compiler.compliance" value="1.5"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_closing_brace_in_objlit_initializer" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.format_source_code" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.wrap_before_binary_operator" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.continuation_indentation_for_array_initializer" value="1"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_expressions_in_array_initializer" value="49"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.blank_lines_after_package" value="1"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_comma_in_objlit_initializer" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.format_javadoc_comments" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.indentation.size" value="4"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_objlit_initializer" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.compiler.source" value="1.5"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.continuation_indentation" value="1"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_conditional_expression" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.indent_parameter_description" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.blank_lines_after_imports" value="1"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.indent_root_tags" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.blank_lines_before_package" value="0"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.blank_lines_before_member_type" value="1"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_enum_constants" value="0"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.blank_lines_before_imports" value="1"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_binary_expression" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.lineSplit" value="999"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.format_html" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.blank_lines_before_method" value="1"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.compiler.codegen.targetPlatform" value="1.5"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.keep_empty_objlit_initializer_on_one_line" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.format_line_comments" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.compiler.problem.assertIdentifier" value="error"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_object_initializer" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.line_length" value="80"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_block" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_multiple_fields" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.indent_statements_compare_to_body" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.tabulation.char" value="space"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.blank_lines_between_import_groups" value="1"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.blank_lines_before_field" value="0"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_opening_brace_in_objlit_initializer" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.compact_else_if" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
</profile>
</profiles>