structure-graph-webpack-plugin
Version:
A webpack plugin to generate project structure graph
106 lines • 2.9 kB
JavaScript
const path = require('path')
const fs = require('fs')
// const pluginName = 'StructureGraphPlugin'
module.exports = class StructureGraphPlugin {
defaultOptions = {
targetName: 'structure.txt',
ignoreDirectorys: [],
ignoreFiles: [],
dress: 'dashed'
}
constructor(options) {
this.options = Object.assign(this.defaultOptions, options)
}
parser(file, pathStr) {
const { ignoreDirectorys, ignoreFiles } = this.options
pathStr = path.resolve(pathStr, file)
let stat = fs.lstatSync(pathStr)
let children = []
if(stat.isDirectory() && !ignoreDirectorys.includes(file)) {
const files = fs.readdirSync(pathStr, 'utf8')
children = files.filter(item => !ignoreFiles.includes(item)).map(item => {
return this.parser(item, pathStr)
})
}
return {
name: file,
type: stat.isDirectory() ? 'directory' : 'file',
children
}
}
transfer(arr, projectName) {
const { ignoreDirectorys, ignoreFiles } = this.options
const ignoreList = ignoreDirectorys.concat(ignoreFiles)
return (pathStr) => {
let data = [
{
name: projectName,
children: []
}
]
data[0].children = arr.filter(item => !ignoreList.includes(item)).map(item => {
const file = this.parser(item, pathStr)
return file
})
return data
}
}
generate(arr, level = -1) {
let str = ''
let mid = ' '
level ++
for(let i = 0, len = arr.length; i < len; i++) {
let item = arr[i]
if(!level) {
str += `+-- ${item.name}\n`
}else {
str += `¦${mid.repeat(level)}+-- ${item.name}\n`
}
if(item.children) {
str += this.generate(item.children, level)
}
}
return str
}
generateSolid(arr, level = -1) {
let str = ''
let mid = '│ '
let majorFlag = '├─'
let minorFlag = '└─'
level ++
arr.sort((prev, next) => prev.children > next.children ? -1 : 1)
for(let i = 0, len = arr.length; i < len; i++) {
let item = arr[i]
if (!level) {
str += `${minorFlag} ${item.name}\n`
} else {
if(i === len -1) {
str += ` ${mid.repeat(level - 1)}${minorFlag} ${item.name}\n`
}else {
str += ` ${mid.repeat(level - 1)}${majorFlag} ${item.name}\n`
}
}
if(item.children) {
str += this.generateSolid(item.children, level)
}
}
return str
}
apply(compiler) {
compiler.hooks.beforeCompile.tap(this.constructor.name, () => {
const { targetName, dress } = this.options
const rootDirectory = process.cwd()
const files = fs.readdirSync(rootDirectory, 'utf8')
const prjName = rootDirectory.split('/').slice(-1)[0]
const file = path.resolve(rootDirectory, targetName)
let structData = this.transfer(files, prjName)(path.resolve(rootDirectory))
let outputStr = ''
if(dress === 'dashed') {
outputStr = this.generate(structData)
}else {
outputStr = this.generateSolid(structData)
}
fs.writeFileSync(file, outputStr)
})
}
}