Implemented PDF options

This commit is contained in:
benweet 2014-08-14 00:44:33 +01:00
parent ae8adddf5d
commit 3f8b5a865a
10 changed files with 449 additions and 372 deletions

View File

@ -18,10 +18,10 @@ module.exports = function(req, res, next) {
} }
// Margins // Margins
var marginRight = parseInt(options.marginRight);
params.push('-R', isNaN(marginRight) ? 25 : marginRight);
var marginTop = parseInt(options.marginTop); var marginTop = parseInt(options.marginTop);
params.push('-T', isNaN(marginTop) ? 25 : marginTop); params.push('-T', isNaN(marginTop) ? 25 : marginTop);
var marginRight = parseInt(options.marginRight);
params.push('-R', isNaN(marginRight) ? 25 : marginRight);
var marginBottom = parseInt(options.marginBottom); var marginBottom = parseInt(options.marginBottom);
params.push('-B', isNaN(marginBottom) ? 25 : marginBottom); params.push('-B', isNaN(marginBottom) ? 25 : marginBottom);
var marginLeft = parseInt(options.marginLeft); var marginLeft = parseInt(options.marginLeft);
@ -42,8 +42,7 @@ module.exports = function(req, res, next) {
options.footerFontSize && params.push('--footer-font-size ', options.footerFontSize); options.footerFontSize && params.push('--footer-font-size ', options.footerFontSize);
// Page size // Page size
var pageSize = options.pageSize; params.push('--page-size', authorizedPageSizes.indexOf(options.pageSize) === -1 ? 'A4' : options.pageSize);
params.push('--page-size', authorizedPageSizes.indexOf(pageSize) === -1 ? 'A4' : pageSize);
// wkhtmltopdf can't access /dev/stdout on Amazon EC2 for some reason // wkhtmltopdf can't access /dev/stdout on Amazon EC2 for some reason
var filePath = '/tmp/' + Date.now() + '.pdf'; var filePath = '/tmp/' + Date.now() + '.pdf';

View File

@ -14,9 +14,10 @@ define([
"text!html/bodyIndex.html", "text!html/bodyIndex.html",
"text!html/bodyViewer.html", "text!html/bodyViewer.html",
"text!html/tooltipSettingsTemplate.html", "text!html/tooltipSettingsTemplate.html",
"text!html/tooltipSettingsPdfOptions.html",
"storage", "storage",
'pagedown' 'pagedown'
], function($, _, crel, editor, layout, constants, utils, storage, settings, eventMgr, MonetizeJS, bodyIndexHTML, bodyViewerHTML, settingsTemplateTooltipHTML) { ], function($, _, crel, editor, layout, constants, utils, storage, settings, eventMgr, MonetizeJS, bodyIndexHTML, bodyViewerHTML, settingsTemplateTooltipHTML, settingsPdfOptionsTooltipHTML) {
var core = {}; var core = {};
@ -142,8 +143,8 @@ define([
utils.setInputValue("#textarea-settings-publish-template", settings.template); utils.setInputValue("#textarea-settings-publish-template", settings.template);
// PDF template // PDF template
utils.setInputValue("#textarea-settings-pdf-template", settings.pdfTemplate); utils.setInputValue("#textarea-settings-pdf-template", settings.pdfTemplate);
// PDF page size // PDF options
utils.setInputValue("#input-settings-pdf-page-size", settings.pdfPageSize); utils.setInputValue("#textarea-settings-pdf-options", settings.pdfOptions);
// SSH proxy // SSH proxy
utils.setInputValue("#input-settings-ssh-proxy", settings.sshProxy); utils.setInputValue("#input-settings-ssh-proxy", settings.sshProxy);
@ -189,8 +190,8 @@ define([
newSettings.template = utils.getInputTextValue("#textarea-settings-publish-template", event); newSettings.template = utils.getInputTextValue("#textarea-settings-publish-template", event);
// PDF template // PDF template
newSettings.pdfTemplate = utils.getInputTextValue("#textarea-settings-pdf-template", event); newSettings.pdfTemplate = utils.getInputTextValue("#textarea-settings-pdf-template", event);
// PDF page size // PDF options
newSettings.pdfPageSize = utils.getInputValue("#input-settings-pdf-page-size"); newSettings.pdfOptions = utils.getInputJSONValue("#textarea-settings-pdf-options", event);
// SSH proxy // SSH proxy
newSettings.sshProxy = utils.checkUrl(utils.getInputTextValue("#input-settings-ssh-proxy", event), true); newSettings.sshProxy = utils.checkUrl(utils.getInputTextValue("#input-settings-ssh-proxy", event), true);
@ -331,10 +332,12 @@ define([
}); });
var $alerts = $(); var $alerts = $();
function hasPaid(payments) { function isSponsor(payments) {
return payments && ( var result = payments && (
(payments.chargeOption && payments.chargeOption.alias == 'once') || (payments.chargeOption && payments.chargeOption.alias == 'once') ||
(payments.subscriptionOption && payments.subscriptionOption.alias == 'yearly')); (payments.subscriptionOption && payments.subscriptionOption.alias == 'yearly'));
eventMgr.isSponsor = result;
return result;
} }
function removeAlerts() { function removeAlerts() {
@ -346,11 +349,10 @@ define([
monetize.getPayments({ monetize.getPayments({
pricingOptions: [ pricingOptions: [
'once', 'once',
'monthly',
'yearly' 'yearly'
] ]
}, function(err, payments) { }, function(err, payments) {
if(hasPaid(payments)) { if(isSponsor(payments)) {
eventMgr.onMessage('Thank you for sponsoring StackEdit!'); eventMgr.onMessage('Thank you for sponsoring StackEdit!');
removeAlerts(); removeAlerts();
} }
@ -363,7 +365,7 @@ define([
} }
monetize.getPaymentsImmediate(function(err, payments) { monetize.getPaymentsImmediate(function(err, payments) {
removeAlerts(); removeAlerts();
if(!hasPaid(payments)) { if(!isSponsor(payments)) {
_.each(document.querySelectorAll('.modal-body'), function(modalBodyElt) { _.each(document.querySelectorAll('.modal-body'), function(modalBodyElt) {
var $elt = $('<div class="alert alert-danger">Please consider <a href="#">sponsoring StackEdit</a> for $5/year (or <a href="#">sign in</a> if you\'re already a sponsor).</div>'); var $elt = $('<div class="alert alert-danger">Please consider <a href="#">sponsoring StackEdit</a> for $5/year (or <a href="#">sign in</a> if you\'re already a sponsor).</div>');
$elt.find('a').click(performPayment); $elt.find('a').click(performPayment);
@ -542,6 +544,7 @@ define([
'<b class="text-danger">NOTE: Backlinks in Stack Exchange Q/A are not welcome.</b>' '<b class="text-danger">NOTE: Backlinks in Stack Exchange Q/A are not welcome.</b>'
].join('')); ].join(''));
utils.createTooltip(".tooltip-template", settingsTemplateTooltipHTML); utils.createTooltip(".tooltip-template", settingsTemplateTooltipHTML);
utils.createTooltip(".tooltip-pdf-options", settingsPdfOptionsTooltipHTML);
// Avoid dropdown panels to close on click // Avoid dropdown panels to close on click
$("div.dropdown-menu").click(function(e) { $("div.dropdown-menu").click(function(e) {

View File

@ -10,6 +10,11 @@ define([
var dialogAbout = new Extension("dialogAbout", 'Dialog "About"'); var dialogAbout = new Extension("dialogAbout", 'Dialog "About"');
var eventMgr;
dialogAbout.onEventMgrCreated = function(eventMgrParameter) {
eventMgr = eventMgrParameter;
};
var monetize = new MonetizeJS({ var monetize = new MonetizeJS({
applicationID: 'iklMbzDI7dvMEScb' applicationID: 'iklMbzDI7dvMEScb'
}); });
@ -22,6 +27,7 @@ define([
monetize.getPayments({ monetize.getPayments({
summary: true summary: true
}, function() { }, function() {
eventMgr.onMessage('Please refresh the page for your sponsorship to take effect.');
}); });
}); });
}; };

View File

@ -89,7 +89,7 @@
<a href="#" data-toggle="collapse" data-target=".collapse-synchronize" <a href="#" data-toggle="collapse" data-target=".collapse-synchronize"
class="list-group-item"> class="list-group-item">
<div><i class="icon-refresh"></i> Synchronize</div> <div><i class="icon-refresh"></i> Synchronize</div>
<small>Backup, collaborate in the cloud</small> <small>Backup, collaborate...</small>
</a> </a>
<div class="sub-menu collapse collapse-synchronize clearfix"> <div class="sub-menu collapse collapse-synchronize clearfix">
<ul class="nav alert alert-danger show-already-synchronized"> <ul class="nav alert alert-danger show-already-synchronized">
@ -159,7 +159,7 @@
<li><a class="action-download-template" href="#"><i <li><a class="action-download-template" href="#"><i
class="icon-download"></i> Using template</a></li> class="icon-download"></i> Using template</a></li>
<li><a class="action-download-pdf" href="#"><i <li><a class="action-download-pdf" href="#"><i
class="icon-download"></i> As PDF</a></li> class="icon-download"></i> As PDF <sup class="text-danger">sponsor</sup></a></li>
</ul> </ul>
</div> </div>
@ -1072,14 +1072,12 @@
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="col-sm-4 control-label" for="input-settings-pdf-page-size">PDF page size</label> <label class="col-sm-4 control-label" for="textarea-settings-pdf-options">PDF options
<a href="#" class="tooltip-pdf-options">(?)</a>
</label>
<div class="col-sm-7"> <div class="col-sm-7">
<select id="input-settings-pdf-page-size" class="form-control"> <textarea id="textarea-settings-pdf-options"
<option value="A3">A3</option> class="form-control"></textarea>
<option value="A4">A4</option>
<option value="Legal">Legal</option>
<option value="Letter">Letter</option>
</select>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
@ -1303,4 +1301,24 @@
</div> </div>
<div class="modal fade modal-sponsorship-required">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h2 class="modal-title">Sponsorship required</h2>
</div>
<div class="modal-body">
<p>This feature is restricted to sponsors only as it's a web service hosted on Amazon EC2.
Note that sponsoring StackEdit would cost you only <b>$5/year</b>...</p>
</div>
<div class="modal-footer">
<a href="#" class="btn btn-primary"
data-dismiss="modal">Close</a>
</div>
</div>
</div>
</div>
<div id="dropboxjs" data-app-key="x0k2l8puemfvg0o"></div> <div id="dropboxjs" data-app-key="x0k2l8puemfvg0o"></div>

View File

@ -0,0 +1,19 @@
Option object in JSON format. Possible attributes:
<br><br>
<b>marginTop</b>,
<b>marginRight</b>,
<b>marginBottom</b>,
<b>marginLeft</b>,<br>
<b>headerCenter</b>,
<b>headerLeft</b>,
<b>headerRight</b>,
<b>headerFontName</b>,
<b>headerFontSize</b>,<br>
<b>footerCenter</b>,
<b>footerLeft</b>,
<b>footerRight</b>,
<b>footerFontName</b>,
<b>footerFontSize</b><br>
<b>pageSize</b><br><br>
Please check out the
<a target="_blank" href="http://wkhtmltopdf.org/usage/wkhtmltopdf.txt">wkhtmltopdf documentation</a> for more info.

View File

@ -86,7 +86,7 @@ define([
var syncIndex = createSyncIndex(path); var syncIndex = createSyncIndex(path);
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex); var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
if(fileDesc !== undefined) { if(fileDesc !== undefined) {
return eventMgr.onError('"' + fileDesc.title + '" was already imported.'); return eventMgr.onError('"' + fileDesc.title + '" is already in your local documents.');
} }
importPaths.push(path); importPaths.push(path);
}); });

View File

@ -91,7 +91,7 @@ define([
var syncIndex = createSyncIndex(doc.id); var syncIndex = createSyncIndex(doc.id);
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex); var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
if(fileDesc !== undefined) { if(fileDesc !== undefined) {
return eventMgr.onError('"' + fileDesc.title + '" was already imported.'); return eventMgr.onError('"' + fileDesc.title + '" is already in your local documents.');
} }
importIds.push(doc.id); importIds.push(doc.id);
}); });

View File

@ -1,376 +1,391 @@
define([ define([
"jquery", "jquery",
"underscore", "underscore",
"constants", "constants",
"utils", "utils",
"storage", "storage",
"settings", "settings",
"eventMgr", "eventMgr",
"fileSystem", "fileSystem",
"fileMgr", "fileMgr",
"sharing", "sharing",
"classes/Provider", "monetizejs",
"classes/AsyncTask", "classes/Provider",
"providers/bloggerProvider", "classes/AsyncTask",
"providers/bloggerPageProvider", "providers/bloggerProvider",
"providers/dropboxProvider", "providers/bloggerPageProvider",
"providers/gistProvider", "providers/dropboxProvider",
"providers/githubProvider", "providers/gistProvider",
"providers/gdriveProvider", "providers/githubProvider",
"providers/gdrivesecProvider", "providers/gdriveProvider",
"providers/gdriveterProvider", "providers/gdrivesecProvider",
"providers/sshProvider", "providers/gdriveterProvider",
"providers/tumblrProvider", "providers/sshProvider",
"providers/wordpressProvider" "providers/tumblrProvider",
], function($, _, constants, utils, storage, settings, eventMgr, fileSystem, fileMgr, sharing, Provider, AsyncTask) { "providers/wordpressProvider"
], function($, _, constants, utils, storage, settings, eventMgr, fileSystem, fileMgr, sharing, MonetizeJS, Provider, AsyncTask) {
var publisher = {}; var publisher = {};
// Create a map with providerId: providerModule // Create a map with providerId: providerModule
var providerMap = _.chain(arguments).map(function(argument) { var providerMap = _.chain(arguments).map(function(argument) {
return argument instanceof Provider && argument.isPublishEnabled === true && [ return argument instanceof Provider && argument.isPublishEnabled === true && [
argument.providerId, argument.providerId,
argument argument
]; ];
}).compact().object().value(); }).compact().object().value();
// Retrieve publish locations from storage // Retrieve publish locations from storage
(function() { (function() {
var publishIndexMap = {}; var publishIndexMap = {};
_.each(fileSystem, function(fileDesc) { _.each(fileSystem, function(fileDesc) {
utils.retrieveIndexArray(fileDesc.fileIndex + ".publish").forEach(function(publishIndex) { utils.retrieveIndexArray(fileDesc.fileIndex + ".publish").forEach(function(publishIndex) {
try { try {
var publishAttributes = JSON.parse(storage[publishIndex]); var publishAttributes = JSON.parse(storage[publishIndex]);
// Store publishIndex // Store publishIndex
publishAttributes.publishIndex = publishIndex; publishAttributes.publishIndex = publishIndex;
// Replace provider ID by provider module in attributes // Replace provider ID by provider module in attributes
var provider = providerMap[publishAttributes.provider]; var provider = providerMap[publishAttributes.provider];
if(!provider) { if(!provider) {
throw new Error("Invalid provider ID: " + publishAttributes.provider); throw new Error("Invalid provider ID: " + publishAttributes.provider);
} }
publishAttributes.provider = provider; publishAttributes.provider = provider;
fileDesc.publishLocations[publishIndex] = publishAttributes; fileDesc.publishLocations[publishIndex] = publishAttributes;
publishIndexMap[publishIndex] = publishAttributes; publishIndexMap[publishIndex] = publishAttributes;
} }
catch(e) { catch(e) {
// storage can be corrupted // storage can be corrupted
eventMgr.onError(e); eventMgr.onError(e);
// Remove publish location // Remove publish location
utils.removeIndexFromArray(fileDesc.fileIndex + ".publish", publishIndex); utils.removeIndexFromArray(fileDesc.fileIndex + ".publish", publishIndex);
} }
}); });
}); });
// Clean fields from deleted files in local storage // Clean fields from deleted files in local storage
Object.keys(storage).forEach(function(key) { Object.keys(storage).forEach(function(key) {
var match = key.match(/publish\.\S+/); var match = key.match(/publish\.\S+/);
if(match && !publishIndexMap.hasOwnProperty(match[0])) { if(match && !publishIndexMap.hasOwnProperty(match[0])) {
storage.removeItem(key); storage.removeItem(key);
} }
}); });
})(); })();
// Apply template to the current document // Apply template to the current document
publisher.applyTemplate = function(fileDesc, publishAttributes, html) { publisher.applyTemplate = function(fileDesc, publishAttributes, html) {
try { try {
var template = (publishAttributes && publishAttributes.customTmpl) || settings.template; var template = (publishAttributes && publishAttributes.customTmpl) || settings.template;
return _.template(template, { return _.template(template, {
documentTitle: fileDesc.title, documentTitle: fileDesc.title,
documentMarkdown: fileDesc.content, documentMarkdown: fileDesc.content,
strippedDocumentMarkdown: fileDesc.content.substring(fileDesc.frontMatter ? fileDesc.frontMatter._frontMatter.length : 0), strippedDocumentMarkdown: fileDesc.content.substring(fileDesc.frontMatter ? fileDesc.frontMatter._frontMatter.length : 0),
documentHTML: html.withoutComments, documentHTML: html.withoutComments,
documentHTMLWithFrontMatter: (fileDesc.frontMatter ? fileDesc.frontMatter._frontMatter : '') + html.withoutComments, documentHTMLWithFrontMatter: (fileDesc.frontMatter ? fileDesc.frontMatter._frontMatter : '') + html.withoutComments,
documentHTMLWithComments: html.withComments, documentHTMLWithComments: html.withComments,
frontMatter: fileDesc.frontMatter, frontMatter: fileDesc.frontMatter,
publishAttributes: publishAttributes publishAttributes: publishAttributes
}); });
} }
catch(e) { catch(e) {
eventMgr.onError(e); eventMgr.onError(e);
return e.message; return e.message;
} }
}; };
// Used to get content to publish // Used to get content to publish
function getPublishContent(fileDesc, publishAttributes, html) { function getPublishContent(fileDesc, publishAttributes, html) {
if(publishAttributes.format === undefined) { if(publishAttributes.format === undefined) {
publishAttributes.format = utils.getInputRadio("radio-publish-format"); publishAttributes.format = utils.getInputRadio("radio-publish-format");
if(publishAttributes.format == 'template' && utils.getInputChecked("#checkbox-publish-custom-template")) { if(publishAttributes.format == 'template' && utils.getInputChecked("#checkbox-publish-custom-template")) {
publishAttributes.customTmpl = utils.getInputValue('#textarea-publish-custom-template'); publishAttributes.customTmpl = utils.getInputValue('#textarea-publish-custom-template');
} }
} }
if(publishAttributes.format == "markdown") { if(publishAttributes.format == "markdown") {
return fileDesc.content; return fileDesc.content;
} }
else if(publishAttributes.format == "html") { else if(publishAttributes.format == "html") {
return html.withoutComments; return html.withoutComments;
} }
else { else {
return publisher.applyTemplate(fileDesc, publishAttributes, html); return publisher.applyTemplate(fileDesc, publishAttributes, html);
} }
} }
// Recursive function to publish a file on multiple locations // Recursive function to publish a file on multiple locations
var publishAttributesList = []; var publishAttributesList = [];
var publishFileDesc; var publishFileDesc;
var publishHTML; var publishHTML;
function publishLocation(callback, errorFlag) {
// No more publish location for this document function publishLocation(callback, errorFlag) {
if(publishAttributesList.length === 0) {
callback(errorFlag);
return;
}
// Dequeue a synchronized location // No more publish location for this document
var publishAttributes = publishAttributesList.pop(); if(publishAttributesList.length === 0) {
callback(errorFlag);
return;
}
// Format the content // Dequeue a synchronized location
var content = getPublishContent(publishFileDesc, publishAttributes, publishHTML); var publishAttributes = publishAttributesList.pop();
var title = (publishFileDesc.frontMatter || {}).title || publishFileDesc.title;
// Call the provider // Format the content
publishAttributes.provider.publish(publishAttributes, publishFileDesc.frontMatter, title, content, function(error) { var content = getPublishContent(publishFileDesc, publishAttributes, publishHTML);
if(error !== undefined) { var title = (publishFileDesc.frontMatter || {}).title || publishFileDesc.title;
var errorMsg = error.toString();
if(errorMsg.indexOf("|removePublish") !== -1) {
publishFileDesc.removePublishLocation(publishAttributes);
eventMgr.onPublishRemoved(publishFileDesc, publishAttributes);
}
if(errorMsg.indexOf("|stopPublish") !== -1) {
callback(error);
return;
}
}
publishLocation(callback, errorFlag || error);
});
}
// Get the html from the onPreviewFinished callback // Call the provider
var currentHTML; publishAttributes.provider.publish(publishAttributes, publishFileDesc.frontMatter, title, content, function(error) {
eventMgr.addListener("onPreviewFinished", function(htmlWithComments, htmlWithoutComments) { if(error !== undefined) {
currentHTML = { var errorMsg = error.toString();
withComments: htmlWithComments, if(errorMsg.indexOf("|removePublish") !== -1) {
withoutComments: htmlWithoutComments publishFileDesc.removePublishLocation(publishAttributes);
}; eventMgr.onPublishRemoved(publishFileDesc, publishAttributes);
}); }
if(errorMsg.indexOf("|stopPublish") !== -1) {
callback(error);
return;
}
}
publishLocation(callback, errorFlag || error);
});
}
// Listen to offline status changes // Get the html from the onPreviewFinished callback
var isOffline = false; var currentHTML;
eventMgr.addListener("onOfflineChanged", function(isOfflineParam) { eventMgr.addListener("onPreviewFinished", function(htmlWithComments, htmlWithoutComments) {
isOffline = isOfflineParam; currentHTML = {
}); withComments: htmlWithComments,
withoutComments: htmlWithoutComments
};
});
var publishRunning = false; // Listen to offline status changes
publisher.publish = function() { var isOffline = false;
// If publish is running or offline eventMgr.addListener("onOfflineChanged", function(isOfflineParam) {
if(publishRunning === true || isOffline === true) { isOffline = isOfflineParam;
return; });
}
publishRunning = true; var publishRunning = false;
eventMgr.onPublishRunning(true); publisher.publish = function() {
publishFileDesc = fileMgr.currentFile; // If publish is running or offline
publishHTML = currentHTML; if(publishRunning === true || isOffline === true) {
publishAttributesList = _.values(publishFileDesc.publishLocations); return;
publishLocation(function(errorFlag) { }
publishRunning = false;
eventMgr.onPublishRunning(false);
if(errorFlag === undefined) {
eventMgr.onPublishSuccess(publishFileDesc);
}
});
};
// Generate a publishIndex associated to a file and store publishAttributes publishRunning = true;
function createPublishIndex(fileDesc, publishAttributes) { eventMgr.onPublishRunning(true);
var publishIndex; publishFileDesc = fileMgr.currentFile;
do { publishHTML = currentHTML;
publishIndex = "publish." + utils.randomString(); publishAttributesList = _.values(publishFileDesc.publishLocations);
} while (_.has(storage, publishIndex)); publishLocation(function(errorFlag) {
publishAttributes.publishIndex = publishIndex; publishRunning = false;
fileDesc.addPublishLocation(publishAttributes); eventMgr.onPublishRunning(false);
eventMgr.onNewPublishSuccess(fileDesc, publishAttributes); if(errorFlag === undefined) {
} eventMgr.onPublishSuccess(publishFileDesc);
}
});
};
// Initialize the "New publication" dialog // Generate a publishIndex associated to a file and store publishAttributes
var newLocationProvider; function createPublishIndex(fileDesc, publishAttributes) {
function initNewLocation(provider) { var publishIndex;
var defaultPublishFormat = provider.defaultPublishFormat || "markdown"; do {
newLocationProvider = provider; publishIndex = "publish." + utils.randomString();
$(".publish-provider-name").text(provider.providerName); } while(_.has(storage, publishIndex));
publishAttributes.publishIndex = publishIndex;
fileDesc.addPublishLocation(publishAttributes);
eventMgr.onNewPublishSuccess(fileDesc, publishAttributes);
}
// Show/hide controls depending on provider // Initialize the "New publication" dialog
$('.modal-publish [class*=" modal-publish-"]').hide().filter(".modal-publish-" + provider.providerId).show(); var newLocationProvider;
// Reset fields function initNewLocation(provider) {
utils.resetModalInputs(); var defaultPublishFormat = provider.defaultPublishFormat || "markdown";
utils.setInputRadio("radio-publish-format", defaultPublishFormat); newLocationProvider = provider;
utils.setInputChecked("#checkbox-publish-custom-template", false); $(".publish-provider-name").text(provider.providerName);
utils.setInputValue('#textarea-publish-custom-template', settings.template);
// Load preferences // Show/hide controls depending on provider
var publishPreferences = utils.retrieveIgnoreError(provider.providerId + ".publishPreferences"); $('.modal-publish [class*=" modal-publish-"]').hide().filter(".modal-publish-" + provider.providerId).show();
if(publishPreferences) {
_.each(provider.publishPreferencesInputIds, function(inputId) {
var publishPreferenceValue = publishPreferences[inputId];
if(_.isBoolean(publishPreferenceValue)) {
utils.setInputChecked("#input-publish-" + inputId, publishPreferenceValue);
}
else {
utils.setInputValue("#input-publish-" + inputId, publishPreferenceValue);
}
});
utils.setInputRadio("radio-publish-format", publishPreferences.format);
utils.setInputChecked("#checkbox-publish-custom-template", publishPreferences.customTmpl !== undefined);
utils.setInputValue('#textarea-publish-custom-template', publishPreferences.customTmpl || settings.template);
}
// Open dialog box // Reset fields
$(".modal-publish").modal(); utils.resetModalInputs();
} utils.setInputRadio("radio-publish-format", defaultPublishFormat);
utils.setInputChecked("#checkbox-publish-custom-template", false);
utils.setInputValue('#textarea-publish-custom-template', settings.template);
// Add a new publish location to a local document // Load preferences
function performNewLocation(event) { var publishPreferences = utils.retrieveIgnoreError(provider.providerId + ".publishPreferences");
var provider = newLocationProvider; if(publishPreferences) {
var publishAttributes = provider.newPublishAttributes(event); _.each(provider.publishPreferencesInputIds, function(inputId) {
if(publishAttributes === undefined) { var publishPreferenceValue = publishPreferences[inputId];
return; if(_.isBoolean(publishPreferenceValue)) {
} utils.setInputChecked("#input-publish-" + inputId, publishPreferenceValue);
}
else {
utils.setInputValue("#input-publish-" + inputId, publishPreferenceValue);
}
});
utils.setInputRadio("radio-publish-format", publishPreferences.format);
utils.setInputChecked("#checkbox-publish-custom-template", publishPreferences.customTmpl !== undefined);
utils.setInputValue('#textarea-publish-custom-template', publishPreferences.customTmpl || settings.template);
}
// Perform provider's publishing // Open dialog box
var fileDesc = fileMgr.currentFile; $(".modal-publish").modal();
var content = getPublishContent(fileDesc, publishAttributes, currentHTML); }
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() {
createPublishIndex(fileDesc, publishAttributes);
});
}
});
// Store input values as preferences for next time we open the publish // Add a new publish location to a local document
// dialog function performNewLocation(event) {
var publishPreferences = {}; var provider = newLocationProvider;
_.each(provider.publishPreferencesInputIds, function(inputId) { var publishAttributes = provider.newPublishAttributes(event);
var inputElt = document.getElementById("input-publish-" + inputId); if(publishAttributes === undefined) {
if(inputElt.type == 'checkbox') { return;
publishPreferences[inputId] = inputElt.checked; }
}
else {
publishPreferences[inputId] = inputElt.value;
}
});
publishPreferences.format = publishAttributes.format;
publishPreferences.customTmpl = publishAttributes.customTmpl;
storage[provider.providerId + ".publishPreferences"] = JSON.stringify(publishPreferences);
}
var initPublishButtonTmpl = [ // Perform provider's publishing
'<li>', var fileDesc = fileMgr.currentFile;
' <a href="#"', var content = getPublishContent(fileDesc, publishAttributes, currentHTML);
' class="action-init-publish-<%= provider.providerId %>">', var title = (fileDesc.frontMatter && fileDesc.frontMatter.title) || fileDesc.title;
' <i class="icon-provider-<%= provider.providerId %>"></i> <%= provider.providerName %>', provider.publish(publishAttributes, fileDesc.frontMatter, title, content, function(error) {
' </a>', if(error === undefined) {
'</li>' publishAttributes.provider = provider;
].join(''); sharing.createLink(publishAttributes, function() {
eventMgr.addListener("onReady", function() { createPublishIndex(fileDesc, publishAttributes);
if(window.viewerMode === false) { });
// Add every provider in the panel menu }
var publishMenuElt = document.querySelector('.menu-panel .publish-on-provider-list'); });
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);
});
});
}
$(".action-process-publish").click(performNewLocation); // Store input values as preferences for next time we open the publish
// dialog
var publishPreferences = {};
_.each(provider.publishPreferencesInputIds, function(inputId) {
var inputElt = document.getElementById("input-publish-" + inputId);
if(inputElt.type == 'checkbox') {
publishPreferences[inputId] = inputElt.checked;
}
else {
publishPreferences[inputId] = inputElt.value;
}
});
publishPreferences.format = publishAttributes.format;
publishPreferences.customTmpl = publishAttributes.customTmpl;
storage[provider.providerId + ".publishPreferences"] = JSON.stringify(publishPreferences);
}
var $customTmplCollapseElt = $('.publish-custom-template-collapse').collapse({ var initPublishButtonTmpl = [
toggle: false '<li>',
}); ' <a href="#"',
var $customTmplTextareaElt = $('#textarea-publish-custom-template'); ' class="action-init-publish-<%= provider.providerId %>">',
var doCustomTmplCollapse = _.debounce(function() { ' <i class="icon-provider-<%= provider.providerId %>"></i> <%= provider.providerName %>',
$customTmplCollapseElt.collapse(utils.getInputRadio("radio-publish-format") == 'template' ? 'show' : 'hide'); ' </a>',
}, 100); '</li>'
$("#checkbox-publish-custom-template").change(function() { ].join('');
$customTmplTextareaElt.prop('disabled', !this.checked); eventMgr.addListener("onReady", function() {
}); if(window.viewerMode === false) {
$("input:radio[name=radio-publish-format]").change(function() { // Add every provider in the panel menu
doCustomTmplCollapse(); var publishMenuElt = document.querySelector('.menu-panel .publish-on-provider-list');
}); var publishMenuHtml = _.reduce(providerMap, function(result, provider) {
$('.modal-publish').on('hidden.bs.modal', function() { return result + _.template(initPublishButtonTmpl, {
$customTmplCollapseElt.collapse('hide'); 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);
});
});
}
// Save As menu items $(".action-process-publish").click(performNewLocation);
$(".action-download-md").click(function() {
var content = fileMgr.currentFile.content;
var title = fileMgr.currentFile.title;
utils.saveAs(content, title + ".md");
});
$(".action-download-html").click(function() {
var title = fileMgr.currentFile.title;
utils.saveAs(currentHTML.withoutComments, title + ".html");
});
$(".action-download-template").click(function() {
var fileDesc = fileMgr.currentFile;
var content = publisher.applyTemplate(fileDesc, undefined, currentHTML);
utils.saveAs(content, fileDesc.title + (settings.template.indexOf("documentHTML") === -1 ? ".md" : ".html"));
});
$(".action-download-pdf").click(function() {
var fileDesc = fileMgr.currentFile;
var content = publisher.applyTemplate(fileDesc, {
customTmpl: settings.pdfTemplate
}, currentHTML);
var task = new AsyncTask();
var pdf;
task.onRun(function() {
if(isOffline === true) {
eventMgr.onError("Operation not available in offline mode.");
task.chain();
return;
}
var xhr = new XMLHttpRequest();
xhr.open('POST', constants.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();
});
});
eventMgr.onPublisherCreated(publisher); var $customTmplCollapseElt = $('.publish-custom-template-collapse').collapse({
return publisher; toggle: false
});
var $customTmplTextareaElt = $('#textarea-publish-custom-template');
var doCustomTmplCollapse = _.debounce(function() {
$customTmplCollapseElt.collapse(utils.getInputRadio("radio-publish-format") == 'template' ? 'show' : 'hide');
}, 100);
$("#checkbox-publish-custom-template").change(function() {
$customTmplTextareaElt.prop('disabled', !this.checked);
});
$("input:radio[name=radio-publish-format]").change(function() {
doCustomTmplCollapse();
});
$('.modal-publish').on('hidden.bs.modal', function() {
$customTmplCollapseElt.collapse('hide');
});
// Save As menu items
$(".action-download-md").click(function() {
var content = fileMgr.currentFile.content;
var title = fileMgr.currentFile.title;
utils.saveAs(content, title + ".md");
});
$(".action-download-html").click(function() {
var title = fileMgr.currentFile.title;
utils.saveAs(currentHTML.withoutComments, title + ".html");
});
$(".action-download-template").click(function() {
var fileDesc = fileMgr.currentFile;
var content = publisher.applyTemplate(fileDesc, undefined, currentHTML);
utils.saveAs(content, fileDesc.title + (settings.template.indexOf("documentHTML") === -1 ? ".md" : ".html"));
});
var monetize = new MonetizeJS({
applicationID: 'iklMbzDI7dvMEScb'
});
$(".action-download-pdf").click(function() {
var fileDesc = fileMgr.currentFile;
var content = publisher.applyTemplate(fileDesc, {
customTmpl: settings.pdfTemplate
}, currentHTML);
var task = new AsyncTask();
var pdf, token;
task.onRun(function() {
if(isOffline === true) {
eventMgr.onError("Operation not available in offline mode.");
return task.chain();
}
if(!eventMgr.isSponsor) {
$('.modal-sponsorship-required').modal('show');
return task.chain();
}
monetize.getTokenImmediate(function(err, result) {
token = result || '';
task.chain();
});
});
task.onRun(function() {
var xhr = new XMLHttpRequest();
xhr.open('POST', constants.HTMLTOPDF_URL + '?token=' + encodeURIComponent(token) + '&options=' + encodeURIComponent(settings.pdfOptions), 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();
});
});
eventMgr.onPublisherCreated(publisher);
return publisher;
}); });

View File

@ -52,10 +52,10 @@ define([
constants.MAIN_URL, constants.MAIN_URL,
'libs/MathJax/MathJax.js?config=TeX-AMS_HTML"></script>\n', 'libs/MathJax/MathJax.js?config=TeX-AMS_HTML"></script>\n',
'</head>\n', '</head>\n',
'<body class="pdf"><%= documentHTML %></body>\n', '<body><%= documentHTML %></body>\n',
'</html>' '</html>'
].join(""), ].join(""),
pdfPageSize: 'A4', pdfOptions: '{}',
sshProxy: constants.SSH_PROXY_URL, sshProxy: constants.SSH_PROXY_URL,
extensionSettings: {} extensionSettings: {}
}; };

View File

@ -129,7 +129,7 @@ define([
// For input control // For input control
function inputError(element, event) { function inputError(element, event) {
if(event !== undefined) { if(event !== undefined) {
element.stop(true, true).addClass("error").delay(1000).queue(function() { element.stop(true, true).addClass("error").delay(3000).queue(function() {
$(this).removeClass("error"); $(this).removeClass("error");
$(this).dequeue(); $(this).dequeue();
}); });
@ -223,6 +223,23 @@ define([
return value; return value;
}; };
// Return input value and check that it's a valid JSON
utils.getInputJSONValue = function(element, event) {
element = jqElt(element);
var value = utils.getInputTextValue(element, event);
if(value === undefined) {
return undefined;
}
try {
JSON.parse(value);
}
catch(e) {
inputError(element, event);
return undefined;
}
return value;
};
// Return checkbox boolean value // Return checkbox boolean value
utils.getInputChecked = function(element) { utils.getInputChecked = function(element) {
element = jqElt(element); element = jqElt(element);