Better permission management
This commit is contained in:
parent
a9b9c3eb5e
commit
4fcc27b9d3
@ -3,12 +3,6 @@ var VERSION = "2.1.7";
|
||||
var MAIN_URL = "http://benweet.github.io/stackedit/";
|
||||
var GOOGLE_ANALYTICS_ACCOUNT_ID = "UA-39556145-1";
|
||||
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 DROPBOX_APP_KEY = "lq6mwopab8wskas";
|
||||
var DROPBOX_APP_SECRET = "851fgnucpezy84t";
|
||||
|
31
res/core.js
31
res/core.js
@ -124,6 +124,8 @@ define([
|
||||
utils.setInputValue("#textarea-settings-default-content", settings.defaultContent);
|
||||
// Commit message
|
||||
utils.setInputValue("#input-settings-publish-commit-msg", settings.commitMsg);
|
||||
// Gdrive full access
|
||||
utils.setInputChecked("#input-settings-gdrive-full-access", settings.gdriveFullAccess);
|
||||
// Template
|
||||
utils.setInputValue("#textarea-settings-publish-template", settings.template);
|
||||
// PDF template
|
||||
@ -158,6 +160,8 @@ define([
|
||||
newSettings.defaultContent = utils.getInputValue("#textarea-settings-default-content");
|
||||
// Commit message
|
||||
newSettings.commitMsg = utils.getInputTextValue("#input-settings-publish-commit-msg", event);
|
||||
// Gdrive full access
|
||||
newSettings.gdriveFullAccess = utils.getInputChecked("#input-settings-gdrive-full-access");
|
||||
// Template
|
||||
newSettings.template = utils.getInputTextValue("#textarea-settings-publish-template", event);
|
||||
// PDF template
|
||||
@ -576,6 +580,14 @@ define([
|
||||
$("#wmd-undo-button").append($('<i class="icon-reply">')).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
|
||||
var isDocumentPanelShown = false;
|
||||
@ -855,6 +867,7 @@ define([
|
||||
trigger: 'hover',
|
||||
title: 'Thanks for supporting StackEdit by adding a backlink in your documents!'
|
||||
});
|
||||
var tooltipOpen = false;
|
||||
$(".tooltip-usercustom-extension").tooltip({
|
||||
html: true,
|
||||
container: '.modal-settings',
|
||||
@ -864,10 +877,12 @@ define([
|
||||
}).click(function(e) {
|
||||
$(this).tooltip('show');
|
||||
$(document).on("click.tooltip-usercustom-extension", function(e) {
|
||||
tooltipOpen = false;
|
||||
$(".tooltip-usercustom-extension").tooltip('hide');
|
||||
$(document).off("click.tooltip-usercustom-extension");
|
||||
});
|
||||
e.stopPropagation();
|
||||
!tooltipOpen && e.stopPropagation();
|
||||
tooltipOpen = true;
|
||||
});
|
||||
_.each(document.querySelectorAll(".tooltip-template"), function(tooltipElt) {
|
||||
var $tooltipElt = $(tooltipElt);
|
||||
@ -880,10 +895,12 @@ define([
|
||||
}).click(function(e) {
|
||||
$tooltipElt.tooltip('show');
|
||||
$(document).on("click.tooltip-template", function(e) {
|
||||
tooltipOpen = false;
|
||||
$(".tooltip-template").tooltip('hide');
|
||||
$(document).off("click.tooltip-template");
|
||||
});
|
||||
e.stopPropagation();
|
||||
!tooltipOpen && e.stopPropagation();
|
||||
tooltipOpen = true;
|
||||
});
|
||||
});
|
||||
|
||||
@ -899,6 +916,16 @@ define([
|
||||
show: false
|
||||
});
|
||||
|
||||
// OAuth redirect dialog
|
||||
$('.modal-oauth-redirect').modal({
|
||||
backdrop: "static",
|
||||
keyboard: false,
|
||||
show: false
|
||||
});
|
||||
$('.action-oauth-redirect').click(function() {
|
||||
oauthRedirectCallback();
|
||||
});
|
||||
|
||||
// Load images
|
||||
_.each(document.querySelectorAll('img'), function(imgElt) {
|
||||
var $imgElt = $(imgElt);
|
||||
|
@ -41,7 +41,9 @@ define([
|
||||
var htmlCode = _.template(buttonHtmlCode.config.template, {
|
||||
documentTitle: selectedFileDesc.title,
|
||||
documentMarkdown: selectedFileDesc.content,
|
||||
documentHTML: html
|
||||
documentHTML: html,
|
||||
frontMatter: selectedFileDesc.frontMatter,
|
||||
publishAttributes: undefined,
|
||||
});
|
||||
textareaElt.value = htmlCode;
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
define([
|
||||
"jquery",
|
||||
"underscore",
|
||||
"crel",
|
||||
"classes/Extension",
|
||||
"text!html/buttonPublish.html",
|
||||
], function($, _, Extension, buttonPublishHTML) {
|
||||
], function($, _, crel, Extension) {
|
||||
|
||||
var buttonPublish = new Extension("buttonPublish", 'Button "Publish"');
|
||||
// buttonPublish.settingsBlock = '<p>Adds a "Publish document" button in the
|
||||
@ -26,7 +26,6 @@ define([
|
||||
button.removeClass("disabled");
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
var publisher = undefined;
|
||||
buttonPublish.onPublisherCreated = function(publisherParameter) {
|
||||
@ -34,13 +33,19 @@ define([
|
||||
};
|
||||
|
||||
buttonPublish.onCreateButton = function() {
|
||||
var $buttonPublishHTML = $(buttonPublishHTML);
|
||||
button = $buttonPublishHTML.click(function() {
|
||||
if(!$buttonPublishHTML.hasClass("disabled")) {
|
||||
var button = crel('button', {
|
||||
class: 'btn btn-success button-publish',
|
||||
title: 'Publish this document'
|
||||
}, crel('i', {
|
||||
class: 'icon-share'
|
||||
}));
|
||||
var $button = $(button);
|
||||
$button.click(function() {
|
||||
if(!$button.hasClass("disabled")) {
|
||||
publisher.publish();
|
||||
}
|
||||
});
|
||||
return button[0];
|
||||
return button;
|
||||
};
|
||||
|
||||
buttonPublish.onPublishRunning = function(isRunning) {
|
||||
|
@ -55,7 +55,7 @@ define([
|
||||
|
||||
buttonSync.onCreateButton = function() {
|
||||
var button = crel('button', {
|
||||
class: 'btn btn-success',
|
||||
class: 'btn btn-success button-synchronize',
|
||||
title: 'Synchronize all'
|
||||
}, crel('i', {
|
||||
class: 'icon-refresh'
|
||||
|
@ -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) {
|
||||
var $checkboxElt = $(checkboxElt);
|
||||
$checkboxElt.click(function(e) {
|
||||
e.stopPropagation();
|
||||
}).find('[type=checkbox]').change(function() {
|
||||
var documentCheckboxElts = $checkboxElt.parent().next().find('[type=checkbox]');
|
||||
if(this.checked) {
|
||||
documentCheckboxElts.prop('checked', true).prop('disabled', true);
|
||||
}
|
||||
else {
|
||||
documentCheckboxElts.prop('checked', false).prop('disabled', false);
|
||||
}
|
||||
$checkboxElt.parent().next().find('[type=checkbox]').prop('checked', this.checked);
|
||||
});
|
||||
});
|
||||
|
||||
@ -327,10 +331,10 @@ define([
|
||||
|
||||
// Selection dropdown menu actions
|
||||
$(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() {
|
||||
$(documentListElt.querySelectorAll('input[type="checkbox"]')).prop('checked', false).change();
|
||||
$(documentListElt.querySelectorAll('input[type="checkbox"]')).prop('checked', false);
|
||||
});
|
||||
|
||||
// Delete selection actions
|
||||
|
@ -2,9 +2,8 @@ define([
|
||||
"utils",
|
||||
"classes/Extension",
|
||||
"text!html/mathJaxSettingsBlock.html",
|
||||
"text!libs/mathjax_config.js",
|
||||
"mathjax",
|
||||
], function(utils, Extension, mathJaxSettingsBlockHTML, mathjaxConfigJS) {
|
||||
], function(utils, Extension, mathJaxSettingsBlockHTML) {
|
||||
|
||||
var mathJax = new Extension("mathJax", "MathJax", true);
|
||||
mathJax.settingsBlock = mathJaxSettingsBlockHTML;
|
||||
|
@ -22,7 +22,7 @@ define([
|
||||
worker.postMessage(JSON.stringify(['init', typoJS, 'en_US', aff, dic]));
|
||||
|
||||
var aceEditor = undefined;
|
||||
var wordRegExp = XRegExp('\\p{L}+', 'g');
|
||||
var wordRegExp = XRegExp('\\p{L}+(?:\'\\p{L}+)*', 'g');
|
||||
var markers = [];
|
||||
var timeoutId = undefined;
|
||||
|
||||
|
@ -34,7 +34,7 @@ define([
|
||||
tour.addSteps([
|
||||
{
|
||||
element: ".navbar-inner",
|
||||
title: "Welcome to StackEdit",
|
||||
title: "Welcome to StackEdit!",
|
||||
content: "Please click <code>Next</code> to take a quick tour.",
|
||||
placement: "bottom",
|
||||
},
|
||||
@ -60,18 +60,22 @@ define([
|
||||
title: "Menu",
|
||||
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>",
|
||||
"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(''),
|
||||
placement: "right",
|
||||
reflex: true,
|
||||
},
|
||||
{
|
||||
element: "#extension-buttons button:first",
|
||||
title: "Synchronize/publish",
|
||||
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>",
|
||||
"Use also the <i class='icon-share'></i> <code>Publish</code> button to update your publications."
|
||||
].join(''),
|
||||
element: "#extension-buttons .button-synchronize",
|
||||
title: "Synchronize",
|
||||
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>",
|
||||
placement: "bottom",
|
||||
reflex: true,
|
||||
},
|
||||
{
|
||||
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",
|
||||
reflex: true,
|
||||
},
|
||||
|
@ -3,7 +3,8 @@ define([
|
||||
"underscore",
|
||||
"core",
|
||||
"eventMgr",
|
||||
"classes/AsyncTask"
|
||||
"classes/AsyncTask",
|
||||
"config",
|
||||
], function($, _, core, eventMgr, AsyncTask) {
|
||||
|
||||
var client = undefined;
|
||||
@ -61,6 +62,11 @@ define([
|
||||
return;
|
||||
}
|
||||
var immediate = true;
|
||||
function oauthRedirect() {
|
||||
core.oauthRedirect('Dropbox', function() {
|
||||
task.chain(localAuthenticate);
|
||||
});
|
||||
}
|
||||
function localAuthenticate() {
|
||||
if(immediate === false) {
|
||||
eventMgr.onMessage("Please make sure the Dropbox authorization popup is not blocked by your browser.");
|
||||
@ -68,7 +74,6 @@ define([
|
||||
// credentials
|
||||
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
|
||||
}
|
||||
client.reset();
|
||||
client.authenticate({
|
||||
interactive: !immediate
|
||||
}, function(error, client) {
|
||||
@ -81,7 +86,7 @@ define([
|
||||
// If immediate did not work retry without immediate flag
|
||||
if(immediate === true) {
|
||||
immediate = false;
|
||||
task.chain(localAuthenticate);
|
||||
task.chain(oauthRedirect);
|
||||
return;
|
||||
}
|
||||
// Error
|
||||
|
@ -3,7 +3,8 @@ define([
|
||||
"core",
|
||||
"utils",
|
||||
"eventMgr",
|
||||
"classes/AsyncTask"
|
||||
"classes/AsyncTask",
|
||||
"config"
|
||||
], function($, core, utils, eventMgr, AsyncTask) {
|
||||
|
||||
var connected = undefined;
|
||||
@ -55,7 +56,7 @@ define([
|
||||
task.chain();
|
||||
return;
|
||||
}
|
||||
var token = localStorage["githubToken"];
|
||||
var token = localStorage.githubToken;
|
||||
if(token !== undefined) {
|
||||
github = new Github({
|
||||
token: token,
|
||||
@ -64,12 +65,17 @@ define([
|
||||
task.chain();
|
||||
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.";
|
||||
// We add time for user to enter his credentials
|
||||
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
|
||||
var code = undefined;
|
||||
function oauthRedirect() {
|
||||
core.oauthRedirect('GitHub', function() {
|
||||
task.chain(getCode);
|
||||
});
|
||||
}
|
||||
function getCode() {
|
||||
eventMgr.onMessage("Please make sure the Github authorization popup is not blocked by your browser.");
|
||||
localStorage.removeItem("githubCode");
|
||||
authWindow = utils.popupWindow('github-oauth-client.html?client_id=' + GITHUB_CLIENT_ID, 'stackedit-github-oauth', 960, 600);
|
||||
authWindow.focus();
|
||||
@ -78,7 +84,7 @@ define([
|
||||
clearInterval(intervalId);
|
||||
authWindow = undefined;
|
||||
intervalId = undefined;
|
||||
code = localStorage["githubCode"];
|
||||
code = localStorage.githubCode;
|
||||
if(code === undefined) {
|
||||
task.error(new Error(errorMsg));
|
||||
return;
|
||||
@ -92,7 +98,7 @@ define([
|
||||
$.getJSON(GATEKEEPER_URL + "authenticate/" + code, function(data) {
|
||||
if(data.token !== undefined) {
|
||||
token = data.token;
|
||||
localStorage["githubToken"] = token;
|
||||
localStorage.githubToken = token;
|
||||
github = new Github({
|
||||
token: token,
|
||||
auth: "oauth"
|
||||
@ -104,7 +110,7 @@ define([
|
||||
}
|
||||
});
|
||||
}
|
||||
task.chain(getCode);
|
||||
task.chain(oauthRedirect);
|
||||
});
|
||||
task.onError(function() {
|
||||
if(intervalId !== undefined) {
|
||||
|
@ -1,13 +1,16 @@
|
||||
define([
|
||||
"underscore",
|
||||
"jquery",
|
||||
"core",
|
||||
"utils",
|
||||
"settings",
|
||||
"eventMgr",
|
||||
"classes/AsyncTask"
|
||||
], function($, core, utils, eventMgr, AsyncTask) {
|
||||
"classes/AsyncTask",
|
||||
"config"
|
||||
], function(_, $, core, utils, settings, eventMgr, AsyncTask) {
|
||||
|
||||
var connected = false;
|
||||
var authenticated = false;
|
||||
var permissionList = {};
|
||||
|
||||
var googleHelper = {};
|
||||
|
||||
@ -50,23 +53,49 @@ define([
|
||||
}
|
||||
|
||||
// Try to authenticate with Oauth
|
||||
function authenticate(task) {
|
||||
function authenticate(task, permission) {
|
||||
task.onRun(function() {
|
||||
if(authenticated === true) {
|
||||
if(_.has(permissionList, permission)) {
|
||||
task.chain();
|
||||
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;
|
||||
function oauthRedirect() {
|
||||
core.oauthRedirect('Google', function() {
|
||||
task.chain(localAuthenticate);
|
||||
});
|
||||
}
|
||||
function localAuthenticate() {
|
||||
if(immediate === false) {
|
||||
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;
|
||||
}
|
||||
gapi.auth.authorize({
|
||||
'client_id': GOOGLE_CLIENT_ID,
|
||||
'scope': GOOGLE_SCOPES,
|
||||
'scope': scopes,
|
||||
'immediate': immediate
|
||||
}, function(authResult) {
|
||||
gapi.client.load('drive', 'v2', function() {
|
||||
@ -75,7 +104,7 @@ define([
|
||||
// flag
|
||||
if(connected === true && immediate === true) {
|
||||
immediate = false;
|
||||
task.chain(localAuthenticate);
|
||||
task.chain(oauthRedirect);
|
||||
return;
|
||||
}
|
||||
// Error
|
||||
@ -83,7 +112,7 @@ define([
|
||||
return;
|
||||
}
|
||||
// Success
|
||||
authenticated = true;
|
||||
permissionList[permission] = true;
|
||||
task.chain();
|
||||
});
|
||||
});
|
||||
@ -91,11 +120,11 @@ define([
|
||||
task.chain(localAuthenticate);
|
||||
});
|
||||
}
|
||||
googleHelper.forceAuthenticate = function() {
|
||||
authenticated = false;
|
||||
googleHelper.forceGdriveAuthenticate = function() {
|
||||
permissionList = _.omit(permissionList, 'gdrive') ;
|
||||
var task = new AsyncTask();
|
||||
connect(task);
|
||||
authenticate(task);
|
||||
authenticate(task, 'gdrive');
|
||||
task.enqueue();
|
||||
};
|
||||
|
||||
@ -103,7 +132,7 @@ define([
|
||||
var result = undefined;
|
||||
var task = new AsyncTask();
|
||||
connect(task);
|
||||
authenticate(task);
|
||||
authenticate(task, 'gdrive');
|
||||
task.onRun(function() {
|
||||
var boundary = '-------314159265358979323846';
|
||||
var delimiter = "\r\n--" + boundary + "\r\n";
|
||||
@ -198,7 +227,7 @@ define([
|
||||
var result = undefined;
|
||||
var task = new AsyncTask();
|
||||
connect(task);
|
||||
authenticate(task);
|
||||
authenticate(task, 'gdrive');
|
||||
task.onRun(function() {
|
||||
var body = {'title': title};
|
||||
var request = gapi.client.drive.files.patch({
|
||||
@ -235,7 +264,7 @@ define([
|
||||
var result = undefined;
|
||||
var task = new AsyncTask();
|
||||
connect(task);
|
||||
authenticate(task);
|
||||
authenticate(task, 'gdrive');
|
||||
task.onRun(function() {
|
||||
var metadata = {
|
||||
title: title,
|
||||
@ -276,7 +305,7 @@ define([
|
||||
var result = undefined;
|
||||
var task = new AsyncTask();
|
||||
connect(task);
|
||||
authenticate(task);
|
||||
authenticate(task, 'picasa');
|
||||
task.onRun(function() {
|
||||
var headers = {
|
||||
"Slug": name
|
||||
@ -331,7 +360,7 @@ define([
|
||||
var newChangeId = lastChangeId || 0;
|
||||
var task = new AsyncTask();
|
||||
connect(task);
|
||||
authenticate(task);
|
||||
authenticate(task, 'gdrive');
|
||||
task.onRun(function() {
|
||||
var nextPageToken = undefined;
|
||||
function retrievePageOfChanges() {
|
||||
@ -383,7 +412,7 @@ define([
|
||||
var task = new AsyncTask();
|
||||
connect(task);
|
||||
if(!skipAuth) {
|
||||
authenticate(task);
|
||||
authenticate(task, 'gdrive');
|
||||
}
|
||||
task.onRun(function() {
|
||||
function recursiveDownloadMetadata() {
|
||||
@ -439,7 +468,7 @@ define([
|
||||
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
|
||||
connect(task);
|
||||
if(!skipAuth) {
|
||||
authenticate(task);
|
||||
authenticate(task, 'gdrive');
|
||||
}
|
||||
task.onRun(function() {
|
||||
function recursiveDownloadContent() {
|
||||
@ -512,7 +541,7 @@ define([
|
||||
var doc = undefined;
|
||||
var task = new AsyncTask();
|
||||
connect(task);
|
||||
authenticate(task);
|
||||
authenticate(task, 'gdrive');
|
||||
task.onRun(function() {
|
||||
gapi.drive.realtime.load(fileId, function(result) {
|
||||
// onFileLoaded
|
||||
@ -552,14 +581,14 @@ define([
|
||||
return;
|
||||
}
|
||||
else if(error.code === 401 || error.code === 403 || error.code == "token_refresh_required") {
|
||||
authenticated = false;
|
||||
permissionList = {};
|
||||
errorMsg = "Access to Google account is not authorized.";
|
||||
task.retry(new Error(errorMsg), 1);
|
||||
return;
|
||||
}
|
||||
else if(error.code === 0 || error.code === -1) {
|
||||
connected = false;
|
||||
authenticated = false;
|
||||
permissionList = {};
|
||||
core.setOffline();
|
||||
errorMsg = "|stopPublish";
|
||||
}
|
||||
@ -670,7 +699,7 @@ define([
|
||||
googleHelper.uploadBlogger = function(blogUrl, blogId, postId, labelList, title, content, callback) {
|
||||
var task = new AsyncTask();
|
||||
connect(task);
|
||||
authenticate(task);
|
||||
authenticate(task, 'blogger');
|
||||
task.onRun(function() {
|
||||
var headers = {};
|
||||
var token = gapi.auth.getToken();
|
||||
|
@ -36,13 +36,12 @@ define([
|
||||
task.chain();
|
||||
return;
|
||||
}
|
||||
var serializedOauthParams = localStorage["tumblrOauthParams"];
|
||||
var serializedOauthParams = localStorage.tumblrOauthParams;
|
||||
if(serializedOauthParams !== undefined) {
|
||||
oauthParams = JSON.parse(serializedOauthParams);
|
||||
task.chain();
|
||||
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.";
|
||||
// We add time for user to enter his credentials
|
||||
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
|
||||
@ -51,14 +50,20 @@ define([
|
||||
$.getJSON(TUMBLR_PROXY_URL + "request_token", function(data) {
|
||||
if(data.oauth_token !== undefined) {
|
||||
oauth_object = data;
|
||||
task.chain(getVerifier);
|
||||
task.chain(oauthRedirect);
|
||||
}
|
||||
else {
|
||||
task.error(new Error(errorMsg));
|
||||
}
|
||||
});
|
||||
}
|
||||
function oauthRedirect() {
|
||||
core.oauthRedirect('Tumblr', function() {
|
||||
task.chain(getVerifier);
|
||||
});
|
||||
}
|
||||
function getVerifier() {
|
||||
eventMgr.onMessage("Please make sure the Tumblr authorization popup is not blocked by your browser.");
|
||||
localStorage.removeItem("tumblrVerifier");
|
||||
authWindow = utils.popupWindow('tumblr-oauth-client.html?oauth_token=' + oauth_object.oauth_token, 'stackedit-tumblr-oauth', 800, 600);
|
||||
authWindow.focus();
|
||||
@ -67,7 +72,7 @@ define([
|
||||
clearInterval(intervalId);
|
||||
authWindow = undefined;
|
||||
intervalId = undefined;
|
||||
oauth_object.oauth_verifier = localStorage["tumblrVerifier"];
|
||||
oauth_object.oauth_verifier = localStorage.tumblrVerifier;
|
||||
if(oauth_object.oauth_verifier === undefined) {
|
||||
task.error(new Error(errorMsg));
|
||||
return;
|
||||
@ -80,7 +85,7 @@ define([
|
||||
function getAccessToken() {
|
||||
$.getJSON(TUMBLR_PROXY_URL + "access_token", oauth_object, function(data) {
|
||||
if(data.access_token !== undefined && data.access_token_secret !== undefined) {
|
||||
localStorage["tumblrOauthParams"] = JSON.stringify(data);
|
||||
localStorage.tumblrOauthParams = JSON.stringify(data);
|
||||
oauthParams = data;
|
||||
task.chain();
|
||||
}
|
||||
|
@ -32,17 +32,22 @@ define([
|
||||
var authWindow = undefined;
|
||||
var intervalId = undefined;
|
||||
task.onRun(function() {
|
||||
token = localStorage["wordpressToken"];
|
||||
token = localStorage.wordpressToken;
|
||||
if(token !== undefined) {
|
||||
task.chain();
|
||||
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.";
|
||||
// We add time for user to enter his credentials
|
||||
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
|
||||
var code = undefined;
|
||||
function oauthRedirect() {
|
||||
core.oauthRedirect('WordPress', function() {
|
||||
task.chain(getCode);
|
||||
});
|
||||
}
|
||||
function getCode() {
|
||||
eventMgr.onMessage("Please make sure the Wordpress authorization popup is not blocked by your browser.");
|
||||
localStorage.removeItem("wordpressCode");
|
||||
authWindow = utils.popupWindow('wordpress-oauth-client.html?client_id=' + WORDPRESS_CLIENT_ID, 'stackedit-wordpress-oauth', 960, 600);
|
||||
authWindow.focus();
|
||||
@ -51,7 +56,7 @@ define([
|
||||
clearInterval(intervalId);
|
||||
authWindow = undefined;
|
||||
intervalId = undefined;
|
||||
code = localStorage["wordpressCode"];
|
||||
code = localStorage.wordpressCode;
|
||||
if(code === undefined) {
|
||||
task.error(new Error(errorMsg));
|
||||
return;
|
||||
@ -65,7 +70,7 @@ define([
|
||||
$.getJSON(WORDPRESS_PROXY_URL + "authenticate/" + code, function(data) {
|
||||
if(data.token !== undefined) {
|
||||
token = data.token;
|
||||
localStorage["wordpressToken"] = token;
|
||||
localStorage.wordpressToken = token;
|
||||
task.chain();
|
||||
}
|
||||
else {
|
||||
@ -73,7 +78,7 @@ define([
|
||||
}
|
||||
});
|
||||
}
|
||||
task.chain(getCode);
|
||||
task.chain(oauthRedirect);
|
||||
});
|
||||
task.onError(function() {
|
||||
if(intervalId !== undefined) {
|
||||
|
@ -745,23 +745,6 @@
|
||||
class="form-control">
|
||||
</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">
|
||||
<label class="col-lg-4 control-label"
|
||||
for="input-publish-dropbox-path">File path</label>
|
||||
@ -833,6 +816,12 @@
|
||||
</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 class="modal-footer">
|
||||
<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="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="col-lg-4 control-label"
|
||||
for="input-settings-publish-commit-msg">Commit message</label>
|
||||
<label class="col-lg-4 control-label">Permission</label>
|
||||
<div class="col-lg-7">
|
||||
<input type="text" id="input-settings-publish-commit-msg"
|
||||
class="form-control">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" id="input-settings-gdrive-full-access" />
|
||||
Allow StackEdit to open any document in Google Drive
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
@ -999,6 +991,14 @@
|
||||
class="form-control"></textarea>
|
||||
</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">
|
||||
<label class="col-lg-4 control-label"
|
||||
for="input-settings-ssh-proxy">SSH proxy</label>
|
||||
@ -1082,6 +1082,24 @@
|
||||
</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-dialog">
|
||||
<div class="modal-content">
|
||||
|
@ -1,3 +0,0 @@
|
||||
<button class="btn btn-success" title="Publish this document">
|
||||
<i class="icon-share"></i>
|
||||
</button>
|
@ -1,26 +1,31 @@
|
||||
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 if not publishing)</li>
|
||||
<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>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>
|
||||
<b>Examples:</b>
|
||||
<br />
|
||||
<title><%= documentTitle %></title>
|
||||
<br />
|
||||
<div><%- documentHTML %></div>
|
||||
<br />
|
||||
<%<br />
|
||||
if(publishAttributes.provider.providerId == "github")
|
||||
print(documentMarkdown);<br />
|
||||
%>
|
||||
<br /><title><%= documentTitle %></title>
|
||||
<br /><div><%- documentHTML %></div>
|
||||
<br /><%
|
||||
<br />if(publishAttributes.provider.providerId == "github") print(documentMarkdown);
|
||||
<br
|
||||
/>%>
|
||||
<br />
|
||||
<br />
|
||||
<a target="_blank" href="http://underscorejs.org/#template">More
|
||||
info</a>
|
||||
<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>
|
@ -1,4 +1,4 @@
|
||||
require([
|
||||
define([
|
||||
"settings",
|
||||
"text!libs/mathjax_config.js"
|
||||
], function(settings, mathjaxConfigJS) {
|
||||
|
@ -11,8 +11,14 @@ define([
|
||||
"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) {
|
||||
bloggerProvider.publish = function(publishAttributes, frontMatter, title, content, callback) {
|
||||
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) {
|
||||
callback(error);
|
||||
return;
|
||||
@ -30,13 +36,6 @@ define([
|
||||
publishAttributes.blogUrl = utils.checkUrl(blogUrl);
|
||||
}
|
||||
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()) {
|
||||
return undefined;
|
||||
}
|
||||
|
@ -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);
|
||||
if(path === undefined) {
|
||||
callback(true);
|
||||
|
@ -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;
|
||||
googleHelper.upload(publishAttributes.id, undefined, publishAttributes.fileName || title, content, contentType, undefined, function(error, result) {
|
||||
if(error) {
|
||||
@ -433,7 +433,7 @@ define([
|
||||
}, function(err) {
|
||||
console.error(err);
|
||||
if(err.type == "token_refresh_required") {
|
||||
googleHelper.forceAuthenticate();
|
||||
googleHelper.forceGdriveAuthenticate();
|
||||
}
|
||||
else if(err.type == "not_found") {
|
||||
eventMgr.onError('"' + fileDesc.title + '" has been removed from Google Drive.');
|
||||
|
@ -13,7 +13,7 @@ define([
|
||||
"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) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
|
@ -12,7 +12,7 @@ define([
|
||||
"github-branch"
|
||||
];
|
||||
|
||||
githubProvider.publish = function(publishAttributes, title, content, callback) {
|
||||
githubProvider.publish = function(publishAttributes, frontMatter, title, content, callback) {
|
||||
var commitMsg = settings.commitMsg;
|
||||
githubHelper.upload(publishAttributes.repository, publishAttributes.username, publishAttributes.branch, publishAttributes.path, content, commitMsg, callback);
|
||||
};
|
||||
|
@ -12,7 +12,7 @@ define([
|
||||
"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);
|
||||
};
|
||||
|
||||
|
@ -1,16 +1,23 @@
|
||||
define([
|
||||
"underscore",
|
||||
"utils",
|
||||
"classes/Provider",
|
||||
"helpers/tumblrHelper"
|
||||
], function(utils, Provider, tumblrHelper) {
|
||||
], function(_, utils, Provider, tumblrHelper) {
|
||||
|
||||
var tumblrProvider = new Provider("tumblr", "Tumblr");
|
||||
tumblrProvider.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) {
|
||||
tumblrProvider.publish = function(publishAttributes, frontMatter, title, content, callback) {
|
||||
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) {
|
||||
callback(error);
|
||||
return;
|
||||
@ -24,7 +31,6 @@ define([
|
||||
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.postId = utils.getInputTextValue("#input-publish-postid");
|
||||
publishAttributes.tags = utils.getInputTextValue("#input-publish-tags");
|
||||
if(event.isPropagationStopped()) {
|
||||
return undefined;
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
define([
|
||||
"underscore",
|
||||
"utils",
|
||||
"classes/Provider",
|
||||
"helpers/wordpressHelper"
|
||||
], function(utils, Provider, wordpressHelper) {
|
||||
], function(_, utils, Provider, wordpressHelper) {
|
||||
|
||||
var wordpressProvider = new Provider("wordpress", "WordPress");
|
||||
wordpressProvider.defaultPublishFormat = "html";
|
||||
@ -10,8 +11,14 @@ define([
|
||||
"wordpress-site"
|
||||
];
|
||||
|
||||
wordpressProvider.publish = function(publishAttributes, title, content, callback) {
|
||||
wordpressHelper.upload(publishAttributes.site, publishAttributes.postId, publishAttributes.tags, title, content, function(error, postId) {
|
||||
wordpressProvider.publish = function(publishAttributes, frontMatter, title, content, callback) {
|
||||
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) {
|
||||
callback(error);
|
||||
return;
|
||||
@ -25,7 +32,6 @@ define([
|
||||
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.postId = utils.getInputTextValue("#input-publish-postid");
|
||||
publishAttributes.tags = utils.getInputTextValue("#input-publish-tags");
|
||||
if(event.isPropagationStopped()) {
|
||||
return undefined;
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ define([
|
||||
documentTitle: fileDesc.title,
|
||||
documentMarkdown: fileDesc.content,
|
||||
documentHTML: html,
|
||||
frontMatter: fileDesc.frontMatter,
|
||||
publishAttributes: publishAttributes
|
||||
});
|
||||
}
|
||||
@ -108,9 +109,10 @@ define([
|
||||
|
||||
// Format the content
|
||||
var content = getPublishContent(publishFileDesc, publishAttributes, publishHTML);
|
||||
var title = (publishFileDesc.frontMatter || {}).title || publishFileDesc.title;
|
||||
|
||||
// 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) {
|
||||
var errorMsg = error.toString();
|
||||
if(errorMsg.indexOf("|removePublish") !== -1) {
|
||||
@ -178,7 +180,7 @@ define([
|
||||
$(".publish-provider-name").text(provider.providerName);
|
||||
|
||||
// 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
|
||||
utils.resetModalInputs();
|
||||
@ -219,7 +221,8 @@ define([
|
||||
var fileDesc = fileMgr.currentFile;
|
||||
var html = previewHtml;
|
||||
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) {
|
||||
publishAttributes.provider = provider;
|
||||
sharing.createLink(publishAttributes, function() {
|
||||
|
@ -12,6 +12,7 @@ define([
|
||||
maxWidth: 960,
|
||||
defaultContent: "\n\n\n> Written with [StackEdit](" + MAIN_URL + ").",
|
||||
commitMsg: "Published with " + MAIN_URL,
|
||||
gdriveFullAccess: true,
|
||||
template: [
|
||||
'<!DOCTYPE html>\n',
|
||||
'<html>\n',
|
||||
|
@ -13,6 +13,7 @@
|
||||
@primary-bg: #ddd;
|
||||
@primary-bg-light: lighten(@primary-bg, 4%);
|
||||
@primary-bg-lighter: lighten(@primary-bg, 8%);
|
||||
@primary-bg-lightest: lighten(@primary-bg, 9.5%);
|
||||
@secondary-bg: #888;
|
||||
@secondary-bg-light: lighten(@secondary-bg, 7%);
|
||||
@secondary-bg-dark: darken(@secondary-bg, 7%);
|
||||
@ -44,7 +45,7 @@
|
||||
@dropdown-border: @primary-bg;
|
||||
@pre-border-color: @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-hover-color: @disabled-color;
|
||||
@nav-tabs-border-color: @transparent;
|
||||
@ -55,7 +56,7 @@
|
||||
@list-group-link-color: @primary-color;
|
||||
@list-group-border: @transparent;
|
||||
@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;
|
||||
@btn-default-color: @primary-color;
|
||||
@btn-default-bg: @transparent;
|
||||
@ -396,6 +397,11 @@ body {
|
||||
background-color: @panel-bg;
|
||||
padding-top: 6px;
|
||||
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 {
|
||||
background-color: @primary-bg-lighter;
|
||||
background-color: @primary-bg-lightest;
|
||||
}
|
||||
|
||||
.ace_print-margin {
|
||||
|
@ -3,6 +3,7 @@
|
||||
@primary-bg: #444;
|
||||
@primary-bg-light: darken(@primary-bg, 7%);
|
||||
@primary-bg-lighter: darken(@primary-bg, 13%);
|
||||
@primary-bg-lightest: darken(@primary-bg, 15%);
|
||||
@secondary-bg: #444;
|
||||
@secondary-bg-light: darken(@secondary-bg, 7%);
|
||||
@secondary-bg-dark: lighten(@secondary-bg, 7%);
|
||||
|
Loading…
Reference in New Issue
Block a user