Better permission management

This commit is contained in:
benweet 2013-10-06 15:34:40 +01:00
parent a9b9c3eb5e
commit 4fcc27b9d3
30 changed files with 277 additions and 150 deletions

View File

@ -3,12 +3,6 @@ var VERSION = "2.1.7";
var MAIN_URL = "http://benweet.github.io/stackedit/"; var MAIN_URL = "http://benweet.github.io/stackedit/";
var GOOGLE_ANALYTICS_ACCOUNT_ID = "UA-39556145-1"; var GOOGLE_ANALYTICS_ACCOUNT_ID = "UA-39556145-1";
var GOOGLE_API_KEY = "AIzaSyAeCU8CGcSkn0z9js6iocHuPBX4f_mMWkw"; var GOOGLE_API_KEY = "AIzaSyAeCU8CGcSkn0z9js6iocHuPBX4f_mMWkw";
var GOOGLE_SCOPES = [
"https://www.googleapis.com/auth/drive.install",
"https://www.googleapis.com/auth/drive",
"https://www.googleapis.com/auth/blogger",
"https://picasaweb.google.com/data/"
];
var GOOGLE_DRIVE_APP_ID = "241271498917"; var GOOGLE_DRIVE_APP_ID = "241271498917";
var DROPBOX_APP_KEY = "lq6mwopab8wskas"; var DROPBOX_APP_KEY = "lq6mwopab8wskas";
var DROPBOX_APP_SECRET = "851fgnucpezy84t"; var DROPBOX_APP_SECRET = "851fgnucpezy84t";

View File

