Tumblr support

This commit is contained in:
benweet 2013-04-28 23:33:17 +01:00
parent 94a739bd80
commit 859f347974
14 changed files with 269 additions and 14 deletions

2
.gitignore vendored
View File

@ -2,4 +2,4 @@ chrome-app*
.project .project
.settings .settings
node_modules node_modules
Thumbs.db

View File

@ -1 +1 @@
CACHE MANIFEST # v16 CACHE: index.html css/main-min.css js/main-min.js js/require.js img/ajax-loader.gif img/glyphicons-halflings.png img/glyphicons-halflings-white.png img/icons.png img/stackedit-32.ico img/stackedit-promo.png NETWORK: * CACHE MANIFEST # v17 CACHE: index.html css/main-min.css js/main-min.js js/require.js img/ajax-loader.gif img/glyphicons-halflings.png img/glyphicons-halflings-white.png img/icons.png img/stackedit-32.ico img/stackedit-promo.png NETWORK: *

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -97,6 +97,8 @@
class="icon-github"></i> GitHub</a></li> class="icon-github"></i> GitHub</a></li>
<li><a href="#" class="action-publish-gdrive"><i <li><a href="#" class="action-publish-gdrive"><i
class="icon-gdrive"></i> Google Drive</a></li> class="icon-gdrive"></i> Google Drive</a></li>
<li><a href="#" class="action-publish-tumblr"><i
class="icon-tumblr"></i> Tumblr</a></li>
</ul></li> </ul></li>
<li><a href="#" data-toggle="modal" <li><a href="#" data-toggle="modal"
data-target="#modal-manage-publish" class="action-reset-input"><i data-target="#modal-manage-publish" class="action-reset-input"><i
@ -315,22 +317,38 @@
placeholder="http://exemple.blogger.com/"> placeholder="http://exemple.blogger.com/">
</div> </div>
</div> </div>
<div class="control-group modal-publish-blogger"> <div class="control-group modal-publish-tumblr">
<label class="control-label" for="input-publish-blogger-postid">Update <label class="control-label" for="input-publish-tumblr-hostname">Blog
hostname</label>
<div class="controls">
<input type="text" id="input-publish-tumblr-hostname"
placeholder="exemple.tumblr.com">
</div>
</div>
<div class="control-group modal-publish-blogger modal-publish-tumblr">
<label class="control-label" for="input-publish-postid">Update
existing post ID (optional)</label> existing post ID (optional)</label>
<div class="controls"> <div class="controls">
<input type="text" id="input-publish-blogger-postid" <input type="text" id="input-publish-postid"
placeholder="Post ID"> placeholder="Post ID">
</div> </div>
</div> </div>
<div class="control-group modal-publish-blogger"> <div class="control-group modal-publish-blogger">
<label class="control-label" for="input-publish-blogger-labels">Labels <label class="control-label" for="input-publish-labels">Labels
(comma separated)</label> (comma separated)</label>
<div class="controls"> <div class="controls">
<input type="text" id="input-publish-blogger-labels" <input type="text" id="input-publish-labels"
placeholder="Label1, Label2"> placeholder="Label1, Label2">
</div> </div>
</div> </div>
<div class="control-group modal-publish-tumblr">
<label class="control-label" for="input-publish-tags">Tags
(comma separated)</label>
<div class="controls">
<input type="text" id="input-publish-tags"
placeholder="Tag1, Tag2">
</div>
</div>
<div class="control-group modal-publish-dropbox"> <div class="control-group modal-publish-dropbox">
<label class="control-label" for="input-publish-dropbox-path">File <label class="control-label" for="input-publish-dropbox-path">File
path</label> path</label>

View File

