dict-sd2json
Version:
stardict to json converter for diglossa.js
418 lines (353 loc) • 13.8 kB
JavaScript
'use strict';
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.sd2json = sd2json;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _lodash = _interopRequireDefault(require("lodash"));
var path = require('path');
var fse = require('fs-extra');
var log = console.log;
var util = require('util');
var pako = require('pako');
var decoder = new util.TextDecoder('utf-8');
var sanitizeHtml = require('sanitize-html');
function sd2json(_x) {
return _sd2json.apply(this, arguments);
} // rdoc - {dict, trns}
function _sd2json() {
_sd2json = (0, _asyncToGenerator2["default"])(
/*#__PURE__*/
_regenerator["default"].mark(function _callee(dictpath) {
var fns, descr, indexData, unzipped, phrases, docs;
return _regenerator["default"].wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.prev = 0;
_context.next = 3;
return checkDir(dictpath);
case 3:
fns = _context.sent;
_context.next = 6;
return parseDescr(fns);
case 6:
descr = _context.sent;
_context.next = 9;
return parseIndex(fns);
case 9:
indexData = _context.sent;
_context.next = 12;
return parseDict(fns);
case 12:
unzipped = _context.sent;
phrases = genDocs(indexData, unzipped);
docs = uniqDocs(phrases);
descr.size = docs.length;
return _context.abrupt("return", {
descr: descr,
docs: docs
});
case 19:
_context.prev = 19;
_context.t0 = _context["catch"](0);
console.log('STARDICT ERR:', _context.t0);
case 22:
case "end":
return _context.stop();
}
}
}, _callee, null, [[0, 19]]);
}));
return _sd2json.apply(this, arguments);
}
function uniqDocs(rdocs) {
var hdocs = Object.create(null);
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = rdocs[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var rdoc = _step.value;
var dict = rdoc.dict.replace(/^_/, ''); // Couch/Pouch restriction
var hdoc = {
_id: dict,
trns: rdoc.trns
};
if (!hdocs[dict]) hdocs[dict] = hdoc;else if (hdocs[dict] && !hdocs[dict].trns) hdocs[dict].trns = [rdoc.trns];else hdocs[dict].trns.push(rdoc.trns);
if (dict.split(' ').length > 1) {
var phrasedocs = parsePhrase(dict);
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = phrasedocs[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var phdoc = _step2.value;
if (!hdocs[phdoc._id]) hdocs[phdoc._id] = phdoc;else if (hdocs[phdoc._id] && !hdocs[phdoc._id].refs) hdocs[phdoc._id].refs = [dict];else hdocs[phdoc._id].refs.push(dict);
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2["return"] != null) {
_iterator2["return"]();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
}
if (hdocs[dict].refs) hdocs[dict].refs = _lodash["default"].uniq(hdocs[dict].refs);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator["return"] != null) {
_iterator["return"]();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
var docs = Object.values(hdocs);
return docs;
} // == здесь doc = {_id, docs}, docs=> {doc, trns}
function uniqDocs_old(rdocs) {
var hdocs = Object.create(null);
var _iteratorNormalCompletion3 = true;
var _didIteratorError3 = false;
var _iteratorError3 = undefined;
try {
for (var _iterator3 = rdocs[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
var rdoc = _step3.value;
var dict = rdoc.dict.replace(/^_/, ''); // Couch/Pouch restriction
var doc = {
trns: rdoc.trns
};
var hdoc = {
_id: dict,
docs: [doc]
};
if (!hdocs[dict]) hdocs[dict] = hdoc;else if (hdocs[dict] && !hdocs[dict].docs) hdocs[dict].docs = [doc];else hdocs[dict].docs.push(doc);
if (dict.split(' ').length > 1) {
var phrasedocs = parsePhrase(dict);
var _iteratorNormalCompletion4 = true;
var _didIteratorError4 = false;
var _iteratorError4 = undefined;
try {
for (var _iterator4 = phrasedocs[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
var phdoc = _step4.value;
if (!hdocs[phdoc._id]) hdocs[phdoc._id] = phdoc;else if (hdocs[phdoc._id] && !hdocs[phdoc._id].refs) hdocs[phdoc._id].refs = [dict];else hdocs[phdoc._id].refs.push(dict);
}
} catch (err) {
_didIteratorError4 = true;
_iteratorError4 = err;
} finally {
try {
if (!_iteratorNormalCompletion4 && _iterator4["return"] != null) {
_iterator4["return"]();
}
} finally {
if (_didIteratorError4) {
throw _iteratorError4;
}
}
}
}
if (hdocs[dict].refs && hdocs[dict].refs.length) hdocs[dict].refs = _lodash["default"].uniq(hdocs[dict].refs);
}
} catch (err) {
_didIteratorError3 = true;
_iteratorError3 = err;
} finally {
try {
if (!_iteratorNormalCompletion3 && _iterator3["return"] != null) {
_iterator3["return"]();
}
} finally {
if (_didIteratorError3) {
throw _iteratorError3;
}
}
}
var docs = Object.values(hdocs);
return docs;
}
function parsePhrase(dict) {
var phdocs = [];
var wfs = dict.split(/(?:[ -#%-\*,-\/:;\?@\[-\]_\{\}\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u09FD\u0A76\u0AF0\u0C77\u0C84\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E4F\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD803[\uDF55-\uDF59]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC8\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9]|\uD805[\uDC4B-\uDC4F\uDC5B\uDC5D\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDE60-\uDE6C\uDF3C-\uDF3E]|\uD806[\uDC3B\uDDE2\uDE3F-\uDE46\uDE9A-\uDE9C\uDE9E-\uDEA2]|\uD807[\uDC41-\uDC45\uDC70\uDC71\uDEF7\uDEF8\uDFFF]|\uD809[\uDC70-\uDC74]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD81B[\uDE97-\uDE9A\uDFE2]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]|\uD83A[\uDD5E\uDD5F])+/g).filter(Boolean);
var _iteratorNormalCompletion5 = true;
var _didIteratorError5 = false;
var _iteratorError5 = undefined;
try {
for (var _iterator5 = wfs[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
var wf = _step5.value;
if (wf.length < 3) continue;
var phdoc = {
_id: wf,
refs: [dict]
};
phdocs.push(phdoc);
}
} catch (err) {
_didIteratorError5 = true;
_iteratorError5 = err;
} finally {
try {
if (!_iteratorNormalCompletion5 && _iterator5["return"] != null) {
_iterator5["return"]();
}
} finally {
if (_didIteratorError5) {
throw _iteratorError5;
}
}
}
return phdocs;
} // todo: EOL
function genDocs(indexData, unzipped) {
var re = /[;\n]/;
var docs = [];
var _iteratorNormalCompletion6 = true;
var _didIteratorError6 = false;
var _iteratorError6 = undefined;
try {
for (var _iterator6 = indexData[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
var arr = _step6.value;
var offset = arr[1],
size = arr[2];
var unchunk = unzipped.slice(offset, offset + size);
var decoded = decoder.decode(unchunk); // decoded = decoded.split('\n').slice(1).join('; ').trim()
var clean = sanitizeHtml(decoded, {
allowedTags: ['b', 'em', 'strong', 'a', 'abr', 'i', 'font'],
// , 'dtrn'
allowedAttributes: {
'a': ['href']
}
});
var trns = _lodash["default"].compact(_lodash["default"].flatten(clean.split(re).map(function (trn) {
return trn.trim();
})));
trns = trns.map(function (trn) {
return trn.replace(/\[[^)]*\]/g, '');
});
if (trns.length) {
var dict = arr[0];
if (/^\d/.test(dict)) continue;
var doc = {
dict: dict,
trns: trns
};
docs.push(doc);
}
}
} catch (err) {
_didIteratorError6 = true;
_iteratorError6 = err;
} finally {
try {
if (!_iteratorNormalCompletion6 && _iterator6["return"] != null) {
_iterator6["return"]();
}
} finally {
if (_didIteratorError6) {
throw _iteratorError6;
}
}
}
return docs;
}
function parseDict(fns) {
var dictpath = path.resolve(fns.dirpath, fns.dict);
return fse.readFile(dictpath).then(function (gzbuf) {
var rawdata = new Uint8Array(gzbuf);
var unzipped = pako.inflate(rawdata);
return unzipped;
});
}
function checkDir(dictpath) {
var dirpath = path.dirname(dictpath);
var filename = path.basename(dictpath);
filename = path.parse(filename).name;
var refn = new RegExp(filename);
return fse.readdir(dirpath).then(function (fns) {
var fn = {
dirpath: dirpath
};
var ifoname = _lodash["default"].find(fns, function (fn) {
return refn.test(fn) && /ifo/.test(fn);
});
if (!ifoname) throw new Error('Not a stardict archive - no .ifo');
fn.ifo = ifoname;
var idxname = _lodash["default"].find(fns, function (fn) {
return refn.test(fn) && /idx/i.test(fn);
});
if (!idxname) throw new Error('Not a stardict archive - no .idx');
fn.idx = idxname;
var dictname = _lodash["default"].find(fns, function (fn) {
return refn.test(fn) && /\.dz/i.test(fn);
});
if (!dictname) throw new Error('Not a stardict archive - no .dz');
fn.dict = dictname;
return fn;
});
}
function parseDescr(fn) {
var ifopath = path.resolve(fn.dirpath, fn.ifo);
return fse.readFile(ifopath).then(function (ifobuf) {
var ifo = ifobuf.toString().split('\n').slice(0, 7);
var namestr = _lodash["default"].find(ifo, function (str) {
return /bookname/.test(str);
});
var name = namestr.replace('bookname=', '');
var totalstr = _lodash["default"].find(ifo, function (str) {
return /wordcount/.test(str);
});
var total = totalstr.replace('wordcount=', '') * 1 || 10000;
var descr = {
type: 'sd',
name: name,
size: total,
descr: ifo
};
return descr;
});
} // todo .gz - наружу
function parseIndex(fn) {
var idxpath = path.resolve(fn.dirpath, fn.idx);
return fse.readFile(idxpath).then(function (buf) {
if (/gz/.test(idxpath)) {
// console.time('BUFFER-UNGZIP')
var rawdata = new Uint8Array(buf);
var uint8Array = pako.inflate(rawdata);
buf = Buffer.from(uint8Array); // console.timeEnd('BUFFER-UNGZIP')
}
var indexData = [];
var i = 0;
var index = 0;
while (i < buf.length) {
var beg = i;
i = buf.indexOf('\x00', beg);
var word = buf.toString('utf-8', beg, i);
i++;
var offset = buf.readUInt32BE(i);
i += 4;
var size = buf.readUInt32BE(i);
i += 4;
indexData.push([word, offset, size]);
index++;
}
return indexData;
})["catch"](function (err) {
log('__ IDX ERR:', err);
});
}