Skip to content

Instantly share code, notes, and snippets.

@liunian
Created December 27, 2014 15:06
Show Gist options
  • Save liunian/f222272307e6a2b4fe1b to your computer and use it in GitHub Desktop.
Save liunian/f222272307e6a2b4fe1b to your computer and use it in GitHub Desktop.
/**
* find all markdown files in given directory, (here just current directory)
* and then fetch their title to generate index markdown file
*
* use -v to show verbose detail
* use -o to specify output file, default to ./index.md
* use -d to specify scanner directory, such as -d the_directory, default to ./
*/
var fs = require('fs'),
path = require('path')
var mdExts = ['.md', '.markdown']
var excludeDir = ['.git']
function isMarkdownFile(filePath) {
return mdExts.indexOf(path.extname(filePath).toLowerCase()) !== -1
}
function isNotExlude(dir) {
return excludeDir.indexOf(dir) == -1
}
function getNamedCommandLineArgs(list) {
var ret = {},
p = /^\-([^\-].*)/
for (var i = 0, l = list.length; i < l; ) {
var m = list[i].match(p)
if (m && m[1]) {
var k = m[1],
v = ''
if (i + 1 < l) {
if (!p.test(list[i+1])) {
v = list[i+1]
i += 2
} else {
i++
}
} else {
i++
}
ret[k] = v
} else {
i++
}
}
return ret
}
function findMarkdownFiles(dir) {
if (!dir || !fs.existsSync(dir)) return []
var mdFiles = []
var files = fs.readdirSync(dir)
files.forEach(function(file) {
filePath = path.join(dir, file)
var st = fs.statSync(filePath)
if (st && st.isFile() && isMarkdownFile(filePath)) {
mdFiles.push(filePath)
} else if (st && st.isDirectory() && isNotExlude(file)) {
mdFiles = mdFiles.concat(findMarkdownFiles(filePath))
}
})
return mdFiles
}
function isTitleDash(str) {
var p = /^(?:\-+|=+)[\s\t]*$/
return p.test(str)
}
function getMarkDownFileTitle(filePath) {
/*
1. readFile
2. trim
3. first line: index of #, and limit in (1, 6) yes to 4, no to 5
4. get string from the last continues #
5. if the second line is = or - , return the first line, else return empty string
*/
var title = ''
// try to use file name as default
try {
title = path.basename(filePath, path.extname(filePath))
} catch(e) {}
try {
var lines = fs.readFileSync(filePath).toString().split('\n')
var i = 0, l = lines.length
while (i < l && lines[i].trim() === '') {
i++
}
// starts with #
var startPattern = /^#{1,6}(?:[\s\t]*)(.*)/,
startMatches = lines[i].match(startPattern)
if (startMatches) {
if (startMatches[1]) {
title = startMatches[1].trim()
}
} else {
var nextLine = lines[i + 1]
if (i + 1 < l && nextLine) {
if (isTitleDash(nextLine)) {
title = lines[i].trim()
}
}
}
} catch(e) {
typeof console === 'object' && console.warn && console.warn(e)
}
return title
}
function createIndexPageWithData(targetFile, data) {
var lines = ['# wiki 索引']
data.forEach(function(item) {
lines.push('- [' + item.title + '](' + item.file + ')')
})
try {
fs.writeFile(targetFile, lines.join('\n'))
console.log('success generate', targetFile)
} catch(e) {
console.error('failed to generate', targetFile, e)
}
}
// run
var argsObj = getNamedCommandLineArgs(process.argv.slice(2)),
scanDir = argsObj.d || './',
outputFile = argsObj.o || './index.md',
verbose = argsObj.v !== undefined
if (verbose) {
console.log('name args', argsObj, '\n')
console.log('title from md files')
}
var ret = findMarkdownFiles(scanDir).map(function(mdFilePath) {
var title = getMarkDownFileTitle(mdFilePath)
if (verbose) {
console.log(' ', title, '<=', mdFilePath)
}
// remove .md extension (actually remove all extension)
// so gitlab will render it rather than show source code
return {
file: path.join(path.dirname(mdFilePath), path.basename(mdFilePath, path.extname(mdFilePath))),
title: title
}
})
if (verbose) {
console.log('\n')
}
createIndexPageWithData(outputFile, ret)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment