@gkotulski/doc_preprocessing
Version:
Preprocess 4D doc to be built by docusaurus
172 lines (153 loc) • 5.99 kB
JavaScript
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