diff --git a/src/tasks/libraries-db.js b/src/tasks/libraries-db.js index d18b907..493a1bf 100644 --- a/src/tasks/libraries-db.js +++ b/src/tasks/libraries-db.js @@ -287,7 +287,9 @@ module.exports = { } Object.keys(registry[lib].versions).forEach(function (version) { - result.push({ lib: lib, version: version }); + var item = { lib: lib, version: version }; + target.getChanges().getLibraries().addAdded(item); + result.push(item); }); }); return result; diff --git a/src/tasks/override-links.js b/src/tasks/override-links.js index 39d7d83..0558afb 100644 --- a/src/tasks/override-links.js +++ b/src/tasks/override-links.js @@ -9,18 +9,19 @@ var util = require('util'), logger = require('../logger'), REGEXP = { - HREF: /]*?\s+)?href="([^"]*)"/g, // - SRC: /]*?\s+)?src="([^"]*)"/g, // - RELATIVE: { - DOC: /^\.?\/?(?:\.\.\/)+?([\w|-]+)\.?[md|html|ru\.md|en\.md]?/, - VERSION_DOC: /^\.?\/?(\d+\.\d+\.\d+)\-([\w|-]+)?\.?[md|html|ru\.md|en\.md]?/, - BLOCK: /^\.\.?\/([\w|-]+)\/?([\w|-]+)?\.?[md|html|ru\.md|en\.md]?/, - BLOCKS: /^\.?\/?(?:\.\.\/)?([\w|-]+)\.blocks\/([\w|-]+)\/?([\w|-]+)?\.[md|html|ru\.md|en\.md]/, - LEVEL: /^\.\.?\/\.\.\/([\w|-]+)\.blocks\/([\w|-]+)\/?([\w|-]+)?\.?[md|html|ru\.md|en\.md]?/, - BLOCK_FILES: /^\.?\/?(?:\.\.\/)?([\w|-]+)\.blocks\/([\w|-]+)\/?([\w|-]+)?\.(?![md|html|ru\.md|en\.md])/, - JSON: /\w+\.json/ - } -}; + HREF: /]*?\s+)?href="([^"]*)"/g, // + SRC: /]*?\s+)?src="([^"]*)"/g, // + RELATIVE: { + DOC: /^\.?\/?(?:\.\.\/)+?([\w|-]+)\.?[md|html|ru\.md|en\.md]?/, + VERSION_DOC: /^\.?\/?(\d+\.\d+\.\d+)\-([\w|-]+)?\.?[md|html|ru\.md|en\.md]?/, + BLOCK: /^\.\.?\/([\w|-]+)\/?([\w|-]+)?\.?[md|html|ru\.md|en\.md]?/, + BLOCKS: /^\.?\/?(?:\.\.\/)?([\w|-]+)\.blocks\/([\w|-]+)\/?([\w|-]+)?\.[md|html|ru\.md|en\.md]/, + LEVEL: /^\.\.?\/\.\.\/([\w|-]+)\.blocks\/([\w|-]+)\/?([\w|-]+)?\.?[md|html|ru\.md|en\.md]?/, + BLOCK_FILES: /^\.?\/?(?:\.\.\/)?([\w|-]+)\.blocks\/([\w|-]+)\/?([\w|-]+)?\.(?![md|html|ru\.md|en\.md])/, + JSON: /\w+\.json/ + } + }, + PORTION_SIZE = 100; function buildHref(a) { return util.format(' site url + */ return levelDb.get().getByKeyRange(target.KEY.DOCS_PREFIX, target.KEY.NODE_PREFIX) .then(function (docRecords) { return vow.all([ @@ -345,46 +360,171 @@ function collectUrls(target) { }); } -module.exports = function (target) { - logger.info('Start overriding links', module); +/** + * Reads document page records from db + * @param {TargetBase} target object + * @param {Object[]} changedLibVersions - array with changed library versions + * @returns {Promise} + */ +function getDocumentRecordsFromDb (target, changedLibVersions) { + /** + * Здесь происходит выборка из пространства ключей NODE + * по критериям: + * + * 1. view страницы должно быть 'post' + * 2. Если это документ версии библиотеки, то версия библиотеки должна быть в модели измененных + */ + return levelDb.get().getByCriteria(function (record) { + var value = record.value, + route = value.route, + conditions, lib, version; + + if (value.view !== 'post') { + return false; + } - if (!target.getChanges().areModified()) { - logger.warn('No changes were made during this synchronization. This step will be skipped', module); - return vow.resolve(target); - } + conditions = route.conditions; + if (conditions && conditions.lib && conditions.version) { + lib = conditions.lib; + version = conditions.version; - var languages = utility.getLanguages(), - librariesChanges = target.getChanges().getLibraries(), - changedLibVersions = [] - .concat(librariesChanges.getAdded()) - .concat(librariesChanges.getModified()); + return changedLibVersions.some(function (item) { + return item.lib === lib && item.version === version; + }); + } - return vow.all([ - levelDb.get().getByCriteria(function (record) { - var value = record.value, - route = value.route, - conditions, lib, version; + return true; + }, { gte: target.KEY.NODE_PREFIX, lt: target.KEY.PEOPLE_PREFIX, fillCache: true }); +} - conditions = route.conditions; - if (conditions && conditions.lib && conditions.version) { - lib = conditions.lib; - version = conditions.version; +/** + * Reads block pages from database + * @param {TargetBase} target object + * @param {Object[]} changedLibVersions - array with changed library versions + * @returns {Promise} + */ +function getBlockRecordsFromDb(target, changedLibVersions) { + /** + * Здесь происходит выборка из пространства ключей NODE + * по критериям: + * + * 1. view страницы должно быть 'block' + * 2. Должен быть source.data - ссылка на запись с документацией блока + * 3. Версия библиотеки должна быть в модели измененных + */ + return levelDb.get().getByCriteria(function (record) { + var value = record.value, + route = value.route, + conditions, lib, version; + + if (value.view !== 'block') { + return false; + } - return changedLibVersions.some(function (item) { - return item.lib === lib && item.version === version; - }); - } + if (!value.source || !value.source.data) { + return false; + } - return true; - }, { gte: target.KEY.NODE_PREFIX, lt: target.KEY.PEOPLE_PREFIX, fillCache: true }), - collectUrls(target) - ]) - .spread(function (nodeRecords, urlsHash) { - logger.debug('Urls were collected. Start to process pages ...', module); - return vow.all(nodeRecords.map(function (nodeRecord) { - var nodeValue = nodeRecord.value; + conditions = route.conditions; + if (conditions && conditions.lib && conditions.version) { + lib = conditions.lib; + version = conditions.version; + + return changedLibVersions.some(function (item) { + return item.lib === lib && item.version === version; + }); + } + + return false; + }, { gte: target.KEY.NODE_PREFIX, lt: target.KEY.PEOPLE_PREFIX, fillCache: true }); +} + +/** + * Overrides links for document page records + * @param {TargetBase} target object + * @param {Object} urlsHash - url comparison hash + * @param {String []} languages - array of language identifiers + * @param {Object[]} changedLibVersions - array with changed library versions + * @returns {Promise} + */ +function overrideLinksInDocuments (target, urlsHash, languages, changedLibVersions) { + logger.debug('Start to override links in documents', module); + + /** + * 1. Выбираем страницы документов из бд + * 2. Делим массив полученных записей на массивы по 100 штук + * 3. Последовательно выполняем переопределение ссылок для каждой порции записей + * 3.1 Внутри порции переопредление ссылок для записей происходит параллельно + * 3.2 Для каждой записи страницы выбираем связанную с ней запись документа + * 3.3 Еслитаковая присутствует, то скармливаем ее content в переопределятор + * 3.4 Сохраняем запись документа с измененным контентом + */ + return getDocumentRecordsFromDb(target, changedLibVersions).then(function (records) { + logger.debug(util.format('Document records count: %s', records.length), module); + var portionSize = PORTION_SIZE, + portions = _.chunk(records, portionSize); + + logger.debug(util.format('Document records were divided into %s portions', portions.length), module); + + return portions.reduce(function (prev, item, index) { + prev = prev.then(function () { + logger.debug(util.format('override document links in range %s - %s', + index * portionSize, (index + 1) * portionSize), module); + return vow.allResolved(item.map(function (_item) { + var nodeValue = _item.value; + return vow.all(languages.map(function (lang) { + var docKey = util.format('%s%s:%s', target.KEY.DOCS_PREFIX, nodeValue.id, lang); + return levelDb.get().get(docKey) + .then(function (docValue) { + if (!docValue || !docValue.content) { + return vow.resolve(); + } + docValue.content = overrideLinks(docValue.content, nodeValue, urlsHash, lang, docValue); + return levelDb.get().put(docKey, docValue); + }); + })); + })); + }); + return prev; + }, vow.resolve()); + }); +} + +/** + * Overrides links for block page records + * @param {TargetBase} target object + * @param {Object} urlsHash - url comparison hash + * @param {String []} languages - array of language identifiers + * @param {Object[]} changedLibVersions - array with changed library versions + * @returns {Promise} + */ +function overrideLinksInBlocks(target, urlsHash, languages, changedLibVersions) { + logger.debug('Start to override links in blocks', module); + + /** + * 1. Выбираем страницы блоков из бд + * 2. Делим массив полученных записей на массивы по 100 штук + * 3. Последовательно выполняем переопределение ссылок для каждой порции записей + * 3.1 Внутри порции переопредление ссылок для записей происходит параллельно + * 3.2 Для каждой записи страницы выбираем связанную с ней запись докуметации блока + * 3.3 Если таковая присутствует, то скармливаем ее content в переопределятор + * с учетом различных форматов документации для разных библиотек и наличия нескольких языков + * 3.4 Сохраняем запись документации блока с измененным контентом + */ + return getBlockRecordsFromDb(target, changedLibVersions).then(function (records) { + logger.debug(util.format('Block records count: %s', records.length), module); + var portionSize = PORTION_SIZE, + portions = _.chunk(records, portionSize); + + logger.debug(util.format('Block records were divided into %s portions', portions.length), module); + + return portions.reduce(function (prev, item, index) { + prev = prev.then(function () { + logger.debug(util.format('override block links in range %s - %s', + index * portionSize, (index + 1) * portionSize), module); + return vow.allResolved(item.map(function (_item) { + var nodeValue = _item.value; - if (nodeValue.source && nodeValue.source.data) { return levelDb.get().get(nodeValue.source.data).then(function (blockValue) { if (!blockValue) { return vow.resolve(); @@ -421,20 +561,39 @@ module.exports = function (target) { return levelDb.get().put(nodeValue.source.data, blockValue); }); - } - - return vow.all(languages.map(function (lang) { - var docKey = util.format('%s%s:%s', target.KEY.DOCS_PREFIX, nodeValue.id, lang); - return levelDb.get().get(docKey) - .then(function (docValue) { - if (!docValue || !docValue.content) { - return vow.resolve(); - } - docValue.content = overrideLinks(docValue.content, nodeValue, urlsHash, lang, docValue); - return levelDb.get().put(docKey, docValue); - }); })); - })); + }); + return prev; + }, vow.resolve()); + }); +} + +module.exports = function (target) { + logger.info('Start overriding links', module); + + if (!target.getChanges().areModified()) { + logger.warn('No changes were made during this synchronization. This step will be skipped', module); + return vow.resolve(target); + } + + var languages = utility.getLanguages(), + librariesChanges = target.getChanges().getLibraries(), + changedLibVersions = [] + .concat(librariesChanges.getAdded()) + .concat(librariesChanges.getModified()), + urlsHash; + + return collectUrls(target) + .then(function (_urlsHash) { + logger.debug('Urls were collected. Start to process pages ...', module); + urlsHash = _urlsHash; + return urlsHash; + }) + .then(function () { + return overrideLinksInDocuments(target, urlsHash, languages, changedLibVersions); + }) + .then(function () { + return overrideLinksInBlocks(target, urlsHash, languages, changedLibVersions); }) .then(function () { logger.info('Links were successfully overrided', module);