Skip to content

Commit

Permalink
refactor: encapsulate *
Browse files Browse the repository at this point in the history
  • Loading branch information
w2xi committed Feb 5, 2024
1 parent a3c9072 commit 062704f
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 86 deletions.
15 changes: 15 additions & 0 deletions src/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const emoji = {
directory: '📁',
file: '📄',
}
const characters = {
border: '|',
contain: '├',
line: '─',
last: '└'
}

module.exports = {
emoji,
characters,
}
28 changes: 28 additions & 0 deletions src/generate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const { emoji, characters } = require('./config')
const { isNumber } = require('./utils')

function generate(data, options = {}, deep = 0) {
if (isNumber(options.level) && deep >= options.level) {
return ''
}
let output = ''

data.forEach((item, index) => {
const borderPrefix = (characters.border + ' '.repeat(3)).repeat(deep)
let contentPrefix = index === data.length - 1 ? characters.last : characters.contain
contentPrefix += characters.line.repeat(2)
const content = options.icon ? `${emoji[item.type]}${item.name}` : `${item.name}`

let currentLineStr = `${borderPrefix}${contentPrefix}${content}`
currentLineStr += '\n'
output += currentLineStr

if (item.children) { // directory
output += generate(item.children, options, deep + 1)
}
})

return output
}

module.exports = generate
112 changes: 26 additions & 86 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,11 @@

const fs = require('fs')
const { program } = require('commander')
const { fileExistSync, isDirectory } = require('./utils')
const { fileExistSync } = require('./utils')
const toTree = require('./toTree')
const generate = require('./generate')
const package = require('../package.json')

const map = {
directory: '📁',
file: '📄',
}
const characters = {
border: '|',
contain: '├',
line: '─',
last: '└'
}

program
.name('treei')
.version(package.version)
Expand All @@ -30,85 +21,34 @@ program

const options = program.opts()

let ignoreList = []
if (options.ignore) {
ignoreList = options.ignore.replace(/\s*/g, '').split(/,|\|/)
}

// The difference between statSync and lstatSync
// https://stackoverflow.com/questions/32478698/what-is-the-different-between-stat-fstat-and-lstat-functions-in-node-js
const onExits = []

function toTree(path, deep = 0) {
if (isDirectory(path)) {
let dir = fs.readdirSync(path)

if (ignoreList.length) {
dir = dir.filter(child => !ignoreList.includes(child))
}
if (options.onlyFolder) {
dir = dir.filter(child => isDirectory(`${path}/${child}`))
}
const children = dir.map(child => toTree(`${path}/${child}`, deep + 1))
const dirName = path.split('/').pop()

return {
type: 'directory',
name: dirName,
children,
}
} else {
return {
type: 'file',
name: path.split('/').pop(),
}
function handleOptions() {
if (options.ignore) {
options.ignore = options.ignore.replace(/\s*/g, '').split(/,|\|/)
}
if (options.level && !Number.isNaN(parseInt(options.level))) {
options.level = parseInt(options.level)
}
if (options.output) {
onExits.push((result) => {
let outputString = result
if (fileExistSync(options.output)) { // appending mode
outputString = '\n' + result
}
fs.appendFile(options.output, outputString, (err) => {
if (err) throw err
})
})
}
}

const root = toTree(options.directory)

let level
if (options.level && !Number.isNaN(parseInt(options.level))) {
level = parseInt(options.level)
}

function isReachedDepth(deep) {
return typeof level === 'number' && deep >= level
}

let output = ''

function generateTreeStructure(data, deep = 0) {
if (isReachedDepth(deep)) return
handleOptions()

data.forEach((item, index) => {
const borderPrefix = (characters.border + ' '.repeat(3)).repeat(deep)
let contentPrefix = index === data.length - 1 ? characters.last : characters.contain
contentPrefix += characters.line.repeat(2)
const content = options.icon ? `${map[item.type]}${item.name}` : `${item.name}`
let currentLineStr = `${borderPrefix}${contentPrefix}${content}`
const root = toTree(options.directory, options)
const result = generate(root.children, options)

currentLineStr += '\n'

if (item.children) { // directory
output += currentLineStr
generateTreeStructure(item.children, deep + 1)
} else { // file
output += currentLineStr
}
})
}

generateTreeStructure(root.children)

if (options.output) {
let outputString = output
if (fileExistSync(options.output)) { // appending mode
outputString = '\n' + output
}
fs.appendFile(options.output, outputString, (err) => {
if (err) throw err
})
}
onExits.forEach(onExit => onExit(result))

console.log(root.name)
console.log(output)
console.log(result)
34 changes: 34 additions & 0 deletions src/toTree.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const fs = require('fs')
const { isDirectory } = require('./utils')

// The difference between statSync and lstatSync
// https://stackoverflow.com/questions/32478698/what-is-the-different-between-stat-fstat-and-lstat-functions-in-node-js

function toTree(path, options = {}) {
if (isDirectory(path)) {
let dir = fs.readdirSync(path)
const ignoreList = options.ignore || []

if (ignoreList.length) {
dir = dir.filter(child => !ignoreList.includes(child))
}
if (options.onlyFolder) {
dir = dir.filter(child => isDirectory(`${path}/${child}`))
}
const children = dir.map(child => toTree(`${path}/${child}`))
const dirName = path.split('/').pop()

return {
type: 'directory',
name: dirName,
children,
}
} else {
return {
type: 'file',
name: path.split('/').pop(),
}
}
}

module.exports = toTree
5 changes: 5 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ function isDirectory(path) {
return stats.isDirectory()
}

function isNumber(value) {
return typeof value === 'number'
}

module.exports = {
fileExistSync,
isDirectory,
isNumber,
}

0 comments on commit 062704f

Please sign in to comment.