diff --git a/website/jsdocs/jsdocs.js b/website/jsdocs/jsdocs.js index f81f0e7c0..a4d763693 100644 --- a/website/jsdocs/jsdocs.js +++ b/website/jsdocs/jsdocs.js @@ -19,6 +19,7 @@ var genericTransform = require('./generic-function-visitor'); var genericVisitor = genericTransform.visitorList[0]; var traverseFlat = require('./traverseFlat'); var parseTypehint = require('./TypeExpressionParser').parse; +var util = require('util'); // Don't save object properties source code that is longer than this var MAX_PROPERTY_SOURCE_LENGTH = 1000; @@ -317,6 +318,7 @@ function getObjectData(node, state, source, scopeChain, commentsForFile, linesForFile) { var methods = []; var properties = []; + var classes = []; var superClass = null; node.properties.forEach(function(property) { if (property.type === Syntax.SpreadProperty) { @@ -341,7 +343,8 @@ function getObjectData(node, state, source, scopeChain, scopeChain ); if (expr) { - if (expr.type === Syntax.FunctionDeclaration) { + if (expr.type === Syntax.FunctionDeclaration || + expr.type === Syntax.FunctionExpression) { var functionData = getFunctionData(expr, property, state, source, commentsForFile, linesForFile); @@ -362,16 +365,24 @@ function getObjectData(node, state, source, scopeChain, } var docBlock = getDocBlock(property, commentsForFile, linesForFile); /* CodexVarDef: modifiers, type, name, default, docblock */ - var propertyData = [ - ['static'], - '', + if (property.value.type === Syntax.ClassDeclaration) { + var type = {name: property.value.id.name}; + var classData = getClassData(property.value, state, source, commentsForFile, linesForFile); + classData.ownerProperty = property.key.name; + classes.push(classData); + } else { + var type = {name: property.value.type}; + } + var propertyData = { // Cast to String because this can be a Number // Could also be a String literal (e.g. "key") hence the value - String(property.key.name || property.key.value), + name: String(property.key.name || property.key.value), + type, + docblock: docBlock || '', + source: source.substring.apply(source, property.range), + modifiers: ['static'], propertySource, - docBlock || '', - property.loc.start.line - ]; + }; properties.push(propertyData); break; } @@ -379,6 +390,7 @@ function getObjectData(node, state, source, scopeChain, return { methods: methods, properties: properties, + classes: classes, superClass: superClass }; } @@ -410,6 +422,7 @@ function getClassData(node, state, source, commentsForFile, linesForFile) { } }); var data = { + name: node.id.name, methods: methods }; if (node.superClass && node.superClass.type === Syntax.Identifier) { diff --git a/website/layout/AutodocsLayout.js b/website/layout/AutodocsLayout.js index 604082a1e..fc54c1431 100644 --- a/website/layout/AutodocsLayout.js +++ b/website/layout/AutodocsLayout.js @@ -20,53 +20,52 @@ var slugify = require('slugify'); var styleReferencePattern = /^[^.]+\.propTypes\.style$/; -var ComponentDoc = React.createClass({ - renderType: function(type) { - if (type.name === 'enum') { - if (typeof type.value === 'string') { - return type.value; - } - return 'enum(' + type.value.map((v => v.value)).join(', ') + ')'; - } - - if (type.name === 'shape') { - return '{' + Object.keys(type.value).map((key => key + ': ' + this.renderType(type.value[key]))).join(', ') + '}'; - } - - if (type.name == 'union') { - return type.value.map(this.renderType).join(', '); - } - - if (type.name === 'arrayOf') { - return '[' + this.renderType(type.value) + ']'; - } - - if (type.name === 'instanceOf') { +function renderType(type) { + if (type.name === 'enum') { + if (typeof type.value === 'string') { return type.value; } + return 'enum(' + type.value.map((v) => v.value).join(', ') + ')'; + } - if (type.name === 'custom') { - if (styleReferencePattern.test(type.raw)) { - var name = type.raw.substring(0, type.raw.indexOf('.')); - return {name}#style - } - if (type.raw === 'EdgeInsetsPropType') { - return '{top: number, left: number, bottom: number, right: number}'; - } - return type.raw; + if (type.name === 'shape') { + return '{' + Object.keys(type.value).map((key => key + ': ' + renderType(type.value[key]))).join(', ') + '}'; + } + + if (type.name == 'union') { + return type.value.map(renderType).join(', '); + } + + if (type.name === 'arrayOf') { + return '[' + renderType(type.value) + ']'; + } + + if (type.name === 'instanceOf') { + return type.value; + } + + if (type.name === 'custom') { + if (styleReferencePattern.test(type.raw)) { + var name = type.raw.substring(0, type.raw.indexOf('.')); + return {name}#style } - - if (type.name === 'stylesheet') { - return 'style'; + if (type.raw === 'EdgeInsetsPropType') { + return '{top: number, left: number, bottom: number, right: number}'; } + return type.raw; + } - if (type.name === 'func') { - return 'function'; - } + if (type.name === 'stylesheet') { + return 'style'; + } - return type.name; - }, + if (type.name === 'func') { + return 'function'; + } + return type.name; +} +var ComponentDoc = React.createClass({ renderProp: function(name, prop) { return (
@@ -77,7 +76,7 @@ var ComponentDoc = React.createClass({ {name} {' '} {prop.type && - {this.renderType(prop.type)} + {renderType(prop.type)} } {prop.type && prop.type.name === 'stylesheet' && @@ -128,7 +127,7 @@ var ComponentDoc = React.createClass({ {name} {' '} {style.props[name].type && - {this.renderType(style.props[name].type)} + {renderType(style.props[name].type)} }
@@ -190,7 +189,6 @@ var ComponentDoc = React.createClass({ {content.description} - +
+ {property.name} + {property.type && + + {': ' + renderType(property.type)} + + } +
+ {property.docblock && + {this.removeCommentsFromDocblock(property.docblock)} + } + + ); + }, + + renderProperties: function(properties) { + if (!properties || !properties.length) { + return null; + } + return ( + + Properties +
+ {properties.filter((property) => { + return property.name[0] !== '_'; + }).map(this.renderProperty)} +
+
+ ); + }, + + renderClasses: function(classes) { + if (!classes || !classes.length) { + return null; + } + return ( + +
+ {classes.filter((cls) => { + return cls.name[0] !== '_' && cls.ownerProperty[0] !== '_'; + }).map((cls) => { + return ( + +
+ class {cls.name} +
+
    + {this.renderMethods(cls.methods)} + {this.renderProperties(cls.properties)} +
+
+ ); + })} +
+
+ ); + }, + render: function() { var content = this.props.content; if (!content.methods) { @@ -294,6 +352,8 @@ var APIDoc = React.createClass({ {this.removeCommentsFromDocblock(content.docblock)} {this.renderMethods(content.methods)} + {this.renderProperties(content.properties)} + {this.renderClasses(content.classes)} ); } @@ -371,7 +431,7 @@ var Autodocs = React.createClass({ var docs = JSON.parse(this.props.children); var content = docs.type === 'component' || docs.type === 'style' ? : - ; + ; return ( diff --git a/website/server/extractDocs.js b/website/server/extractDocs.js index 0e609a255..c52cf3b7b 100644 --- a/website/server/extractDocs.js +++ b/website/server/extractDocs.js @@ -134,7 +134,7 @@ function renderAPI(type) { try { json = jsDocs(fs.readFileSync(filepath).toString()); } catch(e) { - console.error('Cannot parse file', filepath); + console.error('Cannot parse file', filepath, e); json = {}; } return componentsToMarkdown(type, json, filepath, n++); @@ -187,6 +187,7 @@ var components = [ var apis = [ '../Libraries/ActionSheetIOS/ActionSheetIOS.js', '../Libraries/Utilities/AlertIOS.js', + '../Libraries/Animated/Animated.js', '../Libraries/AppRegistry/AppRegistry.js', '../Libraries/AppStateIOS/AppStateIOS.ios.js', '../Libraries/Storage/AsyncStorage.ios.js',