UNPKG

jsduckify

Version:

Enables the use of Sencha's JSDuck for documenting CoffeeScript projects.

219 lines (183 loc) 7.28 kB
path = require('path') fs = require('fs') {spawn, exec} = require('child_process') #jsduckify = require('../') #{duckifyFiles, documentExportsAPI, buildMainFile} = jsduckify documentExportsAPI = require('./documentExportsAPI').documentExportsAPI duckifyFiles = require('./duckifyFiles').duckifyFiles buildMainFile = require('./buildMainFile').buildMainFile _run = (command, options, next) -> if options? and options.length > 0 command += ' ' + options.join(' ') exec(command, (error, stdout, stderr) -> if stderr.length > 0 and error? console.log("Stderr exec'ing command '#{command}'...\n" + stderr) console.log(error) if next? next(error, stdout, stderr) else if stdout.length > 0 and stdout? console.log("Stdout exec'ing command '#{command}'...\n" + stdout) ) _emptyDirectory = (target) -> _rm(path.join(target, p)) for p in fs.readdirSync(target) _rm = (target) -> if fs.existsSync(target) if fs.statSync(target).isDirectory() _emptyDirectory(target) fs.rmdirSync(target) else fs.unlinkSync(target) # Command line options OPTIONS = '--help, -h ': 'Displays this help' '--prefix, -p <prefix> ': 'Specifies the root to prefix all documentation (default: <module_name>)' '--output, -o <output_directory> ': 'Output directory (default: <prefix>_jsduckify)' '--docsoutput, -d <doc_directory>': 'JSDuck output directory (default: <module_name>_jsduckify_JSDuckDocs)' '--noduck, -n ': 'Tells jsduckify not to call JSDuck when done duckifying' '--readme, -r ': 'Tells jsduckify to use the README.md as the docs for the main file' help = () -> #Show help message and exit console.log(''' Usage: jsduckify [options] [module_directory (default .)] Options: ''') for flag, description of OPTIONS console.log(' ' + flag + ': ' + description) process.exit(1) opts = process.argv[2...process.argv.length] if opts.length == 0 then help() noduck = false searchNodeModules = false readme = false while opts[0]? and opts[0].substr(0, 1) == '-' o = opts.shift() switch o when '-h', '--help' help() when '-o', '--output' outputDirectory = opts.shift() when '-d', '--docoutput' docoutput = opts.shift() when '-p', '--prefix' prefix = opts.shift() when '-n', '--noduck' noduck = true when '-r', '--readme' readme = true if opts.length == 1 moduleDirectory = opts[0] unless fs.statSync(moduleDirectory).isDirectory() help() else if opts.length == 0 moduleDirectory = '.' else console.error('No target directory specified.') help() moduleDirectory = path.resolve(moduleDirectory) unless prefix? prefix = path.basename(path.resolve(moduleDirectory)) unless outputDirectory? outputDirectory = prefix + '_jsduckify' unless docoutput? resolvedoutputDirectory = path.resolve(outputDirectory) docoutput = path.join(path.dirname(resolvedoutputDirectory), path.basename(resolvedoutputDirectory, '.js')) + '_JSDuckDocs' # Get source file paths _getsourceFiles = (target, a) -> if not a? a = [] if path.extname(target) == '.coffee' a.push(target) else if fs.statSync(target).isDirectory() if searchNodeModules or path.basename(target) != 'node_modules' _getsourceFiles(path.join(target, p), a) for p in fs.readdirSync(target) return a sources = _getsourceFiles(moduleDirectory) _removeBasePath = (filename, baseToRemove) -> unless filename.indexOf(baseToRemove) == 0 or baseToRemove in ['', './', '.'] throw new Error("Filename #{filename} does not start with #{baseToRemove}") return filename.slice(baseToRemove.length) sourceFileMap = {} for s in sources key = _removeBasePath(s, moduleDirectory) sourceFileMap[key] = fs.readFileSync(s, 'utf8') exportsAPI = documentExportsAPI(moduleDirectory) # {key = fileName: value = string with .js file to be written to disk} duckifiedFileMap = duckifyFiles(sourceFileMap, prefix, exportsAPI) #for key, value of duckifiedFileMap # console.log(key, value.length) # Get README.md if readme fileNames = fs.readdirSync(moduleDirectory) for f in fileNames if f.toLowerCase() == 'readme.md' readmePath = path.join(moduleDirectory, f) break if readmePath? readmeString = fs.readFileSync(readmePath, 'utf8') else readmeString = '' mainSourceString = null if fs.existsSync(path.join(moduleDirectory, 'package.json')) packageDotJSONString = fs.readFileSync(path.join(moduleDirectory, 'package.json'), 'utf8') packageJSON = JSON.parse(packageDotJSONString) if packageJSON.main? mainFilename = path.join(moduleDirectory, packageJSON.main) unless mainFilename.indexOf('.coffee') > 0 mainFilename += '.coffee' if fs.existsSync(mainFilename) mainSourceString = fs.readFileSync(mainFilename, 'utf8') else console.error("Could not find mainfile at #{mainFilename}.") else console.log("Found package.json but no 'main' key in it.") unless mainSourceString? mainFilename = path.join(moduleDirectory, 'index.coffee') if fs.existsSync(mainFilename) mainSourceString = fs.readFileSync(mainFilename, 'utf8') else console.log("Couldn't find 'index.coffee'. Creating dummy index.coffee.") mainFilename = path.join(moduleDirectory, 'index.coffee') mainSourceString = """ # Spaceholder CoffeeScript """ mainFileString = buildMainFile(mainFilename, readmeString, mainSourceString, exportsAPI, prefix) duckifiedFileMap[path.basename(mainFilename) + '.js'] = mainFileString if outputDirectory? _rm(outputDirectory) _createDirectoryTree = (directoryTreeArray, index) -> currentDirectoryArray = directoryTreeArray.slice(0, index + 1) currentDirectory = currentDirectoryArray.join(path.sep) unless fs.existsSync(currentDirectory) fs.mkdirSync(currentDirectory) unless index >= directoryTreeArray.length - 1 or directoryTreeArray[index + 1] == '' _createDirectoryTree(directoryTreeArray, index + 1) process.chdir(moduleDirectory) for fileName, fileContents of duckifiedFileMap if fileContents? fullFileName = path.join(outputDirectory, fileName) directoryTreeArray = path.join(outputDirectory, path.dirname(fileName)).split(path.sep) _createDirectoryTree(directoryTreeArray, 0) fs.writeFileSync(fullFileName, fileContents, 'utf8') # Run jsduck unless noduck _rm(docoutput) options = [] options.push('-o') options.push("'" + docoutput + "'") jsduckConfigFilename = path.join(moduleDirectory, 'jsduck-config.json') jsduckCategoriesFilename = path.join(moduleDirectory, 'jsduck-categories.json') if fs.existsSync(jsduckConfigFilename) options.push("--config='#{jsduckConfigFilename}'") if fs.existsSync(jsduckCategoriesFilename) options.push("--categories='#{jsduckCategoriesFilename}'") options.push("'" + outputDirectory + "'") _run('jsduck', options, (error, stdout, stderr) -> unless error? _rm(outputDirectory) if error console.log('*** Error from running JSDuck...\n' + error) console.log('*** Stdout from running JSDuck...\n' + stdout) console.log('*** Stderr from running JSDuck...\n' + stderr) )