Files
inpx-web/server/core/fb2/Fb2Helper.js

100 lines
3.4 KiB
JavaScript

const fs = require('fs-extra');
const iconv = require('iconv-lite');
const textUtils = require('./textUtils');
const Fb2Parser = require('../fb2/Fb2Parser');
const utils = require('../utils');
class Fb2Helper {
checkEncoding(data) {
//Корректируем кодировку UTF-16
let encoding = textUtils.getEncoding(data);
if (encoding.indexOf('UTF-16') == 0) {
data = Buffer.from(iconv.decode(data, encoding));
encoding = 'utf-8';
}
//Корректируем пробелы, всякие файлы попадаются :(
if (data[0] == 32) {
data = Buffer.from(data.toString().trim());
}
//Окончательно корректируем кодировку
let result = data;
let left = data.indexOf('<?xml version="1.0"');
if (left < 0) {
left = data.indexOf('<?xml version=\'1.0\'');
}
if (left >= 0) {
const right = data.indexOf('?>', left);
if (right >= 0) {
const head = data.slice(left, right + 2).toString();
const m = head.match(/encoding=['"](.*?)['"]/);
if (m) {
let enc = m[1].toLowerCase();
if (enc != 'utf-8') {
//если кодировка не определена в getEncoding, используем enc
if (encoding.indexOf('ISO-8859') >= 0) {
encoding = enc;
}
result = iconv.decode(data, encoding);
result = Buffer.from(result.toString().replace(m[0], `encoding="utf-8"`));
}
}
}
}
return result;
}
async getDescAndCover(bookFile) {
let data = await fs.readFile(bookFile);
data = await utils.gunzipBuffer(data);
data = this.checkEncoding(data);
const parser = new Fb2Parser();
parser.fromString(data.toString(), {
lowerCase: true,
pickNode: route => route.indexOf('fictionbook/body') !== 0,
});
const coverImage = parser.$$('/description/title-info/coverpage/image');
let cover = null;
let coverExt = '';
if (coverImage.count) {
const coverAttrs = coverImage.attrs();
const href = coverAttrs[`${parser.xlinkNS}:href`];
if (href) {
const binaryId = (href[0] == '#' ? href.substring(1) : href);
//найдем нужный image
for (const node of parser.$$array('/binary')) {
let attrs = node.attrs();
if (!attrs)
return;
if (attrs.id === binaryId) {
let coverType = attrs['content-type'];
coverType = (coverType == 'image/jpg' || coverType == 'application/octet-stream' ? 'image/jpeg' : coverType);
coverExt = (coverType == 'image/png' ? '.png' : '.jpg');
const base64 = node.text();
cover = (base64 ? Buffer.from(base64, 'base64') : null);
}
}
}
}
parser.remove('binary');
return {fb2: parser, cover, coverExt};
}
}
module.exports = Fb2Helper;