epubchecker
Version:
Validation tool for ePub.
206 lines (175 loc) • 6.3 kB
JavaScript
const fs = require('fs');
const epubcheck = require('./epubcheck');
/**
* @typedef {Object} EpubCheckerOptions
* @property {boolean} includeWarnings Report should include warnings
* @property {boolean} includeNotices Report should include notices
* @property {string} output The path where to store the report
* @property {RegExp|RegExp[]} ignore Regex for messages to ignore
* @property {RegExp|RegExp[]} exclude Regex for files to exclude
* @property {RegExp|RegExp[]} include Regex for files to include
* @property {string} locale Set report language
*/
/**
* Sort the report messages by severity.
* @private
*
* @param {Object} report The epubchek report to sort
* @return {Object} The sorted report
*/
function sortReport(report) {
report.messages.sort((msg1, msg2) => {
if (msg1.severity === msg2.severity) {
return 0;
}
let severities = ['FATAL', 'ERROR', 'WARNING', 'INFO'];
for (let i = 0; i < severities.length; i++) {
let severity = severities[i];
if (msg1.severity === severity) {
return -1;
}
if (msg2.severity === severity) {
return 1;
}
}
});
return report;
}
/**
* Filter report by messages and files.
*
* @param {EpubCheckerOptions} options A set of filters options
* @return {Object} The filtered report
*/
function filterReport(options = {}) {
return function(report) {
report.messages = report.messages.filter((msg) => {
if (!options.includeWarnings && msg.severity === 'WARNING') {
return false;
}
if (!options.includeNotices && msg.severity === 'INFO') {
return false;
}
if (options.ignore) {
let ignoreList = options.ignore;
if (!Array.isArray(ignoreList)) {
ignoreList = [ignoreList];
}
if (ignoreList.some((regex) => {
if (regex.test(msg.ID)) {
return true;
}
if (regex.test(msg.message)) {
return true;
}
if (!msg.locations) {
return false;
}
msg.locations = msg.locations.filter((location) => {
if (location.context && regex.test(location.context)) {
return false;
}
return true;
});
if (msg.locations.length === 0) {
return true;
}
if (msg.locations.length === 1 && msg.locations[0].path.includes('additional locations')) {
return true;
}
})) {
// remove ignored messages
return false;
}
}
if (!options.exclude && !options.include) {
return true;
}
if (!msg.locations || !msg.locations.length) {
return true;
}
msg.locations = msg.locations.filter((location) => {
if (options.include) {
let includeList = options.include;
if (!Array.isArray(includeList)) {
includeList = [includeList];
}
if (includeList.some((regex) => regex.test(location.path))) {
// keep included location
return true;
}
}
if (options.exclude) {
let excludeList = options.exclude;
if (!Array.isArray(excludeList)) {
excludeList = [excludeList];
}
if (!excludeList.some((regex) => regex.test(location.path))) {
// location is not excluded
return true;
}
}
// filter location
return false;
});
if (msg.locations.length === 1 && msg.locations[0].path.includes('additional locations')) {
// consider locations with only "additional" message as empty
return false;
}
return !!msg.locations.length;
});
return report;
}
}
/**
* Run epubcheck over an ePub file (or an uncompressed ePub directory).
*
* @param {string} epubFile The ePub file or directory path
* @param {EpubCheckerOptions} options A set of options for the checker
* @param {Function} [callback] Optional callback for the checker
* @return {Promise<Object>} The epubcheck report
*/
function epubchecker(epubFile, options = {}, callback = () => { }) {
let epubTempFile = null;
if (typeof options === 'function') {
callback = options;
options = {};
}
if (!fs.existsSync(epubFile)) {
// cannot find epub file or directory
return Promise.reject('missing file');
}
let mode;
if (fs.statSync(epubFile).isDirectory()) {
mode = 'exp';
}
// run epubcheck over the file and sort the report
let resultPromise = epubcheck(epubFile, {
locale: options.locale,
mode,
})
.then(filterReport(options))
.then(sortReport);
resultPromise.then((report) => {
if (epubTempFile && fs.existsSync(epubTempFile)) {
// remove temporary files
fs.unlinkSync(epubTempFile);
}
if (options.output) {
// store the output
fs.writeFileSync(options.output, JSON.stringify(report, null, 2));
}
// exec callback with report
callback(null, report);
});
resultPromise.catch((error) => {
if (epubTempFile && fs.existsSync(epubTempFile)) {
// remove temporary files
fs.unlinkSync(epubTempFile);
}
// exec callback with report
callback(error, null);
});
return resultPromise;
}
module.exports = epubchecker;