react-native/website/server/extractDocs.js
Martin Konicek 42eb5464fd Release React Native for Android
This is an early release and there are several things that are known
not to work if you're porting your iOS app to Android.

See the Known Issues guide on the website.

We will work with the community to reach platform parity with iOS.
2015-09-14 18:13:39 +01:00

276 lines
8.3 KiB
JavaScript

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
var docgen = require('react-docgen');
var docgenHelpers = require('./docgenHelpers');
var fs = require('fs');
var path = require('path');
var slugify = require('../core/slugify');
var jsDocs = require('../jsdocs/jsdocs.js');
var ANDROID_SUFFIX = 'android';
var CROSS_SUFFIX = 'cross';
var IOS_SUFFIX = 'ios';
function endsWith(str, suffix) {
return str.indexOf(suffix, str.length - suffix.length) !== -1;
}
function getNameFromPath(filepath) {
var ext = null;
while (ext = path.extname(filepath)) {
filepath = path.basename(filepath, ext);
}
if (filepath === 'LayoutPropTypes') {
return 'Flexbox';
} else if (filepath === 'TransformPropTypes') {
return 'Transforms';
} else if (filepath === 'TabBarItemIOS') {
return 'TabBarIOS.Item';
}
return filepath;
}
function getPlatformFromPath(filepath) {
var ext = null;
while (ext = path.extname(filepath)) {
filepath = path.basename(filepath, ext);
}
if (endsWith(filepath, 'Android')) {
return ANDROID_SUFFIX;
} else if (endsWith(filepath, 'IOS')) {
return IOS_SUFFIX;
}
return CROSS_SUFFIX;
}
function getExample(componentName, componentPlatform) {
var path = '../Examples/UIExplorer/' + componentName + 'Example.js';
if (!fs.existsSync(path)) {
path = '../Examples/UIExplorer/' + componentName + 'Example.'+ componentPlatform +'.js';
if (!fs.existsSync(path)) {
return;
}
}
return {
path: path.replace(/^\.\.\//, ''),
content: fs.readFileSync(path).toString(),
};
}
// Determines whether a component should have a link to a runnable example
function isRunnable(componentName) {
if (componentName === 'AlertIOS') {
return true;
}
return false;
}
// Hide a component from the sidebar by making it return false from
// this function
function shouldDisplayInSidebar(componentName) {
if (componentName === 'Transforms') {
return false;
}
return true;
}
function getNextComponent(i) {
var next;
var filepath = all[i];
if (all[i + 1]) {
var nextComponentName = getNameFromPath(all[i + 1]);
if (shouldDisplayInSidebar(nextComponentName)) {
return slugify(nextComponentName);
} else {
return getNextComponent(i + 1);
}
} else {
return 'network';
}
}
function componentsToMarkdown(type, json, filepath, i, styles) {
var componentName = getNameFromPath(filepath);
var componentPlatform = getPlatformFromPath(filepath);
var docFilePath = '../docs/' + componentName + '.md';
if (fs.existsSync(docFilePath)) {
json.fullDescription = fs.readFileSync(docFilePath).toString();
}
json.type = type;
json.filepath = filepath.replace(/^\.\.\//, '');
json.componentName = componentName;
json.componentPlatform = componentPlatform;
if (styles) {
json.styles = styles;
}
json.example = getExample(componentName, componentPlatform);
// Put Flexbox into the Polyfills category
var category = (type === 'style' ? 'Polyfills' : type + 's');
var next = getNextComponent(i);
var res = [
'---',
'id: ' + slugify(componentName),
'title: ' + componentName,
'layout: autodocs',
'category: ' + category,
'permalink: docs/' + slugify(componentName) + '.html',
'platform: ' + componentPlatform,
'next: ' + next,
'sidebar: ' + shouldDisplayInSidebar(componentName),
'runnable:' + isRunnable(componentName),
'---',
JSON.stringify(json, null, 2),
].filter(function(line) { return line; }).join('\n');
return res;
}
var n;
function renderComponent(filepath) {
var json = docgen.parse(
fs.readFileSync(filepath),
docgenHelpers.findExportedOrFirst,
docgen.defaultHandlers.concat(docgenHelpers.stylePropTypeHandler)
);
return componentsToMarkdown('component', json, filepath, n++, styleDocs);
}
function renderAPI(type) {
return function(filepath) {
var json;
try {
json = jsDocs(fs.readFileSync(filepath).toString());
} catch(e) {
console.error('Cannot parse file', filepath, e);
json = {};
}
return componentsToMarkdown(type, json, filepath, n++);
};
}
function renderStyle(filepath) {
var json = docgen.parse(
fs.readFileSync(filepath),
docgenHelpers.findExportedObject,
[docgen.handlers.propTypeHandler]
);
// Remove deprecated transform props from docs
if (filepath === "../Libraries/StyleSheet/TransformPropTypes.js") {
['rotation', 'scaleX', 'scaleY', 'translateX', 'translateY'].forEach(function(key) {
delete json['props'][key];
});
}
return componentsToMarkdown('style', json, filepath, n++);
}
var components = [
'../Libraries/Components/ActivityIndicatorIOS/ActivityIndicatorIOS.ios.js',
'../Libraries/Components/DatePicker/DatePickerIOS.ios.js',
'../Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js',
'../Libraries/Image/Image.ios.js',
'../Libraries/CustomComponents/ListView/ListView.js',
'../Libraries/Components/MapView/MapView.js',
'../Libraries/CustomComponents/Navigator/Navigator.js',
'../Libraries/Modal/Modal.js',
'../Libraries/Components/Navigation/NavigatorIOS.ios.js',
'../Libraries/Picker/PickerIOS.ios.js',
'../Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js',
'../Libraries/Components/ProgressViewIOS/ProgressViewIOS.ios.js',
'../Libraries/Components/ScrollView/ScrollView.js',
'../Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.ios.js',
'../Libraries/Components/SliderIOS/SliderIOS.ios.js',
'../Libraries/Components/SwitchAndroid/SwitchAndroid.android.js',
'../Libraries/Components/SwitchIOS/SwitchIOS.ios.js',
'../Libraries/Components/TabBarIOS/TabBarIOS.ios.js',
'../Libraries/Components/TabBarIOS/TabBarItemIOS.ios.js',
'../Libraries/Text/Text.js',
'../Libraries/Components/TextInput/TextInput.js',
'../Libraries/Components/ToolbarAndroid/ToolbarAndroid.android.js',
'../Libraries/Components/Touchable/TouchableHighlight.js',
'../Libraries/Components/Touchable/TouchableNativeFeedback.android.js',
'../Libraries/Components/Touchable/TouchableOpacity.js',
'../Libraries/Components/Touchable/TouchableWithoutFeedback.js',
'../Libraries/Components/View/View.js',
'../Libraries/Components/WebView/WebView.ios.js',
];
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',
'../Libraries/Utilities/BackAndroid.android.js',
'../Libraries/CameraRoll/CameraRoll.js',
'../Libraries/Interaction/InteractionManager.js',
'../Libraries/LayoutAnimation/LayoutAnimation.js',
'../Libraries/LinkingIOS/LinkingIOS.js',
'../Libraries/Network/NetInfo.js',
'../Libraries/vendor/react/browser/eventPlugins/PanResponder.js',
'../Libraries/Utilities/PixelRatio.js',
'../Libraries/PushNotificationIOS/PushNotificationIOS.js',
'../Libraries/Components/StatusBar/StatusBarIOS.ios.js',
'../Libraries/StyleSheet/StyleSheet.js',
'../Libraries/Components/ToastAndroid/ToastAndroid.android.js',
'../Libraries/Vibration/VibrationIOS.ios.js',
];
var styles = [
'../Libraries/StyleSheet/LayoutPropTypes.js',
'../Libraries/StyleSheet/TransformPropTypes.js',
'../Libraries/Components/View/ViewStylePropTypes.js',
'../Libraries/Text/TextStylePropTypes.js',
'../Libraries/Image/ImageStylePropTypes.js',
];
var polyfills = [
'../Libraries/GeoLocation/Geolocation.js',
];
var all = components
.concat(apis)
.concat(styles.slice(0, 2))
.concat(polyfills);
var styleDocs = styles.slice(2).reduce(function(docs, filepath) {
docs[path.basename(filepath).replace(path.extname(filepath), '')] =
docgen.parse(
fs.readFileSync(filepath),
docgenHelpers.findExportedObject,
[docgen.handlers.propTypeHandler, docgen.handlers.propTypeCompositionHandler]
);
return docs;
}, {});
module.exports = function() {
n = 0;
return [].concat(
components.map(renderComponent),
apis.map(renderAPI('api')),
styles.slice(0, 2).map(renderStyle),
polyfills.map(renderAPI('Polyfill'))
);
};