@ -32,9 +32,9 @@ define(["jquery", "core", "google-helper"], function($, core, googleHelper) {
if(blogUrl !== undefined) { if(blogUrl !== undefined) {
publishAttributes.blogUrl = core.checkUrl(blogUrl); publishAttributes.blogUrl = core.checkUrl(blogUrl);
} }
publishAttributes.postId = $("#input-publish-blogger-postid").val() || undefined; publishAttributes.postId = $("#input-publish-postid").val() || undefined;
publishAttributes.labelList = []; publishAttributes.labelList = [];
var labels = $("#input-publish-blogger-labels").val() || undefined; var labels = $("#input-publish-labels").val() || undefined;
if(labels !== undefined) { if(labels !== undefined) {
publishAttributes.labelList = _.chain(labels.split(",")) publishAttributes.labelList = _.chain(labels.split(","))
.map(function(label) { .map(function(label) {

View File

@ -16,6 +16,7 @@ var PROVIDER_BLOGGER = "blogger";
var PROVIDER_DROPBOX = "dropbox"; var PROVIDER_DROPBOX = "dropbox";
var PROVIDER_GDRIVE = "gdrive"; var PROVIDER_GDRIVE = "gdrive";
var PROVIDER_GITHUB = "github"; var PROVIDER_GITHUB = "github";
var PROVIDER_TUMBLR = "tumblr";
var WELCOME_DOCUMENT_TITLE = "Welcome document"; var WELCOME_DOCUMENT_TITLE = "Welcome document";
// Use by Google's client.js // Use by Google's client.js
@ -32,6 +33,7 @@ var GOOGLE_KEY = "AIzaSyAeCU8CGcSkn0z9js6iocHuPBX4f_mMWkw";
var GOOGLE_CLIENT_ID = '241271498917-lev37kef013q85avc91am1gccg5g8lrb.apps.googleusercontent.com'; var GOOGLE_CLIENT_ID = '241271498917-lev37kef013q85avc91am1gccg5g8lrb.apps.googleusercontent.com';
var GITHUB_CLIENT_ID = 'e47fef6055344579799d'; var GITHUB_CLIENT_ID = 'e47fef6055344579799d';
var GATEKEEPER_URL = "http://stackedit-gatekeeper-localhost.herokuapp.com/"; var GATEKEEPER_URL = "http://stackedit-gatekeeper-localhost.herokuapp.com/";
var TUMBLR_PROXY_URL = "http://stackedit-tumblr-proxy-local.herokuapp.com/";
if(location.hostname.indexOf("benweet.github.io") === 0) { if(location.hostname.indexOf("benweet.github.io") === 0) {
BASE_URL = "http://benweet.github.io/stackedit/"; BASE_URL = "http://benweet.github.io/stackedit/";
@ -39,4 +41,5 @@ if(location.hostname.indexOf("benweet.github.io") === 0) {
GOOGLE_CLIENT_ID = '241271498917-jpto9lls9fqnem1e4h6ppds9uob8rpvu.apps.googleusercontent.com'; GOOGLE_CLIENT_ID = '241271498917-jpto9lls9fqnem1e4h6ppds9uob8rpvu.apps.googleusercontent.com';
GITHUB_CLIENT_ID = 'fa0d09514da8377ee32e'; GITHUB_CLIENT_ID = 'fa0d09514da8377ee32e';
GATEKEEPER_URL = "http://stackedit-gatekeeper.herokuapp.com/"; GATEKEEPER_URL = "http://stackedit-gatekeeper.herokuapp.com/";
TUMBLR_PROXY_URL = "http://stackedit-tumblr-proxy.herokuapp.com/";
} }

View File

@ -53,7 +53,7 @@ define(["jquery", "core", "dropbox-helper"], function($, core, dropboxHelper) {
dropboxProvider.importFiles = function() { dropboxProvider.importFiles = function() {
dropboxHelper.picker(function(error, paths) { dropboxHelper.picker(function(error, paths) {
if(error) { if(error || paths.length === 0) {
return; return;
} }
var importPaths = []; var importPaths = [];

View File

@ -40,7 +40,7 @@ define(["jquery", "core", "google-helper", "underscore"], function($, core, goog
gdriveProvider.importFiles = function() { gdriveProvider.importFiles = function() {
googleHelper.picker(function(error, ids) { googleHelper.picker(function(error, ids) {
if(ids === undefined) { if(error || ids.length === 0) {
return; return;
} }
var importIds = []; var importIds = [];

View File

@ -75,7 +75,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
localStorage.removeItem("githubCode"); localStorage.removeItem("githubCode");
task.chain(getToken); task.chain(getToken);
} }
}); }, 500);
} }
function getToken() { function getToken() {
$.getJSON(GATEKEEPER_URL + "authenticate/" + code, function(data) { $.getJSON(GATEKEEPER_URL + "authenticate/" + code, function(data) {
@ -156,6 +156,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
errorMsg = "Could not publish on GitHub."; errorMsg = "Could not publish on GitHub.";
if (error.error === 401 || error.error === 403) { if (error.error === 401 || error.error === 403) {
github = undefined; github = undefined;
localStorage.removeItem("githubToken");
errorMsg = "Access to GitHub account is not authorized."; errorMsg = "Access to GitHub account is not authorized.";
task.retry(new Error(errorMsg), 1); task.retry(new Error(errorMsg), 1);
return; return;

2
js/main-min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
define(["jquery", "core", "github-provider", "blogger-provider", "dropbox-provider", "gdrive-provider", "underscore"], function($, core) { define(["jquery", "core", "github-provider", "blogger-provider", "dropbox-provider", "gdrive-provider", "tumblr-provider", "underscore"], function($, core) {
var publisher = {}; var publisher = {};

164
js/tumblr-helper.js Normal file
View File

@ -0,0 +1,164 @@
define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
var oauthParams = undefined;
var tumblrHelper = {};
// Only used to check the offline status
function connect(task) {
task.onRun(function() {
if(core.isOffline === true) {
task.error(new Error("Operation not available in offline mode."));
return;
}
task.chain();
});
}
// Try to authenticate with Oauth
function authenticate(task) {
var authWindow = undefined;
var intervalId = undefined;
task.onRun(function() {
if (oauthParams !== undefined) {
task.chain();
return;
}
var serializedOauthParams = localStorage["tumblrOauthParams"];
if(serializedOauthParams !== undefined) {
oauthParams = JSON.parse(serializedOauthParams);
task.chain();
return;
}
core.showMessage("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;
var oauth_object = undefined;
function getOauthToken() {
$.getJSON(TUMBLR_PROXY_URL + "request_token", function(data) {
if(data.oauth_token !== undefined) {
oauth_object = data;
task.chain(getVerifier);
}
else {
task.error(new Error(errorMsg));
}
});
}
function getVerifier() {
localStorage.removeItem("tumblrVerifier");
authWindow = core.popupWindow(
'tumblr-oauth-client.html?oauth_token=' + oauth_object.oauth_token,
'stackedit-tumblr-oauth', 800, 600);
authWindow.focus();
intervalId = setInterval(function() {
if(authWindow.closed === true) {
clearInterval(intervalId);
authWindow = undefined;
intervalId = undefined;
oauth_object.oauth_verifier = localStorage["tumblrVerifier"];
if(oauth_object.oauth_verifier === undefined) {
task.error(new Error(errorMsg));
return;
}
localStorage.removeItem("tumblrVerifier");
task.chain(getAccessToken);
}
}, 500);
}
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);
oauthParams = data;
task.chain();
}
else {
task.error(new Error(errorMsg));
}
});
}
task.chain(getOauthToken);
});
task.onError(function() {
if(intervalId !== undefined) {
clearInterval(intervalId);
}
if(authWindow !== undefined) {
authWindow.close();
}
});
}
tumblrHelper.upload = function(blogHostname, postId, tags, format, title, content, callback) {
callback = callback || core.doNothing;
var task = asyncRunner.createTask();
connect(task);
authenticate(task);
task.onRun(function() {
var data = $.extend({
blog_hostname: blogHostname,
post_id: postId,
tags: tags,
format: format,
title: title,
content: content
}, oauthParams);
$.ajax({
url : TUMBLR_PROXY_URL + "post",
data: data,
type: "POST",
dataType : "json",
timeout : AJAX_TIMEOUT
}).done(function(post, textStatus, jqXHR) {
postId = post.id;
task.chain();
}).fail(function(jqXHR) {
var error = {
code: jqXHR.status,
message: jqXHR.statusText
};
// Handle error
if(error.code === 404 && postId !== undefined) {
error = 'Post ' + postId + ' not found on Blogger.|removePublish';
}
handleError(error, task);
});
});
task.onSuccess(function() {
callback(undefined, postId);
});
task.onError(function(error) {
callback(error);
});
asyncRunner.addTask(task);
};
function handleError(error, task) {
var errorMsg = undefined;
if (error) {
console.error(error);
// Try to analyze the error
if (typeof error === "string") {
errorMsg = error;
}
else {
errorMsg = "Could not publish on Tumblr.";
if (error.code === 401 || error.code === 403) {
oauthParams = undefined;
localStorage.removeItem("tumblrOauthParams");
errorMsg = "Access to Tumblr account is not authorized.";
task.retry(new Error(errorMsg), 1);
return;
} else if (error.code <= 0) {
core.setOffline();
errorMsg = "|stopPublish";
}
}
}
task.error(new Error(errorMsg));
}
return tumblrHelper;
});

43
js/tumblr-provider.js Normal file
View File

@ -0,0 +1,43 @@
define(["jquery", "core", "tumblr-helper"], function($, core, tumblrHelper) {
var tumblrProvider = {
providerId: PROVIDER_TUMBLR,
providerName: "Tumblr"
};
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) {
if(error) {
callback(error);
return;
}
publishAttributes.postId = postId;
callback();
}
);
};
tumblrProvider.newPublishAttributes = function(event) {
var publishAttributes = {};
publishAttributes.blogHostname = core
.getInputValue(
$("#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 = $("#input-publish-postid").val() || undefined;
publishAttributes.tags = $("#input-publish-tags").val() || undefined;
if(event.isPropagationStopped()) {
return undefined;
}
return publishAttributes;
};
return tumblrProvider;
});

26
tumblr-oauth-client.html Normal file
View File

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en">
<head>
<script type="text/javascript">
function getParameter(name) {
var regex = new RegExp(name + "=(.+?)(&|$)");
try {
return decodeURI(regex.exec(location.search)[1]);
} catch (e) {
return undefined;
}
}
var oauth_token = getParameter("oauth_token");
var oauth_verifier = getParameter("oauth_verifier");
if (oauth_token && !oauth_verifier) {
window.location.href = "http://www.tumblr.com/oauth/authorize?oauth_token="
+ oauth_token;
} else {
if (oauth_verifier) {
localStorage["tumblrVerifier"] = oauth_verifier;
}
window.close();
}
</script>
</head>
</html>