@ -124,6 +124,8 @@ define([
utils.setInputValue("#textarea-settings-default-content", settings.defaultContent); utils.setInputValue("#textarea-settings-default-content", settings.defaultContent);
// Commit message // Commit message
utils.setInputValue("#input-settings-publish-commit-msg", settings.commitMsg); utils.setInputValue("#input-settings-publish-commit-msg", settings.commitMsg);
// Gdrive full access
utils.setInputChecked("#input-settings-gdrive-full-access", settings.gdriveFullAccess);
// Template // Template
utils.setInputValue("#textarea-settings-publish-template", settings.template); utils.setInputValue("#textarea-settings-publish-template", settings.template);
// PDF template // PDF template
@ -158,6 +160,8 @@ define([
newSettings.defaultContent = utils.getInputValue("#textarea-settings-default-content"); newSettings.defaultContent = utils.getInputValue("#textarea-settings-default-content");
// Commit message // Commit message
newSettings.commitMsg = utils.getInputTextValue("#input-settings-publish-commit-msg", event); newSettings.commitMsg = utils.getInputTextValue("#input-settings-publish-commit-msg", event);
// Gdrive full access
newSettings.gdriveFullAccess = utils.getInputChecked("#input-settings-gdrive-full-access");
// Template // Template
newSettings.template = utils.getInputTextValue("#textarea-settings-publish-template", event); newSettings.template = utils.getInputTextValue("#textarea-settings-publish-template", event);
// PDF template // PDF template
@ -577,6 +581,14 @@ define([
$("#wmd-redo-button").append($('<i class="icon-forward">')).appendTo($btnGroupElt); $("#wmd-redo-button").append($('<i class="icon-forward">')).appendTo($btnGroupElt);
}; };
// Shows a dialog to force the user to click a button before opening oauth popup
var oauthRedirectCallback = undefined;
core.oauthRedirect = function(providerName, callback) {
oauthRedirectCallback = callback;
$('.oauth-redirect-provider').text(providerName);
$('.modal-oauth-redirect').modal("show");
};
// Initialize multiple things and then fire eventMgr.onReady // Initialize multiple things and then fire eventMgr.onReady
var isDocumentPanelShown = false; var isDocumentPanelShown = false;
var isMenuPanelShown = false; var isMenuPanelShown = false;
@ -855,6 +867,7 @@ define([
trigger: 'hover', trigger: 'hover',
title: 'Thanks for supporting StackEdit by adding a backlink in your documents!' title: 'Thanks for supporting StackEdit by adding a backlink in your documents!'
}); });
var tooltipOpen = false;
$(".tooltip-usercustom-extension").tooltip({ $(".tooltip-usercustom-extension").tooltip({
html: true, html: true,
container: '.modal-settings', container: '.modal-settings',
@ -864,10 +877,12 @@ define([
}).click(function(e) { }).click(function(e) {
$(this).tooltip('show'); $(this).tooltip('show');
$(document).on("click.tooltip-usercustom-extension", function(e) { $(document).on("click.tooltip-usercustom-extension", function(e) {
tooltipOpen = false;
$(".tooltip-usercustom-extension").tooltip('hide'); $(".tooltip-usercustom-extension").tooltip('hide');
$(document).off("click.tooltip-usercustom-extension"); $(document).off("click.tooltip-usercustom-extension");
}); });
e.stopPropagation(); !tooltipOpen && e.stopPropagation();
tooltipOpen = true;
}); });
_.each(document.querySelectorAll(".tooltip-template"), function(tooltipElt) { _.each(document.querySelectorAll(".tooltip-template"), function(tooltipElt) {
var $tooltipElt = $(tooltipElt); var $tooltipElt = $(tooltipElt);
@ -880,10 +895,12 @@ define([
}).click(function(e) { }).click(function(e) {
$tooltipElt.tooltip('show'); $tooltipElt.tooltip('show');
$(document).on("click.tooltip-template", function(e) { $(document).on("click.tooltip-template", function(e) {
tooltipOpen = false;
$(".tooltip-template").tooltip('hide'); $(".tooltip-template").tooltip('hide');
$(document).off("click.tooltip-template"); $(document).off("click.tooltip-template");
}); });
e.stopPropagation(); !tooltipOpen && e.stopPropagation();
tooltipOpen = true;
}); });
}); });
@ -899,6 +916,16 @@ define([
show: false show: false
}); });
// OAuth redirect dialog
$('.modal-oauth-redirect').modal({
backdrop: "static",
keyboard: false,
show: false
});
$('.action-oauth-redirect').click(function() {
oauthRedirectCallback();
});
// Load images // Load images
_.each(document.querySelectorAll('img'), function(imgElt) { _.each(document.querySelectorAll('img'), function(imgElt) {
var $imgElt = $(imgElt); var $imgElt = $(imgElt);

View File

@ -41,7 +41,9 @@ define([
var htmlCode = _.template(buttonHtmlCode.config.template, { var htmlCode = _.template(buttonHtmlCode.config.template, {
documentTitle: selectedFileDesc.title, documentTitle: selectedFileDesc.title,
documentMarkdown: selectedFileDesc.content, documentMarkdown: selectedFileDesc.content,
documentHTML: html documentHTML: html,
frontMatter: selectedFileDesc.frontMatter,
publishAttributes: undefined,
}); });
textareaElt.value = htmlCode; textareaElt.value = htmlCode;
} }

View File

@ -1,9 +1,9 @@
define([ define([
"jquery", "jquery",
"underscore", "underscore",
"crel",
"classes/Extension", "classes/Extension",
"text!html/buttonPublish.html", ], function($, _, crel, Extension) {
], function($, _, Extension, buttonPublishHTML) {
var buttonPublish = new Extension("buttonPublish", 'Button "Publish"'); var buttonPublish = new Extension("buttonPublish", 'Button "Publish"');
// buttonPublish.settingsBlock = '<p>Adds a "Publish document" button in the // buttonPublish.settingsBlock = '<p>Adds a "Publish document" button in the
@ -26,7 +26,6 @@ define([
button.removeClass("disabled"); button.removeClass("disabled");
} }
} }
;
var publisher = undefined; var publisher = undefined;
buttonPublish.onPublisherCreated = function(publisherParameter) { buttonPublish.onPublisherCreated = function(publisherParameter) {
@ -34,13 +33,19 @@ define([
}; };
buttonPublish.onCreateButton = function() { buttonPublish.onCreateButton = function() {
var $buttonPublishHTML = $(buttonPublishHTML); var button = crel('button', {
button = $buttonPublishHTML.click(function() { class: 'btn btn-success button-publish',
if(!$buttonPublishHTML.hasClass("disabled")) { title: 'Publish this document'
}, crel('i', {
class: 'icon-share'
}));
var $button = $(button);
$button.click(function() {
if(!$button.hasClass("disabled")) {
publisher.publish(); publisher.publish();
} }
}); });
return button[0]; return button;
}; };
buttonPublish.onPublishRunning = function(isRunning) { buttonPublish.onPublishRunning = function(isRunning) {

View File

@ -55,7 +55,7 @@ define([
buttonSync.onCreateButton = function() { buttonSync.onCreateButton = function() {
var button = crel('button', { var button = crel('button', {
class: 'btn btn-success', class: 'btn btn-success button-synchronize',
title: 'Synchronize all' title: 'Synchronize all'
}, crel('i', { }, crel('i', {
class: 'icon-refresh' class: 'icon-refresh'

View File

@ -258,19 +258,23 @@ define([
}); });
}); });
// Set folder checkbox special behavior // Set file checkbox behavior
_.each(documentListElt.querySelectorAll('.file .checkbox'), function(checkboxElt) {
var $checkboxElt = $(checkboxElt);
$checkboxElt.click(function(e) {
e.stopPropagation();
}).find('[type=checkbox]').change(function() {
$checkboxElt.parents('.list-group').find('.folder [type=checkbox]').prop('checked', false);
});
});
// Set folder checkbox behavior
_.each(documentListElt.querySelectorAll('.folder .checkbox'), function(checkboxElt) { _.each(documentListElt.querySelectorAll('.folder .checkbox'), function(checkboxElt) {
var $checkboxElt = $(checkboxElt); var $checkboxElt = $(checkboxElt);
$checkboxElt.click(function(e) { $checkboxElt.click(function(e) {
e.stopPropagation(); e.stopPropagation();
}).find('[type=checkbox]').change(function() { }).find('[type=checkbox]').change(function() {
var documentCheckboxElts = $checkboxElt.parent().next().find('[type=checkbox]'); $checkboxElt.parent().next().find('[type=checkbox]').prop('checked', this.checked);
if(this.checked) {
documentCheckboxElts.prop('checked', true).prop('disabled', true);
}
else {
documentCheckboxElts.prop('checked', false).prop('disabled', false);
}
}); });
}); });
@ -327,10 +331,10 @@ define([
// Selection dropdown menu actions // Selection dropdown menu actions
$(modalElt.querySelectorAll('.action-select-all')).click(function() { $(modalElt.querySelectorAll('.action-select-all')).click(function() {
$(documentListElt.querySelectorAll('input[type="checkbox"]')).prop('checked', true).change(); $(documentListElt.querySelectorAll('input[type="checkbox"]')).prop('checked', true);
}); });
$(modalElt.querySelectorAll('.action-unselect-all')).click(function() { $(modalElt.querySelectorAll('.action-unselect-all')).click(function() {
$(documentListElt.querySelectorAll('input[type="checkbox"]')).prop('checked', false).change(); $(documentListElt.querySelectorAll('input[type="checkbox"]')).prop('checked', false);
}); });
// Delete selection actions // Delete selection actions

View File

@ -2,9 +2,8 @@ define([
"utils", "utils",
"classes/Extension", "classes/Extension",
"text!html/mathJaxSettingsBlock.html", "text!html/mathJaxSettingsBlock.html",
"text!libs/mathjax_config.js",
"mathjax", "mathjax",
], function(utils, Extension, mathJaxSettingsBlockHTML, mathjaxConfigJS) { ], function(utils, Extension, mathJaxSettingsBlockHTML) {
var mathJax = new Extension("mathJax", "MathJax", true); var mathJax = new Extension("mathJax", "MathJax", true);
mathJax.settingsBlock = mathJaxSettingsBlockHTML; mathJax.settingsBlock = mathJaxSettingsBlockHTML;

View File

@ -22,7 +22,7 @@ define([
worker.postMessage(JSON.stringify(['init', typoJS, 'en_US', aff, dic])); worker.postMessage(JSON.stringify(['init', typoJS, 'en_US', aff, dic]));
var aceEditor = undefined; var aceEditor = undefined;
var wordRegExp = XRegExp('\\p{L}+', 'g'); var wordRegExp = XRegExp('\\p{L}+(?:\'\\p{L}+)*', 'g');
var markers = []; var markers = [];
var timeoutId = undefined; var timeoutId = undefined;

View File

@ -34,7 +34,7 @@ define([
tour.addSteps([ tour.addSteps([
{ {
element: ".navbar-inner", element: ".navbar-inner",
title: "Welcome to StackEdit", title: "Welcome to StackEdit!",
content: "Please click <code>Next</code> to take a quick tour.", content: "Please click <code>Next</code> to take a quick tour.",
placement: "bottom", placement: "bottom",
}, },
@ -60,18 +60,22 @@ define([
title: "Menu", title: "Menu",
content: [ content: [
"<p>Use the <i class='icon-provider-stackedit'></i> menu to synchronize your document on <i class='icon-provider-gdrive'></i> <code>Google Drive</code> or <i class='icon-provider-dropbox'></i> <code>Dropbox</code>.</p>", "<p>Use the <i class='icon-provider-stackedit'></i> menu to synchronize your document on <i class='icon-provider-gdrive'></i> <code>Google Drive</code> or <i class='icon-provider-dropbox'></i> <code>Dropbox</code>.</p>",
"Use also this menu to publish your document on <i class='icon-provider-github'></i> <code>GitHub</code>, <i class='icon-provider-blogger'></i> <code>Blogger</code>..." "Use also this menu to publish your document on <i class='icon-provider-github'></i> <code>GitHub</code>, <i class='icon-provider-blogger'></i> <code>Blogger</code>, <i class='icon-provider-wordpress'></i> <code>WordPress</code>..."
].join(''), ].join(''),
placement: "right", placement: "right",
reflex: true, reflex: true,
}, },
{ {
element: "#extension-buttons button:first", element: "#extension-buttons .button-synchronize",
title: "Synchronize/publish", title: "Synchronize",
content: [ content: "<p>Once imported/exported, use the <i class='icon-refresh'></i> <code>Synchronize</code> button to force the synchronization (this is done automatically every 3 minutes).</p>",
"<p>Once imported/exported, use the <i class='icon-refresh'></i> <code>Synchronize</code> button to force the synchronization (this is done automatically every 3 minutes).</p>", placement: "bottom",
"Use also the <i class='icon-share'></i> <code>Publish</code> button to update your publications." reflex: true,
].join(''), },
{
element: "#extension-buttons .button-publish",
title: "Update publications",
content: "Once published, use the <i class='icon-share'></i> <code>Publish</code> button to update your publications.",
placement: "bottom", placement: "bottom",
reflex: true, reflex: true,
}, },

View File

@ -3,7 +3,8 @@ define([
"underscore", "underscore",
"core", "core",
"eventMgr", "eventMgr",
"classes/AsyncTask" "classes/AsyncTask",
"config",
], function($, _, core, eventMgr, AsyncTask) { ], function($, _, core, eventMgr, AsyncTask) {
var client = undefined; var client = undefined;
@ -61,6 +62,11 @@ define([
return; return;
} }
var immediate = true; var immediate = true;
function oauthRedirect() {
core.oauthRedirect('Dropbox', function() {
task.chain(localAuthenticate);
});
}
function localAuthenticate() { function localAuthenticate() {
if(immediate === false) { if(immediate === false) {
eventMgr.onMessage("Please make sure the Dropbox authorization popup is not blocked by your browser."); eventMgr.onMessage("Please make sure the Dropbox authorization popup is not blocked by your browser.");
@ -68,7 +74,6 @@ define([
// credentials // credentials
task.timeout = ASYNC_TASK_LONG_TIMEOUT; task.timeout = ASYNC_TASK_LONG_TIMEOUT;
} }
client.reset();
client.authenticate({ client.authenticate({
interactive: !immediate interactive: !immediate
}, function(error, client) { }, function(error, client) {
@ -81,7 +86,7 @@ define([
// If immediate did not work retry without immediate flag // If immediate did not work retry without immediate flag
if(immediate === true) { if(immediate === true) {
immediate = false; immediate = false;
task.chain(localAuthenticate); task.chain(oauthRedirect);
return; return;
} }
// Error // Error

View File

@ -3,7 +3,8 @@ define([
"core", "core",
"utils", "utils",
"eventMgr", "eventMgr",
"classes/AsyncTask" "classes/AsyncTask",
"config"
], function($, core, utils, eventMgr, AsyncTask) { ], function($, core, utils, eventMgr, AsyncTask) {
var connected = undefined; var connected = undefined;
@ -55,7 +56,7 @@ define([
task.chain(); task.chain();
return; return;
} }
var token = localStorage["githubToken"]; var token = localStorage.githubToken;
if(token !== undefined) { if(token !== undefined) {
github = new Github({ github = new Github({
token: token, token: token,
@ -64,12 +65,17 @@ define([
task.chain(); task.chain();
return; return;
} }
eventMgr.onMessage("Please make sure the Github authorization popup is not blocked by your browser.");
var errorMsg = "Failed to retrieve a token from GitHub."; var errorMsg = "Failed to retrieve a token from GitHub.";
// We add time for user to enter his credentials // We add time for user to enter his credentials
task.timeout = ASYNC_TASK_LONG_TIMEOUT; task.timeout = ASYNC_TASK_LONG_TIMEOUT;
var code = undefined; var code = undefined;
function oauthRedirect() {
core.oauthRedirect('GitHub', function() {
task.chain(getCode);
});
}
function getCode() { function getCode() {
eventMgr.onMessage("Please make sure the Github authorization popup is not blocked by your browser.");
localStorage.removeItem("githubCode"); 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(); authWindow.focus();
@ -78,7 +84,7 @@ define([
clearInterval(intervalId); clearInterval(intervalId);
authWindow = undefined; authWindow = undefined;
intervalId = undefined; intervalId = undefined;
code = localStorage["githubCode"]; code = localStorage.githubCode;
if(code === undefined) { if(code === undefined) {
task.error(new Error(errorMsg)); task.error(new Error(errorMsg));
return; return;
@ -92,7 +98,7 @@ define([
$.getJSON(GATEKEEPER_URL + "authenticate/" + code, function(data) { $.getJSON(GATEKEEPER_URL + "authenticate/" + code, function(data) {
if(data.token !== undefined) { if(data.token !== undefined) {
token = data.token; token = data.token;
localStorage["githubToken"] = token; localStorage.githubToken = token;
github = new Github({ github = new Github({
token: token, token: token,
auth: "oauth" auth: "oauth"
@ -104,7 +110,7 @@ define([
} }
}); });
} }
task.chain(getCode); task.chain(oauthRedirect);
}); });
task.onError(function() { task.onError(function() {
if(intervalId !== undefined) { if(intervalId !== undefined) {

View File

@ -1,13 +1,16 @@
define([ define([
"underscore",
"jquery", "jquery",
"core", "core",
"utils", "utils",
"settings",
"eventMgr", "eventMgr",
"classes/AsyncTask" "classes/AsyncTask",
], function($, core, utils, eventMgr, AsyncTask) { "config"
], function(_, $, core, utils, settings, eventMgr, AsyncTask) {
var connected = false; var connected = false;
var authenticated = false; var permissionList = {};
var googleHelper = {}; var googleHelper = {};
@ -50,23 +53,49 @@ define([
} }
// Try to authenticate with Oauth // Try to authenticate with Oauth
function authenticate(task) { function authenticate(task, permission) {
task.onRun(function() { task.onRun(function() {
if(authenticated === true) { if(_.has(permissionList, permission)) {
task.chain(); task.chain();
return; return;
} }
var scopes = undefined;
if(permission == 'gdrive' && settings.gdriveFullAccess === true) {
scopes = [
"https://www.googleapis.com/auth/drive.install",
"https://www.googleapis.com/auth/drive",
];
}
else if(permission == 'gdrive' && settings.gdriveFullAccess === false) {
scopes = [
"https://www.googleapis.com/auth/drive.install",
"https://www.googleapis.com/auth/drive.file",
];
}
else if(permission == 'blogger') {
scopes = [
"https://www.googleapis.com/auth/blogger",
];
}
else if(permission == 'picasa') {
scopes = [
"https://picasaweb.google.com/data/",
];
}
var immediate = true; var immediate = true;
function oauthRedirect() {
core.oauthRedirect('Google', function() {
task.chain(localAuthenticate);
});
}
function localAuthenticate() { function localAuthenticate() {
if(immediate === false) { if(immediate === false) {
eventMgr.onMessage("Please make sure the Google authorization popup is not blocked by your browser."); eventMgr.onMessage("Please make sure the Google authorization popup is not blocked by your browser.");
// If not immediate we add time for user to enter his
// credentials
task.timeout = ASYNC_TASK_LONG_TIMEOUT; task.timeout = ASYNC_TASK_LONG_TIMEOUT;
} }
gapi.auth.authorize({ gapi.auth.authorize({
'client_id': GOOGLE_CLIENT_ID, 'client_id': GOOGLE_CLIENT_ID,
'scope': GOOGLE_SCOPES, 'scope': scopes,
'immediate': immediate 'immediate': immediate
}, function(authResult) { }, function(authResult) {
gapi.client.load('drive', 'v2', function() { gapi.client.load('drive', 'v2', function() {
@ -75,7 +104,7 @@ define([
// flag // flag
if(connected === true && immediate === true) { if(connected === true && immediate === true) {
immediate = false; immediate = false;
task.chain(localAuthenticate); task.chain(oauthRedirect);
return; return;
} }
// Error // Error
@ -83,7 +112,7 @@ define([
return; return;
} }
// Success // Success
authenticated = true; permissionList[permission] = true;
task.chain(); task.chain();
}); });
}); });
@ -91,11 +120,11 @@ define([
task.chain(localAuthenticate); task.chain(localAuthenticate);
}); });
} }
googleHelper.forceAuthenticate = function() { googleHelper.forceGdriveAuthenticate = function() {
authenticated = false; permissionList = _.omit(permissionList, 'gdrive') ;
var task = new AsyncTask(); var task = new AsyncTask();
connect(task); connect(task);
authenticate(task); authenticate(task, 'gdrive');
task.enqueue(); task.enqueue();
}; };
@ -103,7 +132,7 @@ define([
var result = undefined; var result = undefined;
var task = new AsyncTask(); var task = new AsyncTask();
connect(task); connect(task);
authenticate(task); authenticate(task, 'gdrive');
task.onRun(function() { task.onRun(function() {
var boundary = '-------314159265358979323846'; var boundary = '-------314159265358979323846';
var delimiter = "\r\n--" + boundary + "\r\n"; var delimiter = "\r\n--" + boundary + "\r\n";
@ -198,7 +227,7 @@ define([
var result = undefined; var result = undefined;
var task = new AsyncTask(); var task = new AsyncTask();
connect(task); connect(task);
authenticate(task); authenticate(task, 'gdrive');
task.onRun(function() { task.onRun(function() {
var body = {'title': title}; var body = {'title': title};
var request = gapi.client.drive.files.patch({ var request = gapi.client.drive.files.patch({
@ -235,7 +264,7 @@ define([
var result = undefined; var result = undefined;
var task = new AsyncTask(); var task = new AsyncTask();
connect(task); connect(task);
authenticate(task); authenticate(task, 'gdrive');
task.onRun(function() { task.onRun(function() {
var metadata = { var metadata = {
title: title, title: title,
@ -276,7 +305,7 @@ define([
var result = undefined; var result = undefined;
var task = new AsyncTask(); var task = new AsyncTask();
connect(task); connect(task);
authenticate(task); authenticate(task, 'picasa');
task.onRun(function() { task.onRun(function() {
var headers = { var headers = {
"Slug": name "Slug": name
@ -331,7 +360,7 @@ define([
var newChangeId = lastChangeId || 0; var newChangeId = lastChangeId || 0;
var task = new AsyncTask(); var task = new AsyncTask();
connect(task); connect(task);
authenticate(task); authenticate(task, 'gdrive');
task.onRun(function() { task.onRun(function() {
var nextPageToken = undefined; var nextPageToken = undefined;
function retrievePageOfChanges() { function retrievePageOfChanges() {
@ -383,7 +412,7 @@ define([
var task = new AsyncTask(); var task = new AsyncTask();
connect(task); connect(task);
if(!skipAuth) { if(!skipAuth) {
authenticate(task); authenticate(task, 'gdrive');
} }
task.onRun(function() { task.onRun(function() {
function recursiveDownloadMetadata() { function recursiveDownloadMetadata() {
@ -439,7 +468,7 @@ define([
task.timeout = ASYNC_TASK_LONG_TIMEOUT; task.timeout = ASYNC_TASK_LONG_TIMEOUT;
connect(task); connect(task);
if(!skipAuth) { if(!skipAuth) {
authenticate(task); authenticate(task, 'gdrive');
} }
task.onRun(function() { task.onRun(function() {
function recursiveDownloadContent() { function recursiveDownloadContent() {
@ -512,7 +541,7 @@ define([
var doc = undefined; var doc = undefined;
var task = new AsyncTask(); var task = new AsyncTask();
connect(task); connect(task);
authenticate(task); authenticate(task, 'gdrive');
task.onRun(function() { task.onRun(function() {
gapi.drive.realtime.load(fileId, function(result) { gapi.drive.realtime.load(fileId, function(result) {
// onFileLoaded // onFileLoaded
@ -552,14 +581,14 @@ define([
return; return;
} }
else if(error.code === 401 || error.code === 403 || error.code == "token_refresh_required") { else if(error.code === 401 || error.code === 403 || error.code == "token_refresh_required") {
authenticated = false; permissionList = {};
errorMsg = "Access to Google account is not authorized."; errorMsg = "Access to Google account is not authorized.";
task.retry(new Error(errorMsg), 1); task.retry(new Error(errorMsg), 1);
return; return;
} }
else if(error.code === 0 || error.code === -1) { else if(error.code === 0 || error.code === -1) {
connected = false; connected = false;
authenticated = false; permissionList = {};
core.setOffline(); core.setOffline();
errorMsg = "|stopPublish"; errorMsg = "|stopPublish";
} }
@ -670,7 +699,7 @@ define([
googleHelper.uploadBlogger = function(blogUrl, blogId, postId, labelList, title, content, callback) { googleHelper.uploadBlogger = function(blogUrl, blogId, postId, labelList, title, content, callback) {
var task = new AsyncTask(); var task = new AsyncTask();
connect(task); connect(task);
authenticate(task); authenticate(task, 'blogger');
task.onRun(function() { task.onRun(function() {
var headers = {}; var headers = {};
var token = gapi.auth.getToken(); var token = gapi.auth.getToken();

View File

@ -36,13 +36,12 @@ define([
task.chain(); task.chain();
return; return;
} }
var serializedOauthParams = localStorage["tumblrOauthParams"]; var serializedOauthParams = localStorage.tumblrOauthParams;
if(serializedOauthParams !== undefined) { if(serializedOauthParams !== undefined) {
oauthParams = JSON.parse(serializedOauthParams); oauthParams = JSON.parse(serializedOauthParams);
task.chain(); task.chain();
return; return;
} }
eventMgr.onMessage("Please make sure the Tumblr authorization popup is not blocked by your browser.");
var errorMsg = "Failed to retrieve a token from Tumblr."; var errorMsg = "Failed to retrieve a token from Tumblr.";
// We add time for user to enter his credentials // We add time for user to enter his credentials
task.timeout = ASYNC_TASK_LONG_TIMEOUT; task.timeout = ASYNC_TASK_LONG_TIMEOUT;
@ -51,14 +50,20 @@ define([
$.getJSON(TUMBLR_PROXY_URL + "request_token", function(data) { $.getJSON(TUMBLR_PROXY_URL + "request_token", function(data) {
if(data.oauth_token !== undefined) { if(data.oauth_token !== undefined) {
oauth_object = data; oauth_object = data;
task.chain(getVerifier); task.chain(oauthRedirect);
} }
else { else {
task.error(new Error(errorMsg)); task.error(new Error(errorMsg));
} }
}); });
} }
function oauthRedirect() {
core.oauthRedirect('Tumblr', function() {
task.chain(getVerifier);
});
}
function getVerifier() { function getVerifier() {
eventMgr.onMessage("Please make sure the Tumblr authorization popup is not blocked by your browser.");
localStorage.removeItem("tumblrVerifier"); 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(); authWindow.focus();
@ -67,7 +72,7 @@ define([
clearInterval(intervalId); clearInterval(intervalId);
authWindow = undefined; authWindow = undefined;
intervalId = undefined; intervalId = undefined;
oauth_object.oauth_verifier = localStorage["tumblrVerifier"]; oauth_object.oauth_verifier = localStorage.tumblrVerifier;
if(oauth_object.oauth_verifier === undefined) { if(oauth_object.oauth_verifier === undefined) {
task.error(new Error(errorMsg)); task.error(new Error(errorMsg));
return; return;
@ -80,7 +85,7 @@ define([
function getAccessToken() { function getAccessToken() {
$.getJSON(TUMBLR_PROXY_URL + "access_token", oauth_object, function(data) { $.getJSON(TUMBLR_PROXY_URL + "access_token", oauth_object, function(data) {
if(data.access_token !== undefined && data.access_token_secret !== undefined) { if(data.access_token !== undefined && data.access_token_secret !== undefined) {
localStorage["tumblrOauthParams"] = JSON.stringify(data); localStorage.tumblrOauthParams = JSON.stringify(data);
oauthParams = data; oauthParams = data;
task.chain(); task.chain();
} }

View File

@ -32,17 +32,22 @@ define([
var authWindow = undefined; var authWindow = undefined;
var intervalId = undefined; var intervalId = undefined;
task.onRun(function() { task.onRun(function() {
token = localStorage["wordpressToken"]; token = localStorage.wordpressToken;
if(token !== undefined) { if(token !== undefined) {
task.chain(); task.chain();
return; return;
} }
eventMgr.onMessage("Please make sure the Wordpress authorization popup is not blocked by your browser.");
var errorMsg = "Failed to retrieve a token from Wordpress."; var errorMsg = "Failed to retrieve a token from Wordpress.";
// We add time for user to enter his credentials // We add time for user to enter his credentials
task.timeout = ASYNC_TASK_LONG_TIMEOUT; task.timeout = ASYNC_TASK_LONG_TIMEOUT;
var code = undefined; var code = undefined;
function oauthRedirect() {
core.oauthRedirect('WordPress', function() {
task.chain(getCode);
});
}
function getCode() { function getCode() {
eventMgr.onMessage("Please make sure the Wordpress authorization popup is not blocked by your browser.");
localStorage.removeItem("wordpressCode"); 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(); authWindow.focus();
@ -51,7 +56,7 @@ define([
clearInterval(intervalId); clearInterval(intervalId);
authWindow = undefined; authWindow = undefined;
intervalId = undefined; intervalId = undefined;
code = localStorage["wordpressCode"]; code = localStorage.wordpressCode;
if(code === undefined) { if(code === undefined) {
task.error(new Error(errorMsg)); task.error(new Error(errorMsg));
return; return;
@ -65,7 +70,7 @@ define([
$.getJSON(WORDPRESS_PROXY_URL + "authenticate/" + code, function(data) { $.getJSON(WORDPRESS_PROXY_URL + "authenticate/" + code, function(data) {
if(data.token !== undefined) { if(data.token !== undefined) {
token = data.token; token = data.token;
localStorage["wordpressToken"] = token; localStorage.wordpressToken = token;
task.chain(); task.chain();
} }
else { else {
@ -73,7 +78,7 @@ define([
} }
}); });
} }
task.chain(getCode); task.chain(oauthRedirect);
}); });
task.onError(function() { task.onError(function() {
if(intervalId !== undefined) { if(intervalId !== undefined) {

View File

@ -745,23 +745,6 @@
class="form-control"> class="form-control">
</div> </div>
</div> </div>
<div class="form-group modal-publish-blogger">
<label class="col-lg-4 control-label" for="input-publish-labels">Labels
(comma separated)</label>
<div class="col-lg-7">
<input type="text" id="input-publish-labels"
placeholder="Label1, Label2" class="form-control">
</div>
</div>
<div
class="form-group modal-publish-tumblr modal-publish-wordpress">
<label class="col-lg-4 control-label" for="input-publish-tags">Tags
(comma separated)</label>
<div class="col-lg-7">
<input type="text" id="input-publish-tags"
placeholder="Tag1, Tag2" class="form-control">
</div>
</div>
<div class="form-group modal-publish-dropbox"> <div class="form-group modal-publish-dropbox">
<label class="col-lg-4 control-label" <label class="col-lg-4 control-label"
for="input-publish-dropbox-path">File path</label> for="input-publish-dropbox-path">File path</label>
@ -833,6 +816,12 @@
</div> </div>
</div> </div>
</div> </div>
<blockquote class="front-matter-info modal-publish-blogger modal-publish-tumblr modal-publish-wordpress">
<p><b>NOTE:</b> You can use a
<a href="http://jekyllrb.com/docs/frontmatter/"
target="_blank">YAML front matter</a> to specify the title and the tags/labels of your publication.</p>
<p><b>Interpreted variables:</b> <i>title, categories/tags</i></p>
</blockquote>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<a href="#" class="btn btn-default" data-dismiss="modal">Cancel</a> <a href="#" class="btn btn-default" data-dismiss="modal">Cancel</a>
@ -972,11 +961,14 @@
<div class="tab-pane" id="tabpane-settings-services"> <div class="tab-pane" id="tabpane-settings-services">
<div class="form-horizontal"> <div class="form-horizontal">
<div class="form-group"> <div class="form-group">
<label class="col-lg-4 control-label" <label class="col-lg-4 control-label">Permission</label>
for="input-settings-publish-commit-msg">Commit message</label>
<div class="col-lg-7"> <div class="col-lg-7">
<input type="text" id="input-settings-publish-commit-msg" <div class="checkbox">
class="form-control"> <label>
<input type="checkbox" id="input-settings-gdrive-full-access" />
Allow StackEdit to open any document in Google Drive
</label>
</div>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
@ -999,6 +991,14 @@
class="form-control"></textarea> class="form-control"></textarea>
</div> </div>
</div> </div>
<div class="form-group">
<label class="col-lg-4 control-label"
for="input-settings-publish-commit-msg">GitHub commit message</label>
<div class="col-lg-7">
<input type="text" id="input-settings-publish-commit-msg"
class="form-control">
</div>
</div>
<div class="form-group"> <div class="form-group">
<label class="col-lg-4 control-label" <label class="col-lg-4 control-label"
for="input-settings-ssh-proxy">SSH proxy</label> for="input-settings-ssh-proxy">SSH proxy</label>
@ -1082,6 +1082,24 @@
</div> </div>
<div class="modal modal-oauth-redirect">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">Authorization</h3>
</div>
<div class="modal-body">
<blockquote><b>NOTE:</b> You are being redirected to <span class="oauth-redirect-provider"></span> authorization page.</blockquote>
</div>
<div class="modal-footer">
<a class="btn btn-primary action-oauth-redirect" data-dismiss="modal">Continue</a>
</div>
</div>
</div>
</div>
<div class="modal modal-app-reset"> <div class="modal modal-app-reset">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">

View File

@ -1,3 +0,0 @@
<button class="btn btn-success" title="Publish this document">
<i class="icon-share"></i>
</button>

View File

@ -1,26 +1,31 @@
Available variables: Available variables:
<br> <br>
<ul> <ul>
<li><b>documentTitle</b>: document title</li> <li>
<li><b>documentMarkdown</b>: document in Markdown format</li> <b>documentTitle</b>: document title</li>
<li><b>documentHTML</b>: document in HTML format</li> <li>
<li><b>publishAttributes</b>: attributes of the publish location <b>documentMarkdown</b>: document in Markdown format</li>
(undefined if not publishing)</li> <li>
<b>documentHTML</b>: document in HTML format</li>
<li>
<b>frontMatter</b>: YAML front matter object (undefined if not present)</li>
<li>
<b>publishAttributes</b>: attributes of the publish location (undefined if
not publishing)</li>
</ul> </ul>
<b>Examples:</b> <b>Examples:</b>
<br /> <br />&lt;title&gt;&lt;%= documentTitle %&gt;&lt;&#x2F;title&gt;
&lt;title&gt;&lt;%= documentTitle %&gt;&lt;&#x2F;title&gt; <br />&lt;div&gt;&lt;%- documentHTML %&gt;&lt;&#x2F;div&gt;
<br /> <br />&lt;%
&lt;div&gt;&lt;%- documentHTML %&gt;&lt;&#x2F;div&gt; <br />if(publishAttributes.provider.providerId == &quot;github&quot;) print(documentMarkdown);
<br /> <br
&lt;%<br /> />%&gt;
if(publishAttributes.provider.providerId == &quot;github&quot;)
print(documentMarkdown);<br />
%&gt;
<br /> <br />
<br /> <br />
<a target="_blank" href="http://underscorejs.org/#template">More <a target="_blank" href="http://underscorejs.org/#template">More
info</a> info</a>
<br /> <br />
<br /> <br />
<b class="text-danger"><i class="icon-attention"></i> Careful! Template is subject to malicious code. Don't copy/paste untrusted content.</b> <b class="text-danger">
<i class="icon-attention"></i>Careful! Template is subject to malicious code. Don't copy/paste untrusted
content.</b>

View File

@ -1,4 +1,4 @@
require([ define([
"settings", "settings",
"text!libs/mathjax_config.js" "text!libs/mathjax_config.js"
], function(settings, mathjaxConfigJS) { ], function(settings, mathjaxConfigJS) {

View File

@ -11,8 +11,14 @@ define([
"blogger-url" "blogger-url"
]; ];
bloggerProvider.publish = function(publishAttributes, title, content, callback) { bloggerProvider.publish = function(publishAttributes, frontMatter, title, content, callback) {
googleHelper.uploadBlogger(publishAttributes.blogUrl, publishAttributes.blogId, publishAttributes.postId, publishAttributes.labelList, title, content, function(error, blogId, postId) { var labelList = publishAttributes.labelList || [];
if(frontMatter) {
frontMatter.categories !== undefined && (labelList = frontMatter.categories);
frontMatter.tags !== undefined && (labelList = frontMatter.tags);
}
_.isString(labelList) && (labelList = _.compact(labelList.split(/[\s,]/)));
googleHelper.uploadBlogger(publishAttributes.blogUrl, publishAttributes.blogId, publishAttributes.postId, labelList, title, content, function(error, blogId, postId) {
if(error) { if(error) {
callback(error); callback(error);
return; return;
@ -30,13 +36,6 @@ define([
publishAttributes.blogUrl = utils.checkUrl(blogUrl); publishAttributes.blogUrl = utils.checkUrl(blogUrl);
} }
publishAttributes.postId = utils.getInputTextValue("#input-publish-postid"); publishAttributes.postId = utils.getInputTextValue("#input-publish-postid");
publishAttributes.labelList = [];
var labels = utils.getInputTextValue("#input-publish-labels");
if(labels !== undefined) {
publishAttributes.labelList = _.chain(labels.split(",")).map(function(label) {
return utils.trim(label);
}).compact().value();
}
if(event.isPropagationStopped()) { if(event.isPropagationStopped()) {
return undefined; return undefined;
} }

View File

@ -207,7 +207,7 @@ define([
}); });
}; };
dropboxProvider.publish = function(publishAttributes, title, content, callback) { dropboxProvider.publish = function(publishAttributes, frontMatter, title, content, callback) {
var path = checkPath(publishAttributes.path); var path = checkPath(publishAttributes.path);
if(path === undefined) { if(path === undefined) {
callback(true); callback(true);

View File

@ -244,7 +244,7 @@ define([
}); });
}; };
gdriveProvider.publish = function(publishAttributes, title, content, callback) { gdriveProvider.publish = function(publishAttributes, frontMatter, title, content, callback) {
var contentType = publishAttributes.format != "markdown" ? 'text/html' : undefined; var contentType = publishAttributes.format != "markdown" ? 'text/html' : undefined;
googleHelper.upload(publishAttributes.id, undefined, publishAttributes.fileName || title, content, contentType, undefined, function(error, result) { googleHelper.upload(publishAttributes.id, undefined, publishAttributes.fileName || title, content, contentType, undefined, function(error, result) {
if(error) { if(error) {
@ -433,7 +433,7 @@ define([
}, function(err) { }, function(err) {
console.error(err); console.error(err);
if(err.type == "token_refresh_required") { if(err.type == "token_refresh_required") {
googleHelper.forceAuthenticate(); googleHelper.forceGdriveAuthenticate();
} }
else if(err.type == "not_found") { else if(err.type == "not_found") {
eventMgr.onError('"' + fileDesc.title + '" has been removed from Google Drive.'); eventMgr.onError('"' + fileDesc.title + '" has been removed from Google Drive.');

View File

@ -13,7 +13,7 @@ define([
"filename" "filename"
]; ];
gistProvider.publish = function(publishAttributes, title, content, callback) { gistProvider.publish = function(publishAttributes, frontMatter, 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) { if(error) {
callback(error); callback(error);

View File

@ -12,7 +12,7 @@ define([
"github-branch" "github-branch"
]; ];
githubProvider.publish = function(publishAttributes, title, content, callback) { githubProvider.publish = function(publishAttributes, frontMatter, title, content, callback) {
var commitMsg = settings.commitMsg; var commitMsg = settings.commitMsg;
githubHelper.upload(publishAttributes.repository, publishAttributes.username, publishAttributes.branch, publishAttributes.path, content, commitMsg, callback); githubHelper.upload(publishAttributes.repository, publishAttributes.username, publishAttributes.branch, publishAttributes.path, content, commitMsg, callback);
}; };

View File

@ -12,7 +12,7 @@ define([
"ssh-password" "ssh-password"
]; ];
sshProvider.publish = function(publishAttributes, title, content, callback) { sshProvider.publish = function(publishAttributes, frontMatter, 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);
}; };

View File

@ -1,16 +1,23 @@
define([ define([
"underscore",
"utils", "utils",
"classes/Provider", "classes/Provider",
"helpers/tumblrHelper" "helpers/tumblrHelper"
], function(utils, Provider, tumblrHelper) { ], function(_, utils, Provider, tumblrHelper) {
var tumblrProvider = new Provider("tumblr", "Tumblr"); var tumblrProvider = new Provider("tumblr", "Tumblr");
tumblrProvider.publishPreferencesInputIds = [ tumblrProvider.publishPreferencesInputIds = [
"tumblr-hostname" "tumblr-hostname"
]; ];
tumblrProvider.publish = function(publishAttributes, title, content, callback) { tumblrProvider.publish = function(publishAttributes, frontMatter, title, content, callback) {
tumblrHelper.upload(publishAttributes.blogHostname, publishAttributes.postId, publishAttributes.tags, publishAttributes.format == "markdown" ? "markdown" : "html", title, content, function(error, postId) { var labelList = publishAttributes.tags || [];
if(frontMatter) {
frontMatter.categories !== undefined && (labelList = frontMatter.categories);
frontMatter.tags !== undefined && (labelList = frontMatter.tags);
}
_.isString(labelList) && (labelList = _.compact(labelList.split(/[\s,]/)));
tumblrHelper.upload(publishAttributes.blogHostname, publishAttributes.postId, labelList.join(','), publishAttributes.format == "markdown" ? "markdown" : "html", title, content, function(error, postId) {
if(error) { if(error) {
callback(error); callback(error);
return; return;
@ -24,7 +31,6 @@ define([
var publishAttributes = {}; 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.postId = utils.getInputTextValue("#input-publish-postid");
publishAttributes.tags = utils.getInputTextValue("#input-publish-tags");
if(event.isPropagationStopped()) { if(event.isPropagationStopped()) {
return undefined; return undefined;
} }

View File

@ -1,8 +1,9 @@
define([ define([
"underscore",
"utils", "utils",
"classes/Provider", "classes/Provider",
"helpers/wordpressHelper" "helpers/wordpressHelper"
], function(utils, Provider, wordpressHelper) { ], function(_, utils, Provider, wordpressHelper) {
var wordpressProvider = new Provider("wordpress", "WordPress"); var wordpressProvider = new Provider("wordpress", "WordPress");
wordpressProvider.defaultPublishFormat = "html"; wordpressProvider.defaultPublishFormat = "html";
@ -10,8 +11,14 @@ define([
"wordpress-site" "wordpress-site"
]; ];
wordpressProvider.publish = function(publishAttributes, title, content, callback) { wordpressProvider.publish = function(publishAttributes, frontMatter, title, content, callback) {
wordpressHelper.upload(publishAttributes.site, publishAttributes.postId, publishAttributes.tags, title, content, function(error, postId) { var labelList = publishAttributes.tags || [];
if(frontMatter) {
frontMatter.categories !== undefined && (labelList = frontMatter.categories);
frontMatter.tags !== undefined && (labelList = frontMatter.tags);
}
_.isString(labelList) && (labelList = _.compact(labelList.split(/[\s,]/)));
wordpressHelper.upload(publishAttributes.site, publishAttributes.postId, labelList.join(','), title, content, function(error, postId) {
if(error) { if(error) {
callback(error); callback(error);
return; return;
@ -25,7 +32,6 @@ define([
var publishAttributes = {}; 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.postId = utils.getInputTextValue("#input-publish-postid");
publishAttributes.tags = utils.getInputTextValue("#input-publish-tags");
if(event.isPropagationStopped()) { if(event.isPropagationStopped()) {
return undefined; return undefined;
} }

View File

@ -63,6 +63,7 @@ define([
documentTitle: fileDesc.title, documentTitle: fileDesc.title,
documentMarkdown: fileDesc.content, documentMarkdown: fileDesc.content,
documentHTML: html, documentHTML: html,
frontMatter: fileDesc.frontMatter,
publishAttributes: publishAttributes publishAttributes: publishAttributes
}); });
} }
@ -108,9 +109,10 @@ define([
// Format the content // Format the content
var content = getPublishContent(publishFileDesc, publishAttributes, publishHTML); var content = getPublishContent(publishFileDesc, publishAttributes, publishHTML);
var title = (publishFileDesc.frontMatter || {}).title || publishFileDesc.title;
// Call the provider // Call the provider
publishAttributes.provider.publish(publishAttributes, publishFileDesc.title, content, function(error) { publishAttributes.provider.publish(publishAttributes, publishFileDesc.frontMatter, title, content, function(error) {
if(error !== undefined) { if(error !== undefined) {
var errorMsg = error.toString(); var errorMsg = error.toString();
if(errorMsg.indexOf("|removePublish") !== -1) { if(errorMsg.indexOf("|removePublish") !== -1) {
@ -178,7 +180,7 @@ define([
$(".publish-provider-name").text(provider.providerName); $(".publish-provider-name").text(provider.providerName);
// Show/hide controls depending on provider // Show/hide controls depending on provider
$('div[class*=" modal-publish-"]').hide().filter(".modal-publish-" + provider.providerId).show(); $('.modal-publish [class*=" modal-publish-"]').hide().filter(".modal-publish-" + provider.providerId).show();
// Reset fields // Reset fields
utils.resetModalInputs(); utils.resetModalInputs();
@ -219,7 +221,8 @@ define([
var fileDesc = fileMgr.currentFile; var fileDesc = fileMgr.currentFile;
var html = previewHtml; var html = previewHtml;
var content = getPublishContent(fileDesc, publishAttributes, html); var content = getPublishContent(fileDesc, publishAttributes, html);
provider.publish(publishAttributes, fileDesc.title, content, function(error) { var title = (fileDesc.frontMatter && fileDesc.frontMatter.title) || fileDesc.title;
provider.publish(publishAttributes, fileDesc.frontMatter, title, content, function(error) {
if(error === undefined) { if(error === undefined) {
publishAttributes.provider = provider; publishAttributes.provider = provider;
sharing.createLink(publishAttributes, function() { sharing.createLink(publishAttributes, function() {

View File

@ -12,6 +12,7 @@ define([
maxWidth: 960, maxWidth: 960,
defaultContent: "\n\n\n> Written with [StackEdit](" + MAIN_URL + ").", defaultContent: "\n\n\n> Written with [StackEdit](" + MAIN_URL + ").",
commitMsg: "Published with " + MAIN_URL, commitMsg: "Published with " + MAIN_URL,
gdriveFullAccess: true,
template: [ template: [
'<!DOCTYPE html>\n', '<!DOCTYPE html>\n',
'<html>\n', '<html>\n',

View File

@ -13,6 +13,7 @@
@primary-bg: #ddd; @primary-bg: #ddd;
@primary-bg-light: lighten(@primary-bg, 4%); @primary-bg-light: lighten(@primary-bg, 4%);
@primary-bg-lighter: lighten(@primary-bg, 8%); @primary-bg-lighter: lighten(@primary-bg, 8%);
@primary-bg-lightest: lighten(@primary-bg, 9.5%);
@secondary-bg: #888; @secondary-bg: #888;
@secondary-bg-light: lighten(@secondary-bg, 7%); @secondary-bg-light: lighten(@secondary-bg, 7%);
@secondary-bg-dark: darken(@secondary-bg, 7%); @secondary-bg-dark: darken(@secondary-bg, 7%);
@ -44,7 +45,7 @@
@dropdown-border: @primary-bg; @dropdown-border: @primary-bg;
@pre-border-color: @primary-bg; @pre-border-color: @primary-bg;
@navbar-default-bg: @primary-bg; @navbar-default-bg: @primary-bg;
@nav-link-hover-bg: @primary-bg-lighter; @nav-link-hover-bg: @primary-bg-lightest;
@nav-disabled-link-color: @disabled-color; @nav-disabled-link-color: @disabled-color;
@nav-disabled-link-hover-color: @disabled-color; @nav-disabled-link-hover-color: @disabled-color;
@nav-tabs-border-color: @transparent; @nav-tabs-border-color: @transparent;
@ -55,7 +56,7 @@
@list-group-link-color: @primary-color; @list-group-link-color: @primary-color;
@list-group-border: @transparent; @list-group-border: @transparent;
@list-group-active-bg: @dropdown-link-hover-bg; @list-group-active-bg: @dropdown-link-hover-bg;
@list-group-hover-bg: @primary-bg-lighter; @list-group-hover-bg: @primary-bg-lightest;
@input-color-placeholder: @disabled-color; @input-color-placeholder: @disabled-color;
@btn-default-color: @primary-color; @btn-default-color: @primary-color;
@btn-default-bg: @transparent; @btn-default-bg: @transparent;
@ -396,6 +397,11 @@ body {
background-color: @panel-bg; background-color: @panel-bg;
padding-top: 6px; padding-top: 6px;
border-right: 5px solid @panel-border-color; border-right: 5px solid @panel-border-color;
& > .nav > li > a {
&:hover, &:active {
background-color: @panel-bg;
}
}
} }
} }
@ -980,7 +986,7 @@ ul,ol {
} }
.ace_marker-layer .ace_active-line { .ace_marker-layer .ace_active-line {
background-color: @primary-bg-lighter; background-color: @primary-bg-lightest;
} }
.ace_print-margin { .ace_print-margin {

View File

@ -3,6 +3,7 @@
@primary-bg: #444; @primary-bg: #444;
@primary-bg-light: darken(@primary-bg, 7%); @primary-bg-light: darken(@primary-bg, 7%);
@primary-bg-lighter: darken(@primary-bg, 13%); @primary-bg-lighter: darken(@primary-bg, 13%);
@primary-bg-lightest: darken(@primary-bg, 15%);
@secondary-bg: #444; @secondary-bg: #444;
@secondary-bg-light: darken(@secondary-bg, 7%); @secondary-bg-light: darken(@secondary-bg, 7%);
@secondary-bg-dark: lighten(@secondary-bg, 7%); @secondary-bg-dark: lighten(@secondary-bg, 7%);