mirror of
https://github.com/status-im/react-native.git
synced 2025-02-05 06:04:15 +00:00
Add logic to show style props in docs
This commit is contained in:
parent
e811181034
commit
d5f670d19c
@ -17,6 +17,7 @@ var React = require('React');
|
|||||||
var Site = require('Site');
|
var Site = require('Site');
|
||||||
var slugify = require('slugify');
|
var slugify = require('slugify');
|
||||||
|
|
||||||
|
var styleReferencePattern = /^[^.]+\.propTypes\.style$/;
|
||||||
|
|
||||||
var ComponentDoc = React.createClass({
|
var ComponentDoc = React.createClass({
|
||||||
renderType: function(type) {
|
renderType: function(type) {
|
||||||
@ -40,12 +41,20 @@ var ComponentDoc = React.createClass({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type.name === 'custom') {
|
if (type.name === 'custom') {
|
||||||
|
if (styleReferencePattern.test(type.raw)) {
|
||||||
|
var name = type.raw.substring(0, type.raw.indexOf('.'));
|
||||||
|
return <a href={slugify(name) + '.html#style'}>{name}#style</a>
|
||||||
|
}
|
||||||
if (type.raw === 'EdgeInsetsPropType') {
|
if (type.raw === 'EdgeInsetsPropType') {
|
||||||
return '{top: number, left: number, bottom: number, right: number}';
|
return '{top: number, left: number, bottom: number, right: number}';
|
||||||
}
|
}
|
||||||
return type.raw;
|
return type.raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type.name === 'stylesheet') {
|
||||||
|
return 'style';
|
||||||
|
}
|
||||||
|
|
||||||
if (type.name === 'func') {
|
if (type.name === 'func') {
|
||||||
return 'function';
|
return 'function';
|
||||||
}
|
}
|
||||||
@ -63,6 +72,8 @@ var ComponentDoc = React.createClass({
|
|||||||
{this.renderType(prop.type)}
|
{this.renderType(prop.type)}
|
||||||
</span>}
|
</span>}
|
||||||
</Header>
|
</Header>
|
||||||
|
{prop.type && prop.type.name === 'stylesheet' &&
|
||||||
|
this.renderStylesheetProps(prop.type.value)}
|
||||||
{prop.description && <Marked>{prop.description}</Marked>}
|
{prop.description && <Marked>{prop.description}</Marked>}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -78,6 +89,41 @@ var ComponentDoc = React.createClass({
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
renderStylesheetProps: function(stylesheetName) {
|
||||||
|
var style = this.props.content.styles[stylesheetName];
|
||||||
|
return (
|
||||||
|
<div className="compactProps">
|
||||||
|
{(style.composes || []).map((name) => {
|
||||||
|
var link;
|
||||||
|
if (name !== 'LayoutPropTypes') {
|
||||||
|
name = name.replace('StylePropTypes', '');
|
||||||
|
link =
|
||||||
|
<a href={slugify(name) + '.html#style'}>{name}#style...</a>;
|
||||||
|
} else {
|
||||||
|
link =
|
||||||
|
<a href={slugify(name) + '.html#proptypes'}>{name}...</a>;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="prop" key={name}>
|
||||||
|
<h6 className="propTitle">{link}</h6>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{Object.keys(style.props).sort().map((name) =>
|
||||||
|
<div className="prop" key={name}>
|
||||||
|
<h6 className="propTitle">
|
||||||
|
{name}
|
||||||
|
{' '}
|
||||||
|
{style.props[name].type && <span className="propType">
|
||||||
|
{this.renderType(style.props[name].type)}
|
||||||
|
</span>}
|
||||||
|
</h6>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
renderProps: function(props, composes) {
|
renderProps: function(props, composes) {
|
||||||
return (
|
return (
|
||||||
<div className="props">
|
<div className="props">
|
||||||
@ -197,7 +243,11 @@ var APIDoc = React.createClass({
|
|||||||
var Autodocs = React.createClass({
|
var Autodocs = React.createClass({
|
||||||
render: function() {
|
render: function() {
|
||||||
var metadata = this.props.metadata;
|
var metadata = this.props.metadata;
|
||||||
var content = JSON.parse(this.props.children);
|
var docs = JSON.parse(this.props.children);
|
||||||
|
var content = docs.type === 'component' || docs.type === 'style' ?
|
||||||
|
<ComponentDoc content={docs} /> :
|
||||||
|
<APIDoc content={docs} />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Site section="docs">
|
<Site section="docs">
|
||||||
<section className="content wrap documentationContent">
|
<section className="content wrap documentationContent">
|
||||||
@ -205,11 +255,9 @@ var Autodocs = React.createClass({
|
|||||||
<div className="inner-content">
|
<div className="inner-content">
|
||||||
<a id="content" />
|
<a id="content" />
|
||||||
<h1>{metadata.title}</h1>
|
<h1>{metadata.title}</h1>
|
||||||
{content.type === 'component' ?
|
{content}
|
||||||
<ComponentDoc content={content} /> :
|
|
||||||
<APIDoc content={content} />}
|
|
||||||
<Marked>
|
<Marked>
|
||||||
{content.fullDescription}
|
{docs.fullDescription}
|
||||||
</Marked>
|
</Marked>
|
||||||
<div className="docs-prevnext">
|
<div className="docs-prevnext">
|
||||||
{metadata.previous && <a className="docs-prev" href={metadata.previous + '.html#content'}>← Prev</a>}
|
{metadata.previous && <a className="docs-prev" href={metadata.previous + '.html#content'}>← Prev</a>}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
"mkdirp": "*",
|
"mkdirp": "*",
|
||||||
"optimist": "0.6.0",
|
"optimist": "0.6.0",
|
||||||
"react": "~0.12.0",
|
"react": "~0.12.0",
|
||||||
"react-docgen": "^1.0.0",
|
"react-docgen": "^1.1.0",
|
||||||
"react-page-middleware": "git://github.com/facebook/react-page-middleware.git",
|
"react-page-middleware": "git://github.com/facebook/react-page-middleware.git",
|
||||||
"request": "*"
|
"request": "*"
|
||||||
}
|
}
|
||||||
|
67
website/server/docgenHelpers.js
Normal file
67
website/server/docgenHelpers.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
"use strict";
|
||||||
|
var b = require('react-docgen/node_modules/recast').types.builders;
|
||||||
|
var docgen = require('react-docgen');
|
||||||
|
|
||||||
|
function stylePropTypeHandler(documentation, path) {
|
||||||
|
var propTypesPath = docgen.utils.getPropertyValuePath(path, 'propTypes');
|
||||||
|
if (!propTypesPath) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
propTypesPath = docgen.utils.resolveToValue(propTypesPath);
|
||||||
|
if (!propTypesPath || propTypesPath.node.type !== 'ObjectExpression') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the there is a style prop
|
||||||
|
propTypesPath.get('properties').each(function(propertyPath) {
|
||||||
|
if (propertyPath.node.type !== 'Property' ||
|
||||||
|
docgen.utils.getPropertyName(propertyPath) !== 'style') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var valuePath = docgen.utils.resolveToValue(propertyPath.get('value'));
|
||||||
|
// If it's a call to StyleSheetPropType, do stuff
|
||||||
|
if (valuePath.node.type !== 'CallExpression' ||
|
||||||
|
valuePath.node.callee.name !== 'StyleSheetPropType') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Get type of style sheet
|
||||||
|
var styleSheetModule = docgen.utils.resolveToModule(
|
||||||
|
valuePath.get('arguments', 0)
|
||||||
|
);
|
||||||
|
if (styleSheetModule) {
|
||||||
|
var propDescriptor = documentation.getPropDescriptor('style');
|
||||||
|
propDescriptor.type = {name: 'stylesheet', value: styleSheetModule};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function findExportedOrFirst(node, recast) {
|
||||||
|
return docgen.resolver.findExportedReactCreateClassCall(node, recast) ||
|
||||||
|
docgen.resolver.findAllReactCreateClassCalls(node, recast)[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
function findExportedObject(ast, recast) {
|
||||||
|
var objPath;
|
||||||
|
recast.visit(ast, {
|
||||||
|
visitAssignmentExpression: function(path) {
|
||||||
|
if (!objPath && docgen.utils.isExportsOrModuleAssignment(path)) {
|
||||||
|
objPath = docgen.utils.resolveToValue(path.get('right'));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (objPath) {
|
||||||
|
var b = recast.types.builders;
|
||||||
|
// This is a bit hacky, but easier than replicating the default propType
|
||||||
|
// handler. All this does is convert `{...}` to `{propTypes: {...}}`.
|
||||||
|
objPath.replace(b.objectExpression([
|
||||||
|
b.property('init', b.literal('propTypes'), objPath.node)
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
return objPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.stylePropTypeHandler = stylePropTypeHandler;
|
||||||
|
exports.findExportedOrFirst = findExportedOrFirst;
|
||||||
|
exports.findExportedObject = findExportedObject;
|
@ -7,7 +7,8 @@
|
|||||||
* of patent rights can be found in the PATENTS file in the same directory.
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var docs = require('react-docgen');
|
var docgen = require('react-docgen');
|
||||||
|
var docgenHelpers = require('./docgenHelpers');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var slugify = require('../core/slugify');
|
var slugify = require('../core/slugify');
|
||||||
@ -21,7 +22,7 @@ function getNameFromPath(filepath) {
|
|||||||
return filepath;
|
return filepath;
|
||||||
}
|
}
|
||||||
|
|
||||||
function componentsToMarkdown(type, json, filepath, i) {
|
function componentsToMarkdown(type, json, filepath, i, styles) {
|
||||||
var componentName = getNameFromPath(filepath);
|
var componentName = getNameFromPath(filepath);
|
||||||
|
|
||||||
var docFilePath = '../docs/' + componentName + '.md';
|
var docFilePath = '../docs/' + componentName + '.md';
|
||||||
@ -29,6 +30,9 @@ function componentsToMarkdown(type, json, filepath, i) {
|
|||||||
json.fullDescription = fs.readFileSync(docFilePath).toString();
|
json.fullDescription = fs.readFileSync(docFilePath).toString();
|
||||||
}
|
}
|
||||||
json.type = type;
|
json.type = type;
|
||||||
|
if (styles) {
|
||||||
|
json.styles = styles;
|
||||||
|
}
|
||||||
|
|
||||||
var res = [
|
var res = [
|
||||||
'---',
|
'---',
|
||||||
@ -84,20 +88,34 @@ var apis = [
|
|||||||
'../Libraries/Vibration/VibrationIOS.ios.js',
|
'../Libraries/Vibration/VibrationIOS.ios.js',
|
||||||
];
|
];
|
||||||
|
|
||||||
var all = components.concat(apis);
|
var styles = [
|
||||||
|
'../Libraries/StyleSheet/LayoutPropTypes.js',
|
||||||
|
'../Libraries/Components/View/ViewStylePropTypes.js',
|
||||||
|
'../Libraries/Text/TextStylePropTypes.js',
|
||||||
|
'../Libraries/Image/ImageStylePropTypes.js',
|
||||||
|
];
|
||||||
|
|
||||||
|
var all = components.concat(apis).concat(styles.slice(0, 1));
|
||||||
|
var styleDocs = styles.slice(1).reduce(function(docs, filepath) {
|
||||||
|
docs[path.basename(filepath).replace(path.extname(filepath), '')] =
|
||||||
|
docgen.parse(
|
||||||
|
fs.readFileSync(filepath),
|
||||||
|
docgenHelpers.findExportedObject,
|
||||||
|
[docgen.handlers.propTypeHandler]
|
||||||
|
);
|
||||||
|
return docs;
|
||||||
|
}, {});
|
||||||
|
|
||||||
module.exports = function() {
|
module.exports = function() {
|
||||||
var i = 0;
|
var i = 0;
|
||||||
return [].concat(
|
return [].concat(
|
||||||
components.map(function(filepath) {
|
components.map(function(filepath) {
|
||||||
var json = docs.parse(
|
var json = docgen.parse(
|
||||||
fs.readFileSync(filepath),
|
fs.readFileSync(filepath),
|
||||||
function(node, recast) {
|
docgenHelpers.findExportedOrFirst,
|
||||||
return docs.resolver.findExportedReactCreateClassCall(node, recast) ||
|
docgen.defaultHandlers.concat(docgenHelpers.stylePropTypeHandler)
|
||||||
docs.resolver.findAllReactCreateClassCalls(node, recast)[0];
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
return componentsToMarkdown('component', json, filepath, i++);
|
return componentsToMarkdown('component', json, filepath, i++, styleDocs);
|
||||||
}),
|
}),
|
||||||
apis.map(function(filepath) {
|
apis.map(function(filepath) {
|
||||||
try {
|
try {
|
||||||
@ -107,6 +125,14 @@ module.exports = function() {
|
|||||||
var json = {};
|
var json = {};
|
||||||
}
|
}
|
||||||
return componentsToMarkdown('api', json, filepath, i++);
|
return componentsToMarkdown('api', json, filepath, i++);
|
||||||
|
}),
|
||||||
|
styles.slice(0, 1).map(function(filepath) {
|
||||||
|
var json = docgen.parse(
|
||||||
|
fs.readFileSync(filepath),
|
||||||
|
docgenHelpers.findExportedObject,
|
||||||
|
[docgen.handlers.propTypeHandler]
|
||||||
|
);
|
||||||
|
return componentsToMarkdown('style', json, filepath, i++);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -901,7 +901,13 @@ div[data-twttr-id] iframe {
|
|||||||
background-color: hsl(198, 100%, 96%);
|
background-color: hsl(198, 100%, 96%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.prop:nth-child(2n) {
|
.compactProps {
|
||||||
|
border-left: 2px solid hsl(198, 100%, 94%);
|
||||||
|
margin-left: 20px;
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.props > .prop:nth-child(2n) {
|
||||||
background-color: hsl(198, 100%, 94%);
|
background-color: hsl(198, 100%, 94%);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -910,15 +916,30 @@ div[data-twttr-id] iframe {
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.compactProps .propTitle {
|
||||||
|
font-size: 14px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.prop {
|
.prop {
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.compactProps .prop {
|
||||||
|
padding: 3px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.propType {
|
.propType {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.compactProps .propType {
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#content {
|
#content {
|
||||||
display: none;
|
display: none;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user