/
cli.coffee
181 lines (166 loc) · 6.37 KB
/
cli.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
##
# Provides CroJSDoc command line interface
# @module cli
fs = require 'fs'
glob = require 'glob'
walkdir = require 'walkdir'
{basename,dirname,join,resolve} = require 'path'
isWindows = process.platform is 'win32'
##
# Reads a config file(crojsdoc.yaml) to build options
# @param {Options} options
# @memberOf cli
_readConfig = (options) ->
{safeLoad} = require 'js-yaml'
try
config = safeLoad fs.readFileSync(join(process.cwd(), 'crojsdoc.yaml'), 'utf-8')
if config.hasOwnProperty 'output'
options.output = config.output
if config.hasOwnProperty 'title'
options.title = config.title
if config.hasOwnProperty 'quiet' or config.hasOwnProperty 'quite'
options.quiet = config.quiet is true
if config.hasOwnProperty 'files'
options.files = config.files is true
if config.hasOwnProperty('readme') and typeof config.readme is 'string'
options._readme = config.readme
if config.hasOwnProperty 'external-types'
options['external-types'] = config['external-types']
if config.hasOwnProperty 'sources'
if Array.isArray config.sources
[].push.apply options._sources, config.sources
else
options._sources.push config.sources
if config.hasOwnProperty 'github'
options.github = config.github
if options.github.branch is undefined
options.github.branch = 'master'
if config.hasOwnProperty 'reverse_see_also'
options.reverse_see_also = config.reverse_see_also is true
if config.hasOwnProperty 'plugins'
plugins = config.plugins
if not Array.isArray plugins
plugins = [plugins]
options.plugins = plugins.map (plugin) ->
try
require plugin
catch e
console.log "Plugin '#{plugin}' not found"
.filter (plugin) -> plugin
return
##
# Parses the command line arguments to build options
# @param {Options} options
# @memberOf cli
_parseArguments = (options) ->
{OptionParser} = require 'optparse'
switches = [
[ '-h', '--help', 'show help' ]
[ '-o', '--output DIRECTORY', 'Output directory' ]
[ '-t', '--title TITLE', 'Document Title' ]
[ '-q', '--quiet', 'less output' ]
[ '-r', '--readme DIRECTORY', 'README.md directory path']
[ '-f', '--files', 'included source files' ]
[ '--external-types JSONFILE', 'external type definitions' ]
]
parser = new OptionParser switches
parser.banner = 'Usage: crojsdoc [-o DIRECTORY] [-t TITLE] [-q] [options..] SOURCES...'
parser.on 'help', ->
console.log parser.toString()
process.exit(1)
parser.on '*', (opt, value) ->
if value is undefined
value = true
options[opt] = value
[].push.apply options._sources, parser.parse process.argv.slice 2
##
# Reads additional type definitions from a file or a object
# @param {String|Object} external_types
# @param {Object} types
# @memberOf cli
_readExternalTypes = (external_types, types) ->
return if not external_types
if typeof external_types is 'string'
try
content = fs.readFileSync(external_types, 'utf-8').trim()
try
external_types = JSON.parse content
catch e
console.log "external-types: Invalid JSON file"
catch e
console.log "external-types: Cannot open #{external_types}"
if typeof external_types is 'object'
for type, url of external_types
types[type] = url
##
# Builds options from a config file(crojsdoc.yaml) or command line arguments
# @return {Options}
# @memberOf cli
_buildOptions = ->
options =
_project_dir: process.cwd()
types:
# Links for pre-known types
Object: 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object'
Boolean: 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Boolean'
String: 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String'
Array: 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array'
Number: 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Number'
Date: 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date'
Function: 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function'
RegExp: 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/RegExp'
Error: 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error'
undefined: 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/undefined'
_sources: []
_readConfig options
_parseArguments options
if options.plugins
options.plugins.forEach (plugin) ->
if plugin.externalTypes
_readExternalTypes plugin.externalTypes, options.types
return
# process options.external-types after plugins' externalTypes
# for user to override plugins' configurations
_readExternalTypes options['external-types'], options.types
options.output_dir = resolve options._project_dir, options.output or 'doc'
return options
##
# Reads source files
# @param {Options} options
# @return {Array<Content>}
# @memberOf cli
_readSourceFiles = (options) ->
if isWindows
project_dir_re = new RegExp("^" + options._project_dir.replace(/\\/g, '\\\\'))
else
project_dir_re = new RegExp("^" + options._project_dir)
contents = []
for path in options._sources
base_path = path = resolve options._project_dir, path
base_path = dirname base_path while /[*?]/.test basename(base_path)
glob.sync(path).forEach (path) =>
if fs.statSync(path).isDirectory()
list = walkdir.sync path
else
list = [path]
for file in list
continue if fs.statSync(file).isDirectory()
data = fs.readFileSync(file, 'utf-8').trim()
continue if not data
if isWindows
contents.push full_path: file.replace(project_dir_re, '').replace(/\\/g, '/'), path: file.substr(base_path.length+1).replace(/\\/g, '/'), data: data
else
contents.push full_path: file.replace(project_dir_re, ''), path: file.substr(base_path.length+1), data: data
return
try
data = fs.readFileSync "#{options._readme or options._project_dir}/README.md", 'utf-8'
contents.push full_path: '', path: 'README', data: data
return contents
##
# Runs CroJSDoc via CLI
# @memberOf cli
exports.run = ->
options = _buildOptions()
contents = _readSourceFiles options
result = require('./collect') contents, options
require('./render') result, options