/**
* Created by marcobonati on 15/05/2017.
*/
"use strict";
const fs = require("fs-extra");
const path = require('path');
const _ = require('lodash');
const globby = require('globby');
const recursiveReadSync = require('recursive-readdir-sync');
const parseString = require('xml2js').parseString;
const XML = require('pixl-xml');
const md5 = require('md5');
const markdownRender = require('markdown-styles').render;
const opts = require('yargs');
const resolveArgs = require('markdown-styles').resolveArgs;
/**
*
* @constructor
*/
function DocGenerator(){
this.config = {};
}
DocGenerator.prototype.runCli = function(inputArgs,callback) {
var that = this;
this.readConfig(inputArgs);
this.cleanTempFolder();
this.prepareMaster().then(function(success){
var fileList = that.scanDoc(success.mainDocTempFolder);
that.mergeDocs(fileList).then(function(){
console.log("Documentation Generation Completed Successfully!");
var cmdArgs = [ process.argv0, __filename, '--input' , success.mainDocTempFolder, '--output', that.outFolder ];
console.log("out folder=" + that.outFolder);
opts.options({
'layouts': { },
'help': { },
'header-links': { 'default': true },
'layout': { },
'input': { },
'output': { },
'v': { },
'version': { }
}).boolean('layouts').boolean('help').boolean('v').boolean('version').boolean('header-links');
var argv = opts.parse(cmdArgs);
argv = resolveArgs(argv);
//var layoutDir = __dirname + '/../layouts/';
markdownRender(argv, function(){
});
}, function(err){
console.log("ERROR !!!!! " + err);
});
}, function(err){
console.trace(err);
});
}
/**
* Merge main doc with the given pages from file list
* @param fileList
*/
DocGenerator.prototype.mergeDocs = function(fileList) {
var that = this;
var i = 0;
this.merged = 0;
this.toMerge = fileList.length;
return new Promise(function(fullfill, reject){
for (i=0;i<fileList.length;i++){
that.mergeDoc(fileList[i]).then(function(fileInfo){
that.merged++;
console.log("Merged doc " + that.merged +"/" + that.toMerge);
if (that.merged===that.toMerge){
fullfill();
}
}, function(err){
console.log("Error! " + err.stack);
reject(err);
});
}
});
}
/**
* Merge the main doc page with the given remote source page
* @param fileInfo
*/
DocGenerator.prototype.mergeDoc = function(fileInfo) {
var that = this;
console.log("Replacing " + fileInfo.completeFileName + " with remote " + fileInfo.src + " on repo " + fileInfo.srcRepo +"...");
return new Promise(function(fullfill, reject) {
that.cloneRepo(fileInfo.srcRepo, fileInfo.id).then(function(cloneFolder){
var mainDocBaseFolder = path.dirname(fileInfo.completeFileName);
var mainDocBaseFileName = path.basename(fileInfo.completeFileName);
//copy images if required
if (fileInfo.imageSrc){
try {
//copy images folder into main doc relative path
var imageSrcFolder = path.join(cloneFolder, fileInfo.imageSrc);
var imageDestFolder = mainDocBaseFolder;
//if defined use imagePath, elsewhere use the root folder
if (fileInfo.imagePath){
imageDestFolder = path.join(mainDocBaseFolder, fileInfo.imagePath);
}
fs.copySync(imageSrcFolder, imageDestFolder);
console.log("Copied images into "+ mainDocBaseFolder + "");
} catch (ee){
console.log(ee);
}
}
//copy the file
var docSrcFile = path.join(cloneFolder, fileInfo.src);
fs.copySync(docSrcFile, fileInfo.completeFileName);
fullfill(fileInfo);
}, function(er){
console.trace();
reject(er);
});
});
}
/**
* Clone the Master Doc project and move the documentation folder in the mainDocTempFolder
* @returns {Promise}
*/
DocGenerator.prototype.prepareMaster = function() {
var that = this;
return new Promise(function(fullfill, reject){
that.cloneMaster().then(function (cloneFolder){
console.log("Success: " + cloneFolder);
var mainDocTempFolder = that.mainDocTempFolder();
fs.moveSync(cloneFolder + that.config.mainDoc.folder, mainDocTempFolder);
fullfill({
"cloneFolder" : cloneFolder,
"mainDocTempFolder" : mainDocTempFolder
});
}, function (err){
console.trace(err);
reject(err);
});
});
}
/**
* Clone the Master Doc project defined into the config object mainDoc.repoUrl
*/
DocGenerator.prototype.cloneMaster = function() {
//var repoUrl = "https://gitlab.vipera.com/dynamic-engine/de-cli.git";
return this.cloneRepo(this.config.mainDoc.repoUrl, "/main-doc/");
}
/**
* Scan a documentation folder in order to find "<include>" tag and return the list of files with their content
*/
DocGenerator.prototype.scanDoc = function(docfolder){
var completeFileList = globby.sync(['**/*.md'], { cwd: docfolder });
var fileList = new Array();
for (var i=0;i<completeFileList.length;i++){
var fileName = completeFileList[i];
var completeFileName = path.join(docfolder, fileName);
var contents = fs.readFileSync(completeFileName);
var isIncludeFile = contents.includes("<dedoc-include");
if (isIncludeFile){
var doc = XML.parse( contents );
var id = md5(doc.repo + "_" + completeFileName);
var fileInfo = { "completeFileName": completeFileName,
"docFile": fileName,
"rawDocContent": contents,
"srcRepo" : doc.repo,
"src" : doc.src,
"docContent" : doc,
"id": id,
"imageSrc": doc.imageSrc,
"imagePath" : doc.imagePath
};
fileList.push(fileInfo);
}
}
return fileList;
}
DocGenerator.prototype.cloneRepo = function(repoURL, tempFolder){
var that = this;
console.log("Cloning git repo " + repoURL +"...");
return new Promise(function (fulfill, reject){
var workingDirPath = that.gitTempFolder(tempFolder);
var simpleGit = require('simple-git')();
var localPath = workingDirPath;
var gitOptions = {};
simpleGit.clone(repoURL, localPath, gitOptions, function(err, data){
if (err) {
reject(err);
}
else {
console.log("Git repo clone done.");
fulfill(localPath);
}
});
});
}
DocGenerator.prototype.gitTempFolder = function(folder) {
return this.tempFolder("/git/" + folder);
}
DocGenerator.prototype.mainDocTempFolder = function() {
return this.tempFolder("/main-doc/");
}
DocGenerator.prototype.tempFolder = function(folder) {
return path.join(this.tempFolderPath, folder);
}
DocGenerator.prototype.readConfig = function(args) {
var configFile = args.config;
if (!configFile){
configFile = "./docgen.json";
}
var obj = JSON.parse(fs.readFileSync(configFile, 'utf8'));
this.config = obj;
if (this.config.global && this.config.global.tempFolder){
this.tempFolderPath = this.config.global.tempFolder;
}
if (!this.tempFolderPath){
this.tempFolderPath = "./temp";
}
this.outFolder = args.out;
if (this.config.global && this.config.global.outFolder){
this.outFolder = this.config.global.outFolder;
}
if (!this.outFolder){
this.outFolder = "./out";
}
}
DocGenerator.prototype.cleanTempFolder = function()
{
fs.removeSync(this.tempFolderPath);
}
// export the class
module.exports = DocGenerator;