csycms-core
Version:
Markdown powered Knowledgebase
269 lines (234 loc) • 10.4 kB
JavaScript
const fse = require('fs-extra')
const path = require('path')
const _ = require('underscore')
const contentProcessors = require('../functions/contentProcessors')
const { config } = require('shelljs')
// const yargs = require("yargs")
// const appRoot = require('app-root-path')
// const base_url = appRoot.path
// const argv = yargs.argv
/**
* Csystem class
*/
class Csystem {
/**
* constructor
* @param {object} config
*/
constructor(config) {
this.config = config
this.loadPagesList();
}
/**
* Remove leading slash and leading directory and file numbers from paths
* @param {array} path - Optional. Reads from this.sortedFilesPaths if not provided
* @returns Array of file paths
*/
pathsNoLeadingSlashNorNumber = paths => {
if (!paths) {
paths = this.sortedFilesPaths
}
return paths.map(file => file.replace(/\/[0-9]*\./g, '/').replace(/^\//, ''))
}
/**
* Get urls for content files
* @param {array} paths - Optional. Reads from this.sortedFilesPaths if not provided
* @returns Array of relative urls without leading /
*/
sortedUrls = paths => {
if (!paths) {
paths = this.pathsNoLeadingSlashNorNumber(this.sortedFilesPaths)
}
paths[0] = paths[0].replace(/[^\/]+/,'')
return paths.map(file => file.replace(/\.md$/, '').replace(/\/chapter/, '').replace(/\/docs/, ''))
}
/**
* Get hierarchical list of urls, for sidebar
* @param {array} paths - Optional. Reads from this.sortedFilesPaths if not provided
* @returns Hierarchical list of urls
*/
nestedUrls = paths => {
if (!paths) {
paths = this.sortedUrls(this.pathsNoLeadingSlashNorNumber(this.sortedFilesPaths))
}
return this.listToTree(paths)
}
/**
* Get hierarchical list of all site pages
* @returns {oject}
*/
loadPagesList = () => {
let content_dir = path.join(this.config.directory, 'content')
let csycmsdocsDir = path.join(this.config.directory, 'content', 'csycmsdocs')
let files = this.listFiles(content_dir).sort();
/**
* ['/var/www/html/csycms/SITE1/content/01.basics/01.what-is-csycms/docs.md',
* '/var/www/html/csycms/SITE1/content/01.basics/02.Requirements/docs.md',..]
*/
// console.log(files)
files = _.filter(files, (file) => {
// remove csycmsdocs if documentation is disabled.
let allowCsycmsDocs = this.config.documentation
return file.match(/\.md$/) && (allowCsycmsDocs ? true : !file.includes(csycmsdocsDir));
});
// remove wrongly named files
files = _.filter(files, (file) => {
return file.match(/\/docs\.md$/) || file.match(/\/chapter\.md$/);
});
let sortedFilesPaths = files.map(file => file.replace(content_dir, '').replace(/docs\.md$/, `00.docs`).replace(/chapter\.md$/, `00.chapter`)).sort();
sortedFilesPaths = sortedFilesPaths.map(file => file.replace(/00.docs$/, 'docs.md').replace(/00.chapter$/, 'chapter.md'))
/** sorted file paths */
this.sortedFilesPaths = [...sortedFilesPaths];
let sortedFilesPathsNoLeadingSlashNorNumber = this.pathsNoLeadingSlashNorNumber()
this.sortedFilesPathsNoLeadingSlashNorNumber = [...sortedFilesPathsNoLeadingSlashNorNumber]
// console.log(sortedFilesPathsNoLeadingSlashNorNumber)
return
}
/**
* Put files into hierarchical list of directories
* @param {Array} files - list of file paths
* @returns {array} hierarchical list of directories
*/
listToTree = files =>
files.map(file => file.split('/'))
.reduce((out, path) => {
// console.log(out)
// console.log(path)
// process.exit();
let top = out;
while (path.length > 0) {
let node = path.shift();
if (top.findIndex(n => n.text === node) === -1) {
top.push({
text: node
});
}
// console.log('top')
// console.log(top)
if (path.length > 0) {
let index = top.findIndex(n => n.text === node);
top[index] = top[index] || {};
top[index].children = top[index].children || [];
top[index].children.push({
text: path[0]
});
top = top[index].children;
}
}
return out;
}, []);
/**
* List all paths of all files in a directory looping through all directories within the given directory
* @param {string} dir
* @returns {array} An array of paths of all files in the provided directory
*/
listFiles = dir => {
return fse.readdirSync(dir).reduce((list, file) => {
let name = path.join(dir, file);
let isDir = fse.statSync(name).isDirectory();
return list.concat(isDir ? this.listFiles(name) : [name]);
}, []);
}
build_nested_pages(originalPageList, refPageList, content_dir) {
let nestedPages = [];
let pageParts = []
, metas = []
, self = this
for (let i in originalPageList) {
let filePath = path.join(content_dir, originalPageList[i])
filePath = filePath.replace('00.chapter.md', 'chapter.md')
const file = fse.readFileSync(filePath);
const meta = contentProcessors.processMeta(file.toString('utf-8'));
metas[i] = meta
}
let { pageListWithTitle } = originalPageList.reduce((accumulator, currentValue, currentIndex, originalPageListArray) => {
accumulator.pageListWithTitle.push({ path: currentValue, index: currentIndex, slug: refPageList[currentIndex], title: metas[currentIndex].title })
return accumulator
}, { pageListWithTitle: [] })
nestedPages = self.build_nested_pages_inner(pageListWithTitle, 0).slice(1)
return nestedPages
}
build_nested_pages_inner(pageListWithTitle, level, debug) {
let self = this
, chapters = []
, prevChapterNum = 0
, prevDir = ''
, getIndex = (list, Indexinner) => {
for (let i in list) {
if (list[i].index === Indexinner) return i
}
return NaN
}
if (debug) {
console.log(pageListWithTitle)
}
for (let i in pageListWithTitle) {
let filePath = pageListWithTitle[i].path
let parts = filePath.split('.')
let chapterNum = parseInt(parts[0].replace('/', ''))
let thisDir = filePath.split('/')[1]
if (filePath === '/docs.md') continue;
if (!isNaN(chapterNum)) {
if (debug) {
console.log(parts)
}
}
else {
if (thisDir !== prevDir)
chapterNum = prevChapterNum + 1
}
prevChapterNum = chapterNum
prevDir = filePath.split('/')[1]
if (!chapters[chapterNum]) {
parts = filePath.split('/')
let folderPart = '/' + parts[1];
let { numFiles, files_in_dir } = pageListWithTitle.reduce((accumulator, currentValue, currentIndex, originalPageListArray) => {
let testLen = currentValue.path.split('/').length
let testLenResult = testLen === 3 || testLen === 4 ? true : false;
let threeparts = currentValue.path.split('/')
threeparts = [threeparts[0], threeparts[1], threeparts[2]].join('/')
if (debug) console.log(`${accumulator.needle}=>${currentValue.path}`)
if (currentValue.path.indexOf(accumulator.needle) === 0 && currentValue.path !== '/docs.md') {
accumulator.numFiles++
accumulator.files_in_dir.push({ name: currentValue.path, index: currentValue.index })
}
return accumulator
}, { needle: folderPart, numFiles: 0, files_in_dir: [], numDirs: 0 })
chapters[chapterNum] = {
slug: pageListWithTitle[i].slug,
title: pageListWithTitle[i].title,
chapterNum: chapterNum,
show_on_home: true,
is_directory: numFiles > 1 ? true : false,
}
if (level === 0) numFiles--;
if (numFiles > 0) {
chapters[chapterNum].files = []
let pageListWithTitleInner = []
for (let j in files_in_dir) {
let item = files_in_dir[j]
let itemNameParts = item.name.split('/')
let indexInner = item.index
let pathinner = itemNameParts.slice(2)
pathinner = '/' + pathinner.join('/')
let itemInner = {
path: pathinner,
index: item.index,
slug: pageListWithTitle[getIndex(pageListWithTitle, indexInner)].slug,
title: pageListWithTitle[getIndex(pageListWithTitle, indexInner)].title
}
if (pathinner !== '/')
pageListWithTitleInner.push(itemInner)
}
// chapters[chapterNum].files = self.build_nested_pages_inner(pageListWithTitleInner, level+1, '/01.environment/docs.md' === filePath?true:false).slice(1)
chapters[chapterNum].files = self.build_nested_pages_inner(pageListWithTitleInner, level + 1, false).slice(1)
} else chapters[chapterNum].is_index = true
} else {
;
}
}
return chapters
}
}
module.exports = Csystem