diff --git a/client/components/Reader/share/BookParser.js b/client/components/Reader/share/BookParser.js index ac8e2f36..91d50581 100644 --- a/client/components/Reader/share/BookParser.js +++ b/client/components/Reader/share/BookParser.js @@ -37,6 +37,10 @@ export default class BookParser { let center = false; let bold = false; let italic = false; + this.binary = {}; + let binaryId = ''; + let binaryType = ''; + let dimPromises = []; let paraIndex = -1; let paraOffset = 0; @@ -50,6 +54,28 @@ export default class BookParser { addIndex: Number, //индекс добавляемого пустого параграфа (addEmptyParagraphs) } */ + const getImageDimensions = (binaryId, binaryType, data) => { + return new Promise (async(resolve, reject) => { + const i = new Image(); + let resolved = false; + i.onload = () => { + resolved = true; + this.binary[binaryId] = { + w: i.width, + h: i.height, + type: binaryType, + data + }; + resolve(); + }; + + i.src = `data:${binaryType};base64,${data}`; + await sleep(30*1000); + if (!resolved) + reject('Не удалось получить размер изображения'); + }); + }; + const newParagraph = (text, len, addIndex) => { paraIndex++; let p = { @@ -103,13 +129,20 @@ export default class BookParser { paraOffset += p.length; }; - const onStartNode = (elemName) => {// eslint-disable-line no-unused-vars + const onStartNode = (elemName, tail) => {// eslint-disable-line no-unused-vars if (elemName == '?xml') return; tag = elemName; path += '/' + elemName; + if (tag == 'binary') { + let attrs = sax.getAttrsSync(tail); + binaryType = (attrs['content-type'].value ? attrs['content-type'].value : ''); + if (binaryType == 'image/jpeg' || binaryType == 'image/png') + binaryId = (attrs.id.value ? attrs.id.value : ''); + } + if (path.indexOf('/fictionbook/body') == 0) { if (tag == 'title') { newParagraph(' ', 1); @@ -146,6 +179,10 @@ export default class BookParser { const onEndNode = (elemName) => {// eslint-disable-line no-unused-vars if (tag == elemName) { + if (tag == 'binary') { + binaryId = ''; + } + if (path.indexOf('/fictionbook/body') == 0) { if (tag == 'title') { bold = false; @@ -245,6 +282,10 @@ export default class BookParser { growParagraph(`${tOpen}${text}${tClose}`, text.length); } } + + if (binaryId) { + dimPromises.push(getImageDimensions(binaryId, binaryType, text)); + } }; const onProgress = async(prog) => { @@ -256,6 +297,13 @@ export default class BookParser { onStartNode, onEndNode, onTextNode, onProgress }); + if (dimPromises.length) { + try { + await Promise.all(dimPromises); + } catch (e) { + } + } + this.fb2 = fb2; this.para = para; diff --git a/server/core/BookConverter/sax.js b/server/core/BookConverter/sax.js index 90c4e0bc..734d0672 100644 --- a/server/core/BookConverter/sax.js +++ b/server/core/BookConverter/sax.js @@ -276,7 +276,84 @@ async function parse(xstr, options) { await _onProgress(100); } +function getAttrsSync(tail) { + let result = {}; + let name = ''; + let value = ''; + let vOpen = ''; + let inName = false; + let inValue = false; + let waitValue = false; + let waitEq = false; + + const pushResult = () => { + if (name != '') { + let ns = ''; + if (name.indexOf(':') >= 0) { + [ns, name] = name.split(':'); + } + + result[name] = {value, ns}; + } + name = ''; + value = ''; + vOpen = ''; + inName = false; + inValue = false; + waitValue = false; + waitEq = false; + }; + + tail = tail.replace(/[\t\n\r]/g, ' '); + for (let i = 0; i < tail.length; i++) { + const c = tail.charAt(i); + if (c == ' ') { + if (inValue) { + if (vOpen == '"') + value += c; + else + pushResult(); + } else if (inName) { + waitEq = true; + inName = false; + } + } else if (!inValue && c == '=') { + waitEq = false; + waitValue = true; + inName = false; + } else if (c == '"') { + if (inValue) { + pushResult(); + } else if (waitValue) { + inValue = true; + vOpen = '"'; + } + } else if (inValue) { + value += c; + } else if (inName) { + name += c; + } else if (waitEq) { + pushResult(); + inName = true; + name = c; + } else if (waitValue) { + waitValue = false; + inValue = true; + vOpen = ' '; + value = c; + } else { + inName = true; + name = c; + } + } + if (name != '') + pushResult(); + + return result; +} + module.exports = { parseSync, + getAttrsSync, parse } \ No newline at end of file