275 lines
11 KiB
JavaScript
275 lines
11 KiB
JavaScript
define([
|
||
'/api/config',
|
||
'/bower_components/nthen/index.js',
|
||
'/common/common-util.js',
|
||
], function (ApiConfig, nThen, Util) {
|
||
var X2T = {};
|
||
|
||
var CURRENT_VERSION = X2T.CURRENT_VERSION = 'v5';
|
||
var debug = function (str) {
|
||
if (localStorage.CryptPad_dev !== "1") { return; }
|
||
console.debug(str);
|
||
};
|
||
|
||
X2T.start = function () {
|
||
var x2tReady = Util.mkEvent(true);
|
||
var fetchFonts = function (x2t, obj, cb) {
|
||
if (!obj.fonts) { return void cb(); }
|
||
var path = ApiConfig.httpSafeOrigin + '/common/onlyoffice/'+CURRENT_VERSION+'/fonts/';
|
||
var ver = '?' + ApiConfig.requireConf.urlArgs;
|
||
var fonts = obj.fonts;
|
||
var files = obj.fonts_files;
|
||
var suffixes = {
|
||
indexR: '',
|
||
indexB: '_Bold',
|
||
indexBI: '_Bold_Italic',
|
||
indexI: '_Italic',
|
||
};
|
||
nThen(function (waitFor) {
|
||
fonts.forEach(function (font) {
|
||
// Check if the font is already loaded
|
||
if (!font.NeedStyles) { return; }
|
||
// Pick the variants we need (regular, bold, italic)
|
||
['indexR', 'indexB', 'indexI', 'indexBI'].forEach(function (k) {
|
||
if (typeof(font[k]) !== "number" || font[k] === -1) { return; } // No matching file
|
||
var file = files[font[k]];
|
||
|
||
var name = font.Name + suffixes[k] + '.ttf';
|
||
Util.fetch(path + file.Id + ver, waitFor(function (err, buffer) {
|
||
if (buffer) {
|
||
x2t.FS.writeFile('/working/fonts/' + name, buffer);
|
||
}
|
||
}));
|
||
});
|
||
});
|
||
}).nThen(function () {
|
||
cb();
|
||
});
|
||
};
|
||
var x2tInitialized = false;
|
||
var x2tInit = function(x2t) {
|
||
debug("x2t mount");
|
||
// x2t.FS.mount(x2t.MEMFS, {} , '/');
|
||
x2t.FS.mkdir('/working');
|
||
x2t.FS.mkdir('/working/media');
|
||
x2t.FS.mkdir('/working/fonts');
|
||
x2t.FS.mkdir('/working/themes');
|
||
x2tInitialized = true;
|
||
x2tReady.fire();
|
||
debug("x2t mount done");
|
||
};
|
||
var getX2T = function (cb) {
|
||
// Perform the x2t conversion
|
||
require(['/common/onlyoffice/x2t/x2t.js'], function() { // FIXME why does this fail without an access-control-allow-origin header?
|
||
var x2t = window.Module;
|
||
x2t.run();
|
||
if (x2tInitialized) {
|
||
debug("x2t runtime already initialized");
|
||
return void x2tReady.reg(function () {
|
||
cb(x2t);
|
||
});
|
||
}
|
||
|
||
x2t.onRuntimeInitialized = function() {
|
||
debug("x2t in runtime initialized");
|
||
// Init x2t js module
|
||
x2tInit(x2t);
|
||
x2tReady.reg(function () {
|
||
cb(x2t);
|
||
});
|
||
};
|
||
});
|
||
};
|
||
|
||
var getFormatId = function (ext) {
|
||
// Sheets
|
||
if (ext === 'xlsx') { return 257; }
|
||
if (ext === 'xls') { return 258; }
|
||
if (ext === 'ods') { return 259; }
|
||
if (ext === 'csv') { return 260; }
|
||
if (ext === 'pdf') { return 513; }
|
||
// Docs
|
||
if (ext === 'docx') { return 65; }
|
||
if (ext === 'doc') { return 66; }
|
||
if (ext === 'odt') { return 67; }
|
||
if (ext === 'txt') { return 69; }
|
||
if (ext === 'html') { return 70; }
|
||
|
||
// Slides
|
||
if (ext === 'pptx') { return 129; }
|
||
if (ext === 'ppt') { return 130; }
|
||
if (ext === 'odp') { return 131; }
|
||
|
||
return;
|
||
};
|
||
var getFromId = function (ext) {
|
||
var id = getFormatId(ext);
|
||
if (!id) { return ''; }
|
||
return '<m_nFormatFrom>'+id+'</m_nFormatFrom>';
|
||
};
|
||
var getToId = function (ext) {
|
||
var id = getFormatId(ext);
|
||
if (!id) { return ''; }
|
||
return '<m_nFormatTo>'+id+'</m_nFormatTo>';
|
||
};
|
||
|
||
var x2tConvertDataInternal = function(x2t, obj) {
|
||
var data = obj.data;
|
||
var fileName = obj.fileName;
|
||
var outputFormat = obj.outputFormat;
|
||
var images = obj.images;
|
||
debug("Converting Data for " + fileName + " to " + outputFormat);
|
||
|
||
// PDF
|
||
var pdfData = '';
|
||
if (outputFormat === "pdf" && typeof(data) === "object" && data.bin && data.buffer) {
|
||
// Add conversion rules
|
||
pdfData = "<m_bIsNoBase64>false</m_bIsNoBase64>" +
|
||
"<m_sFontDir>/working/fonts/</m_sFontDir>";
|
||
// writing file to mounted working disk (in memory)
|
||
x2t.FS.writeFile('/working/' + fileName, data.bin);
|
||
x2t.FS.writeFile('/working/pdf.bin', data.buffer);
|
||
} else {
|
||
// writing file to mounted working disk (in memory)
|
||
x2t.FS.writeFile('/working/' + fileName, data);
|
||
}
|
||
|
||
// Adding images
|
||
Object.keys(images || {}).forEach(function (_mediaFileName) {
|
||
if (/\.bin$/.test(_mediaFileName)) { return; }
|
||
var mediasSources = obj.mediasSources || {};
|
||
var mediasData = obj.mediasData || {};
|
||
var mediaData = mediasData[_mediaFileName];
|
||
var mediaFileName;
|
||
if (mediaData) { // Theme image
|
||
var path = _mediaFileName.split('/');
|
||
mediaFileName = path.pop();
|
||
var theme = path[path.indexOf('themes') + 1];
|
||
try {
|
||
x2t.FS.mkdir('/working/themes/'+theme);
|
||
x2t.FS.mkdir('/working/themes/'+theme+'/media');
|
||
} catch (e) {
|
||
console.warn(e);
|
||
}
|
||
x2t.FS.writeFile('/working/themes/'+theme+'/media/' + mediaFileName, new Uint8Array(mediaData.content));
|
||
debug("Writing media data " + mediaFileName + " at /working/themes/"+theme+"/media/");
|
||
return;
|
||
}
|
||
// mediaData is undefined, check mediasSources
|
||
mediaFileName = _mediaFileName.substring(6);
|
||
var mediaSource = mediasSources[mediaFileName];
|
||
mediaData = mediaSource ? mediasData[mediaSource.src] : undefined;
|
||
if (mediaData) {
|
||
debug("Writing media data " + mediaFileName);
|
||
debug("Data");
|
||
var fileData = mediaData.content;
|
||
x2t.FS.writeFile('/working/media/' + mediaFileName, new Uint8Array(fileData));
|
||
} else {
|
||
debug("Could not find media content for " + mediaFileName);
|
||
}
|
||
});
|
||
|
||
|
||
var inputFormat = fileName.split('.').pop();
|
||
|
||
var params = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
|
||
+ "<TaskQueueDataConvert xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">"
|
||
+ "<m_sFileFrom>/working/" + fileName + "</m_sFileFrom>"
|
||
+ "<m_sThemeDir>/working/themes</m_sThemeDir>"
|
||
+ "<m_sFileTo>/working/" + fileName + "." + outputFormat + "</m_sFileTo>"
|
||
+ pdfData
|
||
+ getFromId(inputFormat)
|
||
+ getToId(outputFormat)
|
||
+ "<m_bIsNoBase64>false</m_bIsNoBase64>"
|
||
+ "</TaskQueueDataConvert>";
|
||
|
||
|
||
// writing params file to mounted working disk (in memory)
|
||
x2t.FS.writeFile('/working/params.xml', params);
|
||
try {
|
||
// running conversion
|
||
x2t.ccall("runX2T", ["number"], ["string"], ["/working/params.xml"]);
|
||
} catch (e) {
|
||
console.error(e);
|
||
return "";
|
||
}
|
||
|
||
// reading output file from working disk (in memory)
|
||
var result;
|
||
try {
|
||
result = x2t.FS.readFile('/working/' + fileName + "." + outputFormat);
|
||
} catch (e) {
|
||
debug("Failed reading converted file");
|
||
return "";
|
||
}
|
||
return result;
|
||
};
|
||
|
||
var convert = function (obj, cb) {
|
||
console.error(obj);
|
||
getX2T(function (x2t) {
|
||
// Fonts
|
||
fetchFonts(x2t, obj, function () {
|
||
var o = obj.outputFormat;
|
||
|
||
if (o !== 'pdf') {
|
||
// Add intermediary conversion to Microsoft Office format if needed
|
||
// (bin to pdf is allowed)
|
||
[
|
||
// Import from Open Document
|
||
{source: '.ods', format: 'xlsx'},
|
||
{source: '.odt', format: 'docx'},
|
||
{source: '.odp', format: 'pptx'},
|
||
// Export to non Microsoft Office
|
||
{source: '.bin', type: 'sheet', format: 'xlsx'},
|
||
{source: '.bin', type: 'doc', format: 'docx'},
|
||
{source: '.bin', type: 'presentation', format: 'pptx'},
|
||
].forEach(function (_step) {
|
||
if (obj.fileName.endsWith(_step.source) && obj.outputFormat !== _step.format &&
|
||
(!_step.type || _step.type === obj.type)) {
|
||
obj.outputFormat = _step.format;
|
||
obj.data = x2tConvertDataInternal(x2t, obj);
|
||
obj.fileName += '.'+_step.format;
|
||
}
|
||
});
|
||
obj.outputFormat = o;
|
||
}
|
||
|
||
var data = x2tConvertDataInternal(x2t, obj);
|
||
|
||
// Convert to bin -- Import
|
||
// We need to extract the images
|
||
var images;
|
||
if (o === 'bin') {
|
||
images = [];
|
||
var files = x2t.FS.readdir("/working/media/");
|
||
files.forEach(function (file) {
|
||
if (file !== "." && file !== "..") {
|
||
var fileData = x2t.FS.readFile("/working/media/" + file, {
|
||
encoding : "binary"
|
||
});
|
||
images.push({
|
||
name: file,
|
||
data: fileData
|
||
});
|
||
}
|
||
});
|
||
|
||
}
|
||
|
||
cb({
|
||
data: data,
|
||
images: images
|
||
});
|
||
});
|
||
});
|
||
};
|
||
|
||
return {
|
||
convert: convert
|
||
};
|
||
};
|
||
|
||
return X2T;
|
||
});
|