Stackedit/public/res/publisher.js

363 lines
15 KiB
JavaScript
Raw Permalink Normal View History

2013-05-26 22:59:03 +00:00
define([
"jquery",
2013-05-27 19:45:33 +00:00
"underscore",
2013-05-26 22:59:03 +00:00
"utils",
2013-05-27 19:45:33 +00:00
"settings",
2013-07-30 08:46:36 +00:00
"eventMgr",
2013-06-10 21:22:32 +00:00
"fileSystem",
"fileMgr",
2013-05-26 22:59:03 +00:00
"sharing",
2013-06-22 23:48:57 +00:00
"classes/Provider",
2013-09-22 22:16:59 +00:00
"classes/AsyncTask",
"config",
2013-06-10 21:22:32 +00:00
"providers/bloggerProvider",
"providers/dropboxProvider",
"providers/gistProvider",
"providers/githubProvider",
"providers/gdriveProvider",
"providers/sshProvider",
"providers/tumblrProvider",
"providers/wordpressProvider"
2013-09-22 22:16:59 +00:00
], function($, _, utils, settings, eventMgr, fileSystem, fileMgr, sharing, Provider, AsyncTask) {
2013-04-09 07:58:06 +00:00
2013-05-29 19:55:23 +00:00
var publisher = {};
// Create a map with providerId: providerModule
var providerMap = _.chain(arguments).map(function(argument) {
2013-06-22 23:48:57 +00:00
return argument instanceof Provider && [
2013-05-29 19:55:23 +00:00
argument.providerId,
argument
];
}).compact().object().value();
// Retrieve publish locations from localStorage
_.each(fileSystem, function(fileDesc) {
2013-06-03 22:19:52 +00:00
_.each(utils.retrieveIndexArray(fileDesc.fileIndex + ".publish"), function(publishIndex) {
try {
var publishAttributes = JSON.parse(localStorage[publishIndex]);
// Store publishIndex
publishAttributes.publishIndex = publishIndex;
// Replace provider ID by provider module in attributes
var provider = providerMap[publishAttributes.provider];
if(!provider) {
throw new Error("Invalid provider ID: " + publishAttributes.provider);
}
publishAttributes.provider = provider;
2013-06-03 22:19:52 +00:00
fileDesc.publishLocations[publishIndex] = publishAttributes;
}
catch(e) {
// localStorage can be corrupted
2013-07-30 08:46:36 +00:00
eventMgr.onError(e);
2013-06-03 22:19:52 +00:00
// Remove publish location
utils.removeIndexFromArray(fileDesc.fileIndex + ".publish", publishIndex);
localStorage.removeItem(publishIndex);
}
2013-05-29 19:55:23 +00:00
});
});
// Apply template to the current document
2013-06-16 10:47:35 +00:00
publisher.applyTemplate = function(fileDesc, publishAttributes, html) {
2013-05-29 19:55:23 +00:00
try {
2013-08-22 19:10:57 +00:00
var template = (publishAttributes && publishAttributes.customTmpl) || settings.template;
return _.template(template, {
2013-05-29 19:55:23 +00:00
documentTitle: fileDesc.title,
2013-06-16 10:47:35 +00:00
documentMarkdown: fileDesc.content,
documentHTML: html,
2013-10-06 14:34:40 +00:00
frontMatter: fileDesc.frontMatter,
2013-05-29 19:55:23 +00:00
publishAttributes: publishAttributes
});
}
catch(e) {
2013-07-30 08:46:36 +00:00
eventMgr.onError(e);
2013-06-16 10:47:35 +00:00
return e.message;
2013-05-29 19:55:23 +00:00
}
};
// Used to get content to publish
2013-06-16 10:47:35 +00:00
function getPublishContent(fileDesc, publishAttributes, html) {
2013-05-29 19:55:23 +00:00
if(publishAttributes.format === undefined) {
2013-08-22 19:10:57 +00:00
publishAttributes.format = utils.getInputRadio("radio-publish-format");
if(publishAttributes.format == 'template' && utils.getInputChecked("#checkbox-publish-custom-template")) {
publishAttributes.customTmpl = utils.getInputValue('#textarea-publish-custom-template');
}
2013-05-29 19:55:23 +00:00
}
if(publishAttributes.format == "markdown") {
2013-06-16 10:47:35 +00:00
return fileDesc.content;
2013-05-29 19:55:23 +00:00
}
else if(publishAttributes.format == "html") {
2013-06-16 10:47:35 +00:00
return html;
2013-05-29 19:55:23 +00:00
}
else {
2013-06-16 10:47:35 +00:00
return publisher.applyTemplate(fileDesc, publishAttributes, html);
2013-05-29 19:55:23 +00:00
}
}
// Recursive function to publish a file on multiple locations
var publishAttributesList = [];
2013-06-16 10:47:35 +00:00
var publishFileDesc = undefined;
var publishHTML = undefined;
2013-05-29 19:55:23 +00:00
function publishLocation(callback, errorFlag) {
// No more publish location for this document
if(publishAttributesList.length === 0) {
callback(errorFlag);
return;
}
// Dequeue a synchronized location
var publishAttributes = publishAttributesList.pop();
2013-08-13 00:03:38 +00:00
2013-06-16 10:47:35 +00:00
// Format the content
var content = getPublishContent(publishFileDesc, publishAttributes, publishHTML);
2013-10-06 14:34:40 +00:00
var title = (publishFileDesc.frontMatter || {}).title || publishFileDesc.title;
2013-05-29 19:55:23 +00:00
// Call the provider
2013-10-06 14:34:40 +00:00
publishAttributes.provider.publish(publishAttributes, publishFileDesc.frontMatter, title, content, function(error) {
2013-05-29 19:55:23 +00:00
if(error !== undefined) {
var errorMsg = error.toString();
if(errorMsg.indexOf("|removePublish") !== -1) {
2013-06-16 10:47:35 +00:00
publishFileDesc.removePublishLocation(publishAttributes);
2013-07-30 08:46:36 +00:00
eventMgr.onPublishRemoved(publishFileDesc, publishAttributes);
2013-05-29 19:55:23 +00:00
}
if(errorMsg.indexOf("|stopPublish") !== -1) {
callback(error);
return;
}
}
publishLocation(callback, errorFlag || error);
});
}
2013-08-13 00:03:38 +00:00
2013-07-24 23:20:56 +00:00
// Get the html from the onPreviewFinished callback
var previewHtml = undefined;
2013-07-30 08:46:36 +00:00
eventMgr.addListener("onPreviewFinished", function(html) {
2013-07-24 23:20:56 +00:00
previewHtml = html;
});
2013-08-04 00:53:46 +00:00
// Listen to offline status changes
var isOffline = false;
eventMgr.addListener("onOfflineChanged", function(isOfflineParam) {
isOffline = isOfflineParam;
});
2013-05-29 19:55:23 +00:00
var publishRunning = false;
publisher.publish = function() {
// If publish is running or offline
2013-08-04 00:53:46 +00:00
if(publishRunning === true || isOffline === true) {
2013-05-29 19:55:23 +00:00
return;
}
publishRunning = true;
2013-07-30 08:46:36 +00:00
eventMgr.onPublishRunning(true);
2013-06-19 20:33:46 +00:00
publishFileDesc = fileMgr.currentFile;
2013-07-24 23:20:56 +00:00
publishHTML = previewHtml;
2013-06-16 10:47:35 +00:00
publishAttributesList = _.values(publishFileDesc.publishLocations);
2013-05-29 19:55:23 +00:00
publishLocation(function(errorFlag) {
publishRunning = false;
2013-07-30 08:46:36 +00:00
eventMgr.onPublishRunning(false);
2013-05-29 19:55:23 +00:00
if(errorFlag === undefined) {
2013-07-30 08:46:36 +00:00
eventMgr.onPublishSuccess(publishFileDesc);
2013-05-29 19:55:23 +00:00
}
});
};
// Generate a publishIndex associated to a file and store publishAttributes
function createPublishIndex(fileDesc, publishAttributes) {
var publishIndex = undefined;
do {
publishIndex = "publish." + utils.randomString();
} while (_.has(localStorage, publishIndex));
publishAttributes.publishIndex = publishIndex;
2013-06-16 10:47:35 +00:00
fileDesc.addPublishLocation(publishAttributes);
2013-07-30 08:46:36 +00:00
eventMgr.onNewPublishSuccess(fileDesc, publishAttributes);
2013-05-29 19:55:23 +00:00
}
// Initialize the "New publication" dialog
var newLocationProvider = undefined;
function initNewLocation(provider) {
var defaultPublishFormat = provider.defaultPublishFormat || "markdown";
newLocationProvider = provider;
$(".publish-provider-name").text(provider.providerName);
// Show/hide controls depending on provider
2013-10-06 14:34:40 +00:00
$('.modal-publish [class*=" modal-publish-"]').hide().filter(".modal-publish-" + provider.providerId).show();
2013-05-29 19:55:23 +00:00
// Reset fields
utils.resetModalInputs();
2013-08-22 19:10:57 +00:00
utils.setInputRadio("radio-publish-format", defaultPublishFormat);
utils.setInputChecked("#checkbox-publish-custom-template", false);
utils.setInputValue('#textarea-publish-custom-template', settings.template);
2013-05-29 19:55:23 +00:00
// Load preferences
2013-06-03 22:19:52 +00:00
var publishPreferences = utils.retrieveIgnoreError(provider.providerId + ".publishPreferences");
if(publishPreferences) {
2013-05-29 19:55:23 +00:00
_.each(provider.publishPreferencesInputIds, function(inputId) {
2013-08-23 23:50:14 +00:00
var publishPreferenceValue = publishPreferences[inputId];
if(_.isBoolean(publishPreferenceValue)) {
utils.setInputChecked("#input-publish-" + inputId, publishPreferenceValue);
}
else {
utils.setInputValue("#input-publish-" + inputId, publishPreferenceValue);
}
2013-05-29 19:55:23 +00:00
});
utils.setInputRadio("radio-publish-format", publishPreferences.format);
2013-08-23 23:50:14 +00:00
utils.setInputChecked("#checkbox-publish-custom-template", publishPreferences.customTmpl !== undefined);
utils.setInputValue('#textarea-publish-custom-template', publishPreferences.customTmpl || settings.template);
2013-05-29 19:55:23 +00:00
}
// Open dialog box
2013-08-11 00:52:05 +00:00
$(".modal-publish").modal();
2013-05-29 19:55:23 +00:00
}
// Add a new publish location to a local document
function performNewLocation(event) {
var provider = newLocationProvider;
var publishAttributes = provider.newPublishAttributes(event);
if(publishAttributes === undefined) {
return;
}
// Perform provider's publishing
2013-06-19 20:33:46 +00:00
var fileDesc = fileMgr.currentFile;
2013-07-24 23:20:56 +00:00
var html = previewHtml;
2013-06-16 10:47:35 +00:00
var content = getPublishContent(fileDesc, publishAttributes, html);
2013-10-06 14:34:40 +00:00
var title = (fileDesc.frontMatter && fileDesc.frontMatter.title) || fileDesc.title;
provider.publish(publishAttributes, fileDesc.frontMatter, title, content, function(error) {
2013-05-29 19:55:23 +00:00
if(error === undefined) {
2013-05-29 23:04:52 +00:00
publishAttributes.provider = provider;
2013-05-29 19:55:23 +00:00
sharing.createLink(publishAttributes, function() {
createPublishIndex(fileDesc, publishAttributes);
});
}
});
// Store input values as preferences for next time we open the publish
// dialog
var publishPreferences = {};
_.each(provider.publishPreferencesInputIds, function(inputId) {
2013-08-23 23:50:14 +00:00
var inputElt = document.getElementById("input-publish-" + inputId);
if(inputElt.type == 'checkbox') {
publishPreferences[inputId] = inputElt.checked;
}
else {
publishPreferences[inputId] = inputElt.value;
}
2013-05-29 19:55:23 +00:00
});
publishPreferences.format = publishAttributes.format;
2013-08-22 19:10:57 +00:00
publishPreferences.customTmpl = publishAttributes.customTmpl;
2013-05-29 19:55:23 +00:00
localStorage[provider.providerId + ".publishPreferences"] = JSON.stringify(publishPreferences);
}
2013-09-22 22:16:59 +00:00
// Listen to offline status changes
var isOffline = false;
eventMgr.addListener("onOfflineChanged", function(isOfflineParam) {
isOffline = isOfflineParam;
});
2013-08-13 00:03:38 +00:00
var initPublishButtonTmpl = [
'<li>',
' <a href="#"',
' class="action-init-publish-<%= provider.providerId %>">',
' <i class="icon-provider-<%= provider.providerId %>"></i> <%= provider.providerName %>',
' </a>',
'</li>'
].join('');
2013-08-04 00:53:46 +00:00
eventMgr.addListener("onReady", function() {
2013-08-21 00:16:10 +00:00
if(viewerMode === false) {
// Add every provider in the panel menu
var publishMenuElt = document.querySelector('.menu-panel .collapse-publish-on .nav');
var publishMenuHtml = _.reduce(providerMap, function(result, provider) {
return result + _.template(initPublishButtonTmpl, {
provider: provider
});
}, '');
publishMenuElt.innerHTML = publishMenuHtml;
_.each(providerMap, function(provider) {
// Click on open publish dialog
$(publishMenuElt.querySelector('.action-init-publish-' + provider.providerId)).click(function() {
initNewLocation(provider);
});
// Click on perform new publication
$(".action-publish-" + provider.providerId).click(function() {
initNewLocation(provider);
});
2013-05-29 19:55:23 +00:00
});
2013-08-21 00:16:10 +00:00
}
2013-08-23 23:50:14 +00:00
2013-08-21 00:16:10 +00:00
//
2013-05-29 19:55:23 +00:00
$(".action-process-publish").click(performNewLocation);
2013-08-23 23:50:14 +00:00
var $customTmplCollapseElt = $('.publish-custom-template-collapse').collapse({
toggle: false
});
2013-08-22 19:10:57 +00:00
var $customTmplTextareaElt = $('#textarea-publish-custom-template');
2013-08-23 23:50:14 +00:00
var doCustomTmplCollapse = _.debounce(function() {
$customTmplCollapseElt.collapse(utils.getInputRadio("radio-publish-format") == 'template' ? 'show' : 'hide');
}, 100);
2013-08-22 19:10:57 +00:00
$("#checkbox-publish-custom-template").change(function() {
$customTmplTextareaElt.prop('disabled', !this.checked);
});
$("input:radio[name=radio-publish-format]").change(function() {
2013-08-23 23:50:14 +00:00
doCustomTmplCollapse();
});
$('.modal-publish').on('hidden.bs.modal', function() {
$customTmplCollapseElt.collapse('hide');
2013-08-22 19:10:57 +00:00
});
2013-05-29 19:55:23 +00:00
// Save As menu items
$(".action-download-md").click(function() {
2013-09-10 23:51:37 +00:00
var content = fileMgr.currentFile.content;
2013-06-19 20:33:46 +00:00
var title = fileMgr.currentFile.title;
2013-05-29 19:55:23 +00:00
utils.saveAs(content, title + ".md");
});
$(".action-download-html").click(function() {
2013-06-19 20:33:46 +00:00
var title = fileMgr.currentFile.title;
2013-07-24 23:20:56 +00:00
utils.saveAs(previewHtml, title + ".html");
2013-05-29 19:55:23 +00:00
});
$(".action-download-template").click(function() {
2013-06-19 20:33:46 +00:00
var fileDesc = fileMgr.currentFile;
2013-07-24 23:20:56 +00:00
var content = publisher.applyTemplate(fileDesc, undefined, previewHtml);
2013-06-16 10:47:35 +00:00
utils.saveAs(content, fileDesc.title + (settings.template.indexOf("documentHTML") === -1 ? ".md" : ".html"));
2013-05-29 19:55:23 +00:00
});
2013-09-22 22:16:59 +00:00
$(".action-download-pdf").click(function() {
var fileDesc = fileMgr.currentFile;
var content = publisher.applyTemplate(fileDesc, {
customTmpl: settings.pdfTemplate
}, previewHtml);
var task = new AsyncTask();
var pdf = undefined;
task.onRun(function() {
if(isOffline === true) {
eventMgr.onError("Operation not available in offline mode.");
task.chain();
return;
}
var xhr = new XMLHttpRequest();
xhr.open('POST', HTMLTOPDF_URL, true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.responseType = 'blob';
xhr.onreadystatechange = function() {
if(this.readyState == 4) {
if(this.status == 200) {
pdf = this.response;
}
else {
eventMgr.onError("Error when trying to generate PDF: " + this.status);
}
task.chain();
}
};
xhr.send(content);
});
task.onSuccess(function() {
if(pdf !== undefined) {
utils.saveAs(pdf, fileMgr.currentFile.title + ".pdf");
}
});
task.enqueue();
});
2013-05-29 19:55:23 +00:00
});
2013-07-30 08:46:36 +00:00
eventMgr.onPublisherCreated(publisher);
2013-05-29 19:55:23 +00:00
return publisher;
2013-04-09 07:58:06 +00:00
});