nebulab-dropbox
Version:
Client library for the Dropbox API
315 lines (266 loc) • 10.8 kB
text/coffeescript
fs = require 'fs'
mustache = require 'mustache'
path = require 'path'
S = require 'string'
yaml = require 'js-yaml'
jsonDoc = (yamlDir, toc) ->
classIndexPath = path.join yamlDir, 'class_index.yaml'
index = yaml.load fs.readFileSync(classIndexPath, 'utf8')
classes = index.classes
classIndex = {}
for klass in classes
classPath = path.join yamlDir, klass.href
klass.data = yaml.load fs.readFileSync(classPath, 'utf8')
classIndex[klass.namespace + '.' + klass.name] = klass
tocIndex = 0
for section in toc.sections
for entry in section.entries
unless classIndex[entry.class]
throw new Error "TOC entry not found: #{entry.class}"
tocIndex += 1
classIndex[entry.class].tocIndex = tocIndex
inf = classes.length + 1
classes.sort (a, b) ->
if a.tocIndex or b.tocIndex
(a.tocIndex or inf) - (b.tocIndex or inf)
else if a.namespace is b.namespace
a.name.localeCompare b.name
else
a.namespace.localeCompare b.namespace
for klass in classes
continue unless klass.data.includes
for included in klass.data.includes
includedMixin = classIndex[included.name]
for method in includedMixin.data.methods
continue if method.private
methodClone = JSON.parse(JSON.stringify(method))
methodClone.type = 'instance'
klass.data.instanceMethods.push methodClone
nameIndex = makeNameIndex classes
json = { classes: [] }
for klass in classes
continue if klass.type is 'Mixin'
jsonCMethods = []
jsonIMethods = []
jsonClass =
name: klass.namespace + '.' + klass.name
desc: xref(klass.data.doc.comment, nameIndex)
sections: []
json.classes.push jsonClass
methodSections = [
{
methods: klass.data.classMethods, name: 'Class Methods',
type: 'class'
},
{
methods: klass.data.instanceMethods, name: 'Instance Methods',
type: 'instance'
}
]
for section in methodSections
continue unless section.methods and section.methods.length isnt 0
jsonMethods = []
jsonClass.sections.push(
section_name: section.name, methods: jsonMethods)
for method in section.methods
jsonMethod =
desc: ''
method_name: method.name
method_type: section.type
discussion: xref(method.comment, nameIndex)
formattedComponents: methodSignature(method, nameIndex)
params: []
option_hashes: []
throws: []
see: []
jsonMethods.push jsonMethod
if method.params and method.params.length isnt 0
jsonMethod.has_params = true
for param in method.params
jsonParam =
param_name: param.name
formattedType: typeSignature(param.type, nameIndex)
desc: xref(param.desc, nameIndex)
jsonMethod.params.push jsonParam
if method.options and method.options.length isnt 0
for optionHash in method.options
jsonOptions = []
jsonHash =
param_name: S(optionHash.hash).capitalize()
options: jsonOptions
jsonMethod.option_hashes.push jsonHash
for option in optionHash.options
jsonOption =
option_name: option.name
option_type: option.type
desc: xref(option.desc, nameIndex)
jsonOptions.push jsonOption
if method.returns
jsonMethod.returns = xref(method.returns.desc, nameIndex)
if method.throws and method.throws.length isnt 0
jsonMethod.has_throws = true
for thrown in method.throws
jsonThrown =
formattedType: bareTypeSignature(thrown.type, nameIndex)
desc: xref(thrown.desc, nameIndex)
jsonMethod.throws.push jsonThrown
if method.see and method.see.length isnt 0
jsonMethod.has_see = true
for see in method.see
jsonSee =
formattedType: seeAlsoReference(see, nameIndex)
desc: ''
jsonMethod.see.push jsonSee
if klass.data.properties and klass.data.properties.length isnt 0
jsonProperties = []
jsonClass.sections.push(
section_name: 'Properties', methods: jsonProperties)
for property in klass.data.properties
jsonProperty =
desc: ''
method_name: property.name
method_type: 'property'
discussion: xref(property.comment, nameIndex)
formattedComponents: propertySignature(property, nameIndex)
see: []
jsonProperties.push jsonProperty
if property.see and property.see.length isnt 0
jsonProperty.has_see = true
for see in property.see
jsonSee =
formattedType: seeAlsoReference(see, nameIndex)
desc: ''
jsonProperty.see.push jsonSee
if klass.data.constants and klass.data.constants.length isnt 0
jsonConstants = []
jsonClass.sections.push(
section_name: 'Constants', methods: jsonConstants)
for constant in klass.data.constants
jsonConstant =
desc: ''
method_name: constant.name
method_type: 'constant'
discussion: xref(constant.doc.comment, nameIndex)
formattedComponents: constantSignature(constant, nameIndex)
see: []
jsonConstants.push jsonConstant
if property.see and property.see.length isnt 0
jsonConstant.has_see = true
for see in property.see
jsonSee =
formattedType: seeAlsoReference(see, nameIndex)
desc: ''
jsonConstant.see.push jsonSee
json
makeNameIndex = (classes) ->
nameIndex = {}
for klass in classes
className = klass.namespace + '.' + klass.name
nameIndex[className] = "##{className}"
attrs = (klass.data?.instanceMethods or []).concat(
klass.data?.properties or [])
for attr in attrs
nameIndex["#{className}##{attr.name}"] = "##{className}.#{attr.name}"
cattrs = (klass.data?.classMethods or []).concat(
klass.data?.constants or [])
for attr in cattrs
nameIndex["#{className}.#{attr.name}"] = "##{className}.#{attr.name}"
nameIndex
methodSignature = (method, nameIndex) ->
formattedComponents = []
if method.name isnt 'constructor'
returnType = method.doc?.returns?.type or method.returns?.type or 'void'
addTypeSignature returnType, nameIndex, formattedComponents
formattedComponents.push value: ' '
formattedComponents.push value: method.name, emphasized: true
formattedComponents.push value: '('
firstParam = true
for param in method.params or []
if firstParam
firstParam = false
else
formattedComponents.push value: ', '
formattedComponents.push value: param.name
formattedComponents.push value: ')'
formattedComponents
propertySignature = (property, nameIndex) ->
match = /\([^)]*\)/.exec property.signature
if match
propertyType = S(match[0]).unescapeHTML().
replace(/(^\()|(\)$)/g, '').toString()
else
propertyType = null
formattedComponents = []
formattedComponents.push value: property.name, emphasized: true
if propertyType
formattedComponents.push value: ' '
formattedComponents.push value: '('
addTypeSignature propertyType, nameIndex, formattedComponents
formattedComponents.push value: ')'
formattedComponents
typeSignature = (typeString, nameIndex) ->
if typeString.length is 0
null
else
formattedComponents = [{ value: '(' }]
addTypeSignature typeString, nameIndex, formattedComponents
formattedComponents.push value: ')'
formattedComponents
bareTypeSignature = (typeString, nameIndex) ->
if typeString.length is 0
null
else
addTypeSignature typeString, nameIndex, []
addTypeSignature = (typeString, nameIndex, formattedComponents) ->
parts = typeString.split(/([\w\.\
for part in parts
continue if part.length is 0
if nameIndex[part]
formattedComponents.push value: part, href: nameIndex[part]
else
formattedComponents.push value: part
formattedComponents
seeAlsoReference = (see, nameIndex) ->
return null unless see.label
if nameIndex[see.label]
[{value: see.label, href: nameIndex[see.label]}]
else
[{value: see.label, href: see.reference}]
xref = (string, nameIndex) ->
return string unless string
string.replace /(<a [^>]*>)([^>]*)<\/a>/g, (match, tag, innerHtml) ->
newHref = nameIndex[innerHtml.trim()]
return match unless newHref
newTag = tag.replace(/href='[^']+'/, "href='
newTag = newTag.replace(/href="[^"]+"/, "href=\"#{newHref}\"")
"#{newTag}#{innerHtml}</a>"
constantSignature = (constant) ->
[{ value: constant.name }]
siteDoc = (siteDir) ->
tocPath = path.join siteDir, 'templates', 'toc.json'
toc = JSON.parse fs.readFileSync(tocPath, 'utf8')
json = jsonDoc path.join(siteDir, 'yaml'), toc
fs.writeFileSync path.join(siteDir, 'all.json'), JSON.stringify(json)
htmlPath = path.join(siteDir, 'html')
fs.mkdirSync htmlPath unless fs.existsSync htmlPath
docsTemplatePath = path.join siteDir, 'templates', 'docs-template.html'
docsTemplate = fs.readFileSync docsTemplatePath, 'utf8'
docs = mustache.render docsTemplate, json, {}
fs.writeFileSync path.join(htmlPath, 'docs_js_ds.html'), docs
tocTemplatePath = path.join siteDir, 'templates', 'toc-template.html'
tocTemplate = fs.readFileSync tocTemplatePath, 'utf8'
toc = mustache.render tocTemplate, toc, {}
fs.writeFileSync path.join(htmlPath, 'docs_js_ds_toc.html'), toc
module.exports = siteDoc