forked from koding/koding
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocgen.coffee
More file actions
executable file
·147 lines (109 loc) · 3.78 KB
/
Copy pathdocgen.coffee
File metadata and controls
executable file
·147 lines (109 loc) · 3.78 KB
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
#!/usr/bin/env coffee
codo = require 'codo'
_ = require 'lodash'
generateSchema = (sample, required = no) ->
# The MIT License (MIT) Copyright ⒞ 2016 Santtu Pajukanta
# Taken from https://github.com/japsu/json-schema-by-example/blob/master/index.js
# which is designed for es6 wasn't working with current
# node version that we have and there was a missing
# feature that we needed.
#
# This one provides `default` value of fields
# in the schema so we can completely define the schema by providing
# one simple example in the docs ~ GG
#
# TODO make a pull request to https://github.com/japsu/json-schema-by-example
# or make a new package based on this one ~ GG
rules = [
[_.isNull, (data) -> { type: 'null', default: data }],
[_.isNumber, (data) -> { type: 'number', default: data }],
[_.isString, (data) -> { type: 'string', default: data }],
[_.isBoolean, (data) -> { type: 'boolean', default: data }],
[_.isRegExp, (pattern) -> { type: 'string', pattern }],
[
(example) -> _.isArray(example) and not example.length
, ->
{ type: 'array' }
],
[
_.isArray
, (items) -> {
type: 'array', items: generateSchema items[0]
}
],
[
_.isPlainObject
, (object) ->
obj = {
type: 'object',
properties: _.mapValues object, (sample) -> generateSchema sample
}
obj.required = _.keys object if required
return obj
]
]
for [isMatch, makeSchema] in rules when isMatch sample
return makeSchema sample
throw new TypeError sample
compileApiExamples = (examples, methodOptions) ->
for example, index in examples when example.title in ['api', 'return']
try
example.schema = generateSchema (JSON.parse example.code)
catch e
console.log 'Failed to parse example:', example, e
return examples
module.exports = docGen = (path, files) ->
errors = []
doc = {}
unless path
errors.push 'A valid path is required!'
return { errors, doc }
options = {}
if files?.length > 0
options.inputs = files
environment = codo.parseProject path, options
for klass in environment.allClasses()
classDoc = klass.documentation ? {}
if doc.hasOwnProperty klass.name
errors.push "Duplicate Class #{klass.name}"
else
description = classDoc.comment ? "Model #{klass.name}"
parameters = classDoc.params ? []
examples = compileApiExamples (classDoc.examples ? [])
doc[klass.name] = {
description
parameters
examples
instance : {}
static : {}
}
klass.methods.forEach (method) ->
methodDoc = method.documentation ? {}
kind = if method.kind is 'dynamic' then 'instance' else 'static'
if doc[klass.name][kind].hasOwnProperty method.name
errors.push "Duplicate method on #{klass.name}.#{kind}.#{method.name}"
else
doc[klass.name][kind][method.name] = {}
methodOptions = methodDoc.options ? {}
doc[klass.name][kind][method.name] =
description : methodDoc.comment ? "Method #{klass.name}.#{method.name}"
parameters : methodDoc.params ? []
returns : methodDoc.returns ? {}
options : methodOptions
examples : compileApiExamples (methodDoc.examples ? []), methodOptions
return { errors, doc }
unless module.parent
unless project = process.argv[2]
console.log '''
usage: docgen [path]
where path refers to source code path for docs to generate
'''
process.exit 1
try
{ errors, doc } = docGen project
catch e
console.log 'An error occured', e
console.log JSON.stringify doc, ' ', 2
if errors.length > 0
console.log 'Has some errors:', JSON.stringify errors, ' ', 2
process.exit()