UNPKG

@gkotulski/doc_preprocessing

Version:
172 lines (153 loc) 5.99 kB
var fs = require('fs'); var path = require('path') const { PreprocessorInstructor, TYPE} = require("./preprocessorInstruction") const {PreprocessorRef, REFManager} = require("./preprocessorRef") const log = require('./log') function trimFirstLineBreak(inText) { let text = "" let firstIndex = 0 const lastIndex = inText.length if(inText.length > 0) { if(inText[0] === '\r') { firstIndex++ if(inText[1] === '\n') { firstIndex++ } } else if(inText[0] === '\n') { firstIndex++ } } if(firstIndex < lastIndex) { text = inText.substr(firstIndex, lastIndex - firstIndex) } return text } function getFileList(dir, parent, filelist) { const files = fs.readdirSync(dir); filelist = filelist || []; parent = parent || dir; files.forEach(function(file) { if (fs.statSync(dir + file).isDirectory()) { filelist = getFileList(dir + file + '/', parent, filelist); } else { filelist.push((dir + file).replace(parent, "")); } }); return filelist; } class Preprocessing { constructor(path, destination) { this._path = path this._destination = destination this._refManager = new REFManager() } collect() { getFileList(this._path).forEach(file => { const currentPath = this._path + file const extension = path.extname(file) if(extension === ".md") { const content = fs.readFileSync(currentPath, 'utf8'); const re = /(<!--)(.*?)(-->)/g let stack = [] let match while ((match = re.exec(content)) != null) { var keywords = match[2].trim().split(" ") switch(keywords[0]) { case TYPE.REF: if(keywords.length > 1) { let item = new PreprocessorRef() item.start = match.index + match[0].length item.ID = keywords[1] item.filePath = currentPath; stack.push(item) } else { log.show(log.MESSAGE.ERROR, "Missing id for reference") } break case "END": if(stack.length > 0) { let item = stack.pop() if(item.getType() === TYPE.REF) { item.end = match.index item.resolve(content) this._refManager.push(item) } } else { log.show(log.MESSAGE.ERROR, "Too many 'END' in file " + currentPath) } break } } } }); } _resolveInclude(inContent, inPath) { let re = /(<!--)(.*?)(-->)([\r]?[\n])?/g let match let startIndex = 0 let currentContent = "" while ((match = re.exec(inContent)) != null) { currentContent += inContent.substr(startIndex, match.index - startIndex) let keywords = match[2].trim().split(" ") switch(keywords[0]) { case TYPE.INCLUDE: if(keywords.length > 1) { let value = this._refManager.getContentFromID(keywords[1]) if(value.error === true) { const lineEnding = match[4] != undefined ? match[4] : "" let c = trimFirstLineBreak(value.content) + lineEnding currentContent += this._resolveInclude(c, inPath) } else { log.show(log.MESSAGE.WARNING, "The include \'" + keywords[1] + "\' in path " + inPath + " has an invalid reference") } } break } startIndex = match.index + match[0].length } currentContent += inContent.substr(startIndex, inContent.length - startIndex) return currentContent } resolve(inPath) { const content = fs.readFileSync(inPath, 'utf8'); return this._resolveInclude(content, inPath) } write(inPath, newContent) { fs.promises.mkdir(path.dirname(inPath), {recursive: true}).then(x => fs.promises.writeFile(inPath, newContent)) } copy(inPath, toPath) { fs.promises.mkdir(path.dirname(toPath), {recursive: true}).then(x => fs.copyFileSync(inPath, toPath)) } run() { this.collect() getFileList(this._path).forEach(file => { const currentPath = this._path + file const destination = this._destination + file const extension = path.extname(file) if(extension === ".md") { const content = this.resolve(currentPath) this.write(destination, content) } else { if(fs.existsSync(destination)) { if(new Date(fs.statSync(destination).mtime).getTime() !== new Date(fs.statSync(currentPath).mtime).getTime()) { this.copy(currentPath, destination) } } else { this.copy(currentPath, destination) } } }); } } exports.Preprocessing = Preprocessing