Move Documentation to the @0xproject/react-docs
package
This commit is contained in:
5
packages/react-docs/.npmignore
Normal file
5
packages/react-docs/.npmignore
Normal file
@@ -0,0 +1,5 @@
|
||||
.*
|
||||
yarn-error.log
|
||||
/src/
|
||||
/scripts/
|
||||
tsconfig.json
|
3
packages/react-docs/CHANGELOG.md
Normal file
3
packages/react-docs/CHANGELOG.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# CHANGELOG
|
||||
|
||||
## vX.X.X - _TBD, 2018_
|
47
packages/react-docs/README.md
Normal file
47
packages/react-docs/README.md
Normal file
@@ -0,0 +1,47 @@
|
||||
## @0xproject/react-docs
|
||||
|
||||
A full-page React component for rendering beautiful documentation generated with [TypeDoc](http://typedoc.org/) or [Doxity](https://github.com/0xproject/doxity).
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
yarn add @0xproject/react-docs
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly encourage that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install Dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
```bash
|
||||
yarn config set workspaces-experimental true
|
||||
```
|
||||
|
||||
Then install dependencies
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Build
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
```bash
|
||||
yarn test
|
||||
```
|
37
packages/react-docs/package.json
Normal file
37
packages/react-docs/package.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "@0xproject/react-docs",
|
||||
"version": "0.0.1",
|
||||
"description": "React documentation component for rendering TypeDoc & Doxity generated JSON",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"scripts": {
|
||||
"lint": "tslint --project . 'src/ts/**/*.ts' 'src/ts/**/*.tsx'",
|
||||
"build": "tsc",
|
||||
"build:watch": "tsc -w",
|
||||
"clean": "shx rm -rf lib"
|
||||
},
|
||||
"author": "Fabio Berger",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@0xproject/tslint-config": "^0.4.9",
|
||||
"@types/lodash": "^4.14.86",
|
||||
"@types/node": "^8.0.53",
|
||||
"@types/material-ui": "0.18.0",
|
||||
"@types/react": "^15.0.15",
|
||||
"@types/react-dom": "^0.14.23",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "^5.9.1",
|
||||
"typescript": "2.7.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/react-shared": "^0.0.1",
|
||||
"basscss": "^8.0.3",
|
||||
"compare-versions": "^3.0.1",
|
||||
"react-tooltip": "^3.2.7",
|
||||
"material-ui": "^0.17.1",
|
||||
"react": "15.6.1",
|
||||
"react-dom": "15.6.1",
|
||||
"lodash": "^4.17.4",
|
||||
"react-tap-event-plugin": "^2.0.1"
|
||||
}
|
||||
}
|
5
packages/react-docs/scripts/postpublish.js
vendored
Normal file
5
packages/react-docs/scripts/postpublish.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
const postpublish_utils = require('../../../scripts/postpublish_utils');
|
||||
const packageJSON = require('../package.json');
|
||||
|
||||
const subPackageName = packageJSON.name;
|
||||
postpublish_utils.standardPostPublishAsync(subPackageName);
|
56
packages/react-docs/src/ts/components/badge.tsx
Normal file
56
packages/react-docs/src/ts/components/badge.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import { Styles } from '@0xproject/react-shared';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
const styles: Styles = {
|
||||
badge: {
|
||||
width: 50,
|
||||
fontSize: 11,
|
||||
height: 10,
|
||||
borderRadius: 5,
|
||||
lineHeight: 0.9,
|
||||
fontFamily: 'Roboto Mono',
|
||||
marginLeft: 3,
|
||||
marginRight: 3,
|
||||
},
|
||||
};
|
||||
|
||||
export interface BadgeProps {
|
||||
title: string;
|
||||
backgroundColor: string;
|
||||
}
|
||||
|
||||
export interface BadgeState {
|
||||
isHovering: boolean;
|
||||
}
|
||||
|
||||
export class Badge extends React.Component<BadgeProps, BadgeState> {
|
||||
constructor(props: BadgeProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isHovering: false,
|
||||
};
|
||||
}
|
||||
public render() {
|
||||
const badgeStyle = {
|
||||
...styles.badge,
|
||||
backgroundColor: this.props.backgroundColor,
|
||||
opacity: this.state.isHovering ? 0.7 : 1,
|
||||
};
|
||||
return (
|
||||
<div
|
||||
className="p1 center"
|
||||
style={badgeStyle}
|
||||
onMouseOver={this._setHoverState.bind(this, true)}
|
||||
onMouseOut={this._setHoverState.bind(this, false)}
|
||||
>
|
||||
{this.props.title}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
private _setHoverState(isHovering: boolean) {
|
||||
this.setState({
|
||||
isHovering,
|
||||
});
|
||||
}
|
||||
}
|
23
packages/react-docs/src/ts/components/comment.tsx
Normal file
23
packages/react-docs/src/ts/components/comment.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { MarkdownCodeBlock } from '@0xproject/react-shared';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
import * as ReactMarkdown from 'react-markdown';
|
||||
|
||||
export interface CommentProps {
|
||||
comment: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
className: '',
|
||||
};
|
||||
|
||||
export const Comment: React.SFC<CommentProps> = (props: CommentProps) => {
|
||||
return (
|
||||
<div className={`${props.className} comment`}>
|
||||
<ReactMarkdown source={props.comment} renderers={{ code: MarkdownCodeBlock }} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Comment.defaultProps = defaultProps;
|
33
packages/react-docs/src/ts/components/custom_enum.tsx
Normal file
33
packages/react-docs/src/ts/components/custom_enum.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { CustomType } from '../types';
|
||||
import { utils } from '../utils/utils';
|
||||
|
||||
const STRING_ENUM_CODE_PREFIX = ' strEnum(';
|
||||
|
||||
export interface CustomEnumProps {
|
||||
type: CustomType;
|
||||
}
|
||||
|
||||
// This component renders custom string enums that was a work-around for versions of
|
||||
// TypeScript <2.4.0 that did not support them natively. We keep it around to support
|
||||
// older versions of 0x.js <0.9.0
|
||||
export function CustomEnum(props: CustomEnumProps) {
|
||||
const type = props.type;
|
||||
if (!_.startsWith(type.defaultValue, STRING_ENUM_CODE_PREFIX)) {
|
||||
utils.consoleLog('We do not yet support `Variable` types that are not strEnums');
|
||||
return null;
|
||||
}
|
||||
// Remove the prefix and postfix, leaving only the strEnum values without quotes.
|
||||
const enumValues = type.defaultValue.slice(10, -3).replace(/'/g, '');
|
||||
return (
|
||||
<span>
|
||||
{`{`}
|
||||
{'\t'}
|
||||
{enumValues}
|
||||
<br />
|
||||
{`}`}
|
||||
</span>
|
||||
);
|
||||
}
|
120
packages/react-docs/src/ts/components/docs_info.ts
Normal file
120
packages/react-docs/src/ts/components/docs_info.ts
Normal file
@@ -0,0 +1,120 @@
|
||||
import { MenuSubsectionsBySection } from '@0xproject/react-shared';
|
||||
import compareVersions = require('compare-versions');
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {
|
||||
ContractsByVersionByNetworkId,
|
||||
DocAgnosticFormat,
|
||||
DocsInfoConfig,
|
||||
DocsMenu,
|
||||
DoxityDocObj,
|
||||
SectionsMap,
|
||||
SupportedDocJson,
|
||||
TypeDocNode,
|
||||
} from '../types';
|
||||
import { doxityUtils } from '../utils/doxity_utils';
|
||||
import { typeDocUtils } from '../utils/typedoc_utils';
|
||||
|
||||
export class DocsInfo {
|
||||
public id: string;
|
||||
public type: SupportedDocJson;
|
||||
public displayName: string;
|
||||
public packageUrl: string;
|
||||
public menu: DocsMenu;
|
||||
public sections: SectionsMap;
|
||||
public sectionNameToMarkdown: { [sectionName: string]: string };
|
||||
public contractsByVersionByNetworkId?: ContractsByVersionByNetworkId;
|
||||
private _docsInfo: DocsInfoConfig;
|
||||
constructor(config: DocsInfoConfig) {
|
||||
this.id = config.id;
|
||||
this.type = config.type;
|
||||
this.displayName = config.displayName;
|
||||
this.packageUrl = config.packageUrl;
|
||||
this.sections = config.sections;
|
||||
this.sectionNameToMarkdown = config.sectionNameToMarkdown;
|
||||
this.contractsByVersionByNetworkId = config.contractsByVersionByNetworkId;
|
||||
this._docsInfo = config;
|
||||
}
|
||||
public isPublicType(typeName: string): boolean {
|
||||
if (_.isUndefined(this._docsInfo.publicTypes)) {
|
||||
return false;
|
||||
}
|
||||
const isPublic = _.includes(this._docsInfo.publicTypes, typeName);
|
||||
return isPublic;
|
||||
}
|
||||
public getModulePathsIfExists(sectionName: string): string[] {
|
||||
const modulePathsIfExists = this._docsInfo.sectionNameToModulePath[sectionName];
|
||||
return modulePathsIfExists;
|
||||
}
|
||||
public getMenu(selectedVersion?: string): { [section: string]: string[] } {
|
||||
if (_.isUndefined(selectedVersion) || _.isUndefined(this._docsInfo.menuSubsectionToVersionWhenIntroduced)) {
|
||||
return this._docsInfo.menu;
|
||||
}
|
||||
|
||||
const finalMenu = _.cloneDeep(this._docsInfo.menu);
|
||||
if (_.isUndefined(finalMenu.contracts)) {
|
||||
return finalMenu;
|
||||
}
|
||||
|
||||
// TODO: refactor to include more sections then simply the `contracts` section
|
||||
finalMenu.contracts = _.filter(finalMenu.contracts, (contractName: string) => {
|
||||
const versionIntroducedIfExists = this._docsInfo.menuSubsectionToVersionWhenIntroduced[contractName];
|
||||
if (!_.isUndefined(versionIntroducedIfExists)) {
|
||||
const existsInSelectedVersion = compareVersions(selectedVersion, versionIntroducedIfExists) >= 0;
|
||||
return existsInSelectedVersion;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return finalMenu;
|
||||
}
|
||||
public getMenuSubsectionsBySection(docAgnosticFormat?: DocAgnosticFormat): MenuSubsectionsBySection {
|
||||
const menuSubsectionsBySection = {} as MenuSubsectionsBySection;
|
||||
if (_.isUndefined(docAgnosticFormat)) {
|
||||
return menuSubsectionsBySection;
|
||||
}
|
||||
|
||||
const docSections = _.keys(this.sections);
|
||||
_.each(docSections, sectionName => {
|
||||
const docSection = docAgnosticFormat[sectionName];
|
||||
if (_.isUndefined(docSection)) {
|
||||
return; // no-op
|
||||
}
|
||||
|
||||
if (!_.isUndefined(this.sections.types) && sectionName === this.sections.types) {
|
||||
const sortedTypesNames = _.sortBy(docSection.types, 'name');
|
||||
const typeNames = _.map(sortedTypesNames, t => t.name);
|
||||
menuSubsectionsBySection[sectionName] = typeNames;
|
||||
} else {
|
||||
let eventNames: string[] = [];
|
||||
if (!_.isUndefined(docSection.events)) {
|
||||
const sortedEventNames = _.sortBy(docSection.events, 'name');
|
||||
eventNames = _.map(sortedEventNames, m => m.name);
|
||||
}
|
||||
const sortedMethodNames = _.sortBy(docSection.methods, 'name');
|
||||
const methodNames = _.map(sortedMethodNames, m => m.name);
|
||||
menuSubsectionsBySection[sectionName] = [...methodNames, ...eventNames];
|
||||
}
|
||||
});
|
||||
return menuSubsectionsBySection;
|
||||
}
|
||||
public getTypeDefinitionsByName(docAgnosticFormat: DocAgnosticFormat) {
|
||||
if (_.isUndefined(this.sections.types)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const typeDocSection = docAgnosticFormat[this.sections.types];
|
||||
const typeDefinitionByName = _.keyBy(typeDocSection.types, 'name');
|
||||
return typeDefinitionByName;
|
||||
}
|
||||
public isVisibleConstructor(sectionName: string): boolean {
|
||||
return _.includes(this._docsInfo.visibleConstructors, sectionName);
|
||||
}
|
||||
public convertToDocAgnosticFormat(docObj: DoxityDocObj | TypeDocNode): DocAgnosticFormat {
|
||||
if (this.type === SupportedDocJson.Doxity) {
|
||||
return doxityUtils.convertToDocAgnosticFormat(docObj as DoxityDocObj);
|
||||
} else {
|
||||
return typeDocUtils.convertToDocAgnosticFormat(docObj as TypeDocNode, this);
|
||||
}
|
||||
}
|
||||
}
|
337
packages/react-docs/src/ts/components/documentation.tsx
Normal file
337
packages/react-docs/src/ts/components/documentation.tsx
Normal file
@@ -0,0 +1,337 @@
|
||||
import {
|
||||
colors,
|
||||
constants as sharedConstants,
|
||||
EtherscanLinkSuffixes,
|
||||
MarkdownSection,
|
||||
MenuSubsectionsBySection,
|
||||
NestedSidebarMenu,
|
||||
Networks,
|
||||
SectionHeader,
|
||||
Styles,
|
||||
utils as sharedUtils,
|
||||
} from '@0xproject/react-shared';
|
||||
import * as _ from 'lodash';
|
||||
import CircularProgress from 'material-ui/CircularProgress';
|
||||
import * as React from 'react';
|
||||
import { scroller } from 'react-scroll';
|
||||
|
||||
import {
|
||||
AddressByContractName,
|
||||
DocAgnosticFormat,
|
||||
DoxityDocObj,
|
||||
Event,
|
||||
Property,
|
||||
SolidityMethod,
|
||||
SupportedDocJson,
|
||||
TypeDefinitionByName,
|
||||
TypescriptMethod,
|
||||
} from '../types';
|
||||
import { utils } from '../utils/utils';
|
||||
|
||||
import { Badge } from './badge';
|
||||
import { Comment } from './comment';
|
||||
import { DocsInfo } from './docs_info';
|
||||
import { EventDefinition } from './event_definition';
|
||||
import { MethodBlock } from './method_block';
|
||||
import { SourceLink } from './source_link';
|
||||
import { Type } from './type';
|
||||
import { TypeDefinition } from './type_definition';
|
||||
|
||||
const TOP_BAR_HEIGHT = 60;
|
||||
|
||||
const networkNameToColor: { [network: string]: string } = {
|
||||
[Networks.Kovan]: colors.purple,
|
||||
[Networks.Ropsten]: colors.red,
|
||||
[Networks.Mainnet]: colors.turquois,
|
||||
[Networks.Rinkeby]: colors.darkYellow,
|
||||
};
|
||||
|
||||
export interface DocumentationProps {
|
||||
location: Location;
|
||||
docsVersion: string;
|
||||
availableDocVersions: string[];
|
||||
docsInfo: DocsInfo;
|
||||
docAgnosticFormat?: DocAgnosticFormat;
|
||||
menuSubsectionsBySection: MenuSubsectionsBySection;
|
||||
sourceUrl: string;
|
||||
}
|
||||
|
||||
export interface DocumentationState {}
|
||||
|
||||
const styles: Styles = {
|
||||
mainContainers: {
|
||||
position: 'absolute',
|
||||
top: 1,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
overflowZ: 'hidden',
|
||||
overflowY: 'scroll',
|
||||
minHeight: `calc(100vh - ${TOP_BAR_HEIGHT}px)`,
|
||||
WebkitOverflowScrolling: 'touch',
|
||||
},
|
||||
menuContainer: {
|
||||
borderColor: colors.grey300,
|
||||
maxWidth: 330,
|
||||
marginLeft: 20,
|
||||
},
|
||||
};
|
||||
|
||||
export class Documentation extends React.Component<DocumentationProps, DocumentationState> {
|
||||
public componentDidUpdate(prevProps: DocumentationProps, prevState: DocumentationState) {
|
||||
if (!_.isEqual(prevProps.docAgnosticFormat, this.props.docAgnosticFormat)) {
|
||||
const hash = this.props.location.hash.slice(1);
|
||||
sharedUtils.scrollToHash(hash, sharedConstants.SCROLL_CONTAINER_ID);
|
||||
}
|
||||
}
|
||||
public render() {
|
||||
return (
|
||||
<div>
|
||||
{_.isUndefined(this.props.docAgnosticFormat) ? (
|
||||
this._renderLoading()
|
||||
) : (
|
||||
<div style={{ width: '100%', height: '100%', backgroundColor: colors.gray40 }}>
|
||||
<div
|
||||
className="mx-auto max-width-4 flex"
|
||||
style={{ color: colors.grey800, height: `calc(100vh - ${TOP_BAR_HEIGHT}px)` }}
|
||||
>
|
||||
<div
|
||||
className="relative sm-hide xs-hide"
|
||||
style={{ width: '36%', height: `calc(100vh - ${TOP_BAR_HEIGHT}px)` }}
|
||||
>
|
||||
<div
|
||||
className="border-right absolute"
|
||||
style={{
|
||||
...styles.menuContainer,
|
||||
...styles.mainContainers,
|
||||
height: `calc(100vh - ${TOP_BAR_HEIGHT}px)`,
|
||||
}}
|
||||
>
|
||||
<NestedSidebarMenu
|
||||
selectedVersion={this.props.docsVersion}
|
||||
versions={this.props.availableDocVersions}
|
||||
title={this.props.docsInfo.displayName}
|
||||
topLevelMenu={this.props.docsInfo.getMenu(this.props.docsVersion)}
|
||||
menuSubsectionsBySection={this.props.menuSubsectionsBySection}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="relative col lg-col-9 md-col-9 sm-col-12 col-12"
|
||||
style={{ backgroundColor: colors.white }}
|
||||
>
|
||||
<div
|
||||
id={sharedConstants.SCROLL_CONTAINER_ID}
|
||||
style={styles.mainContainers}
|
||||
className="absolute px1"
|
||||
>
|
||||
<div id={sharedConstants.SCROLL_TOP_ID} />
|
||||
{this._renderDocumentation()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
private _renderLoading() {
|
||||
return (
|
||||
<div className="col col-12" style={styles.mainContainers}>
|
||||
<div
|
||||
className="relative sm-px2 sm-pt2 sm-m1"
|
||||
style={{ height: 122, top: '50%', transform: 'translateY(-50%)' }}
|
||||
>
|
||||
<div className="center pb2">
|
||||
<CircularProgress size={40} thickness={5} />
|
||||
</div>
|
||||
<div className="center pt2" style={{ paddingBottom: 11 }}>
|
||||
Loading documentation...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
private _renderDocumentation(): React.ReactNode {
|
||||
const subMenus = _.values(this.props.docsInfo.getMenu());
|
||||
const orderedSectionNames = _.flatten(subMenus);
|
||||
|
||||
const typeDefinitionByName = this.props.docsInfo.getTypeDefinitionsByName(this.props.docAgnosticFormat);
|
||||
const renderedSections = _.map(orderedSectionNames, this._renderSection.bind(this, typeDefinitionByName));
|
||||
|
||||
return renderedSections;
|
||||
}
|
||||
private _renderSection(typeDefinitionByName: TypeDefinitionByName, sectionName: string): React.ReactNode {
|
||||
const markdownFileIfExists = this.props.docsInfo.sectionNameToMarkdown[sectionName];
|
||||
if (!_.isUndefined(markdownFileIfExists)) {
|
||||
return (
|
||||
<MarkdownSection
|
||||
key={`markdown-section-${sectionName}`}
|
||||
sectionName={sectionName}
|
||||
markdownContent={markdownFileIfExists}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const docSection = this.props.docAgnosticFormat[sectionName];
|
||||
if (_.isUndefined(docSection)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const sortedTypes = _.sortBy(docSection.types, 'name');
|
||||
const typeDefs = _.map(sortedTypes, customType => {
|
||||
return (
|
||||
<TypeDefinition
|
||||
sectionName={sectionName}
|
||||
key={`type-${customType.name}`}
|
||||
customType={customType}
|
||||
docsInfo={this.props.docsInfo}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
const sortedProperties = _.sortBy(docSection.properties, 'name');
|
||||
const propertyDefs = _.map(sortedProperties, this._renderProperty.bind(this, sectionName));
|
||||
|
||||
const sortedMethods = _.sortBy(docSection.methods, 'name');
|
||||
const methodDefs = _.map(sortedMethods, method => {
|
||||
const isConstructor = false;
|
||||
return this._renderMethodBlocks(method, sectionName, isConstructor, typeDefinitionByName);
|
||||
});
|
||||
|
||||
const sortedEvents = _.sortBy(docSection.events, 'name');
|
||||
const eventDefs = _.map(sortedEvents, (event: Event, i: number) => {
|
||||
return (
|
||||
<EventDefinition
|
||||
key={`event-${event.name}-${i}`}
|
||||
event={event}
|
||||
sectionName={sectionName}
|
||||
docsInfo={this.props.docsInfo}
|
||||
/>
|
||||
);
|
||||
});
|
||||
return (
|
||||
<div key={`section-${sectionName}`} className="py2 pr3 md-pl2 sm-pl3">
|
||||
<div className="flex pb2">
|
||||
<div style={{ marginRight: 7 }}>
|
||||
<SectionHeader sectionName={sectionName} />
|
||||
</div>
|
||||
{this._renderNetworkBadgesIfExists(sectionName)}
|
||||
</div>
|
||||
{docSection.comment && <Comment comment={docSection.comment} />}
|
||||
{docSection.constructors.length > 0 &&
|
||||
this.props.docsInfo.isVisibleConstructor(sectionName) && (
|
||||
<div>
|
||||
<h2 className="thin">Constructor</h2>
|
||||
{this._renderConstructors(docSection.constructors, sectionName, typeDefinitionByName)}
|
||||
</div>
|
||||
)}
|
||||
{docSection.properties.length > 0 && (
|
||||
<div>
|
||||
<h2 className="thin">Properties</h2>
|
||||
<div>{propertyDefs}</div>
|
||||
</div>
|
||||
)}
|
||||
{docSection.methods.length > 0 && (
|
||||
<div>
|
||||
<h2 className="thin">Methods</h2>
|
||||
<div>{methodDefs}</div>
|
||||
</div>
|
||||
)}
|
||||
{!_.isUndefined(docSection.events) &&
|
||||
docSection.events.length > 0 && (
|
||||
<div>
|
||||
<h2 className="thin">Events</h2>
|
||||
<div>{eventDefs}</div>
|
||||
</div>
|
||||
)}
|
||||
{!_.isUndefined(typeDefs) &&
|
||||
typeDefs.length > 0 && (
|
||||
<div>
|
||||
<div>{typeDefs}</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
private _renderNetworkBadgesIfExists(sectionName: string) {
|
||||
if (this.props.docsInfo.type !== SupportedDocJson.Doxity) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const networkToAddressByContractName = this.props.docsInfo.contractsByVersionByNetworkId[
|
||||
this.props.docsVersion
|
||||
];
|
||||
const badges = _.map(
|
||||
networkToAddressByContractName,
|
||||
(addressByContractName: AddressByContractName, networkName: string) => {
|
||||
const contractAddress = addressByContractName[sectionName];
|
||||
if (_.isUndefined(contractAddress)) {
|
||||
return null;
|
||||
}
|
||||
const linkIfExists = sharedUtils.getEtherScanLinkIfExists(
|
||||
contractAddress,
|
||||
sharedConstants.NETWORK_ID_BY_NAME[networkName],
|
||||
EtherscanLinkSuffixes.Address,
|
||||
);
|
||||
return (
|
||||
<a
|
||||
key={`badge-${networkName}-${sectionName}`}
|
||||
href={linkIfExists}
|
||||
target="_blank"
|
||||
style={{ color: colors.white, textDecoration: 'none' }}
|
||||
>
|
||||
<Badge title={networkName} backgroundColor={networkNameToColor[networkName]} />
|
||||
</a>
|
||||
);
|
||||
},
|
||||
);
|
||||
return badges;
|
||||
}
|
||||
private _renderConstructors(
|
||||
constructors: SolidityMethod[] | TypescriptMethod[],
|
||||
sectionName: string,
|
||||
typeDefinitionByName: TypeDefinitionByName,
|
||||
): React.ReactNode {
|
||||
const constructorDefs = _.map(constructors, constructor => {
|
||||
return this._renderMethodBlocks(constructor, sectionName, constructor.isConstructor, typeDefinitionByName);
|
||||
});
|
||||
return <div>{constructorDefs}</div>;
|
||||
}
|
||||
private _renderProperty(sectionName: string, property: Property): React.ReactNode {
|
||||
return (
|
||||
<div key={`property-${property.name}-${property.type.name}`} className="pb3">
|
||||
<code className="hljs">
|
||||
{property.name}:
|
||||
<Type type={property.type} sectionName={sectionName} docsInfo={this.props.docsInfo} />
|
||||
</code>
|
||||
{property.source && (
|
||||
<SourceLink
|
||||
version={this.props.docsVersion}
|
||||
source={property.source}
|
||||
sourceUrl={this.props.sourceUrl}
|
||||
/>
|
||||
)}
|
||||
{property.comment && <Comment comment={property.comment} className="py2" />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
private _renderMethodBlocks(
|
||||
method: SolidityMethod | TypescriptMethod,
|
||||
sectionName: string,
|
||||
isConstructor: boolean,
|
||||
typeDefinitionByName: TypeDefinitionByName,
|
||||
): React.ReactNode {
|
||||
return (
|
||||
<MethodBlock
|
||||
key={`method-${method.name}-${sectionName}`}
|
||||
sectionName={sectionName}
|
||||
method={method}
|
||||
typeDefinitionByName={typeDefinitionByName}
|
||||
libraryVersion={this.props.docsVersion}
|
||||
docsInfo={this.props.docsInfo}
|
||||
sourceUrl={this.props.sourceUrl}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
23
packages/react-docs/src/ts/components/enum.tsx
Normal file
23
packages/react-docs/src/ts/components/enum.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { EnumValue } from '../types';
|
||||
|
||||
export interface EnumProps {
|
||||
values: EnumValue[];
|
||||
}
|
||||
|
||||
export function Enum(props: EnumProps) {
|
||||
const values = _.map(props.values, (value, i) => {
|
||||
const defaultValueIfAny = !_.isUndefined(value.defaultValue) ? ` = ${value.defaultValue}` : '';
|
||||
return `\n\t${value.name}${defaultValueIfAny},`;
|
||||
});
|
||||
return (
|
||||
<span>
|
||||
{`{`}
|
||||
{values}
|
||||
<br />
|
||||
{`}`}
|
||||
</span>
|
||||
);
|
||||
}
|
84
packages/react-docs/src/ts/components/event_definition.tsx
Normal file
84
packages/react-docs/src/ts/components/event_definition.tsx
Normal file
@@ -0,0 +1,84 @@
|
||||
import { AnchorTitle, colors, HeaderSizes } from '@0xproject/react-shared';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { Event, EventArg } from '../types';
|
||||
|
||||
import { DocsInfo } from './docs_info';
|
||||
import { Type } from './type';
|
||||
|
||||
export interface EventDefinitionProps {
|
||||
event: Event;
|
||||
sectionName: string;
|
||||
docsInfo: DocsInfo;
|
||||
}
|
||||
|
||||
export interface EventDefinitionState {
|
||||
shouldShowAnchor: boolean;
|
||||
}
|
||||
|
||||
export class EventDefinition extends React.Component<EventDefinitionProps, EventDefinitionState> {
|
||||
constructor(props: EventDefinitionProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
shouldShowAnchor: false,
|
||||
};
|
||||
}
|
||||
public render() {
|
||||
const event = this.props.event;
|
||||
const id = `${this.props.sectionName}-${event.name}`;
|
||||
return (
|
||||
<div
|
||||
id={id}
|
||||
className="pb2"
|
||||
style={{ overflow: 'hidden', width: '100%' }}
|
||||
onMouseOver={this._setAnchorVisibility.bind(this, true)}
|
||||
onMouseOut={this._setAnchorVisibility.bind(this, false)}
|
||||
>
|
||||
<AnchorTitle
|
||||
headerSize={HeaderSizes.H3}
|
||||
title={`Event ${event.name}`}
|
||||
id={id}
|
||||
shouldShowAnchor={this.state.shouldShowAnchor}
|
||||
/>
|
||||
<div style={{ fontSize: 16 }}>
|
||||
<pre>
|
||||
<code className="hljs">{this._renderEventCode()}</code>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
private _renderEventCode() {
|
||||
const indexed = <span style={{ color: colors.green }}> indexed</span>;
|
||||
const eventArgs = _.map(this.props.event.eventArgs, (eventArg: EventArg) => {
|
||||
const type = (
|
||||
<Type type={eventArg.type} sectionName={this.props.sectionName} docsInfo={this.props.docsInfo} />
|
||||
);
|
||||
return (
|
||||
<span key={`eventArg-${eventArg.name}`}>
|
||||
{eventArg.name}
|
||||
{eventArg.isIndexed ? indexed : ''}: {type},
|
||||
</span>
|
||||
);
|
||||
});
|
||||
const argList = _.reduce(eventArgs, (prev: React.ReactNode, curr: React.ReactNode) => {
|
||||
return [prev, '\n\t', curr];
|
||||
});
|
||||
return (
|
||||
<span>
|
||||
{`{`}
|
||||
<br />
|
||||
{'\t'}
|
||||
{argList}
|
||||
<br />
|
||||
{`}`}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
private _setAnchorVisibility(shouldShowAnchor: boolean) {
|
||||
this.setState({
|
||||
shouldShowAnchor,
|
||||
});
|
||||
}
|
||||
}
|
63
packages/react-docs/src/ts/components/interface.tsx
Normal file
63
packages/react-docs/src/ts/components/interface.tsx
Normal file
@@ -0,0 +1,63 @@
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { CustomType, TypeDocTypes } from '../types';
|
||||
|
||||
import { DocsInfo } from './docs_info';
|
||||
import { MethodSignature } from './method_signature';
|
||||
import { Type } from './type';
|
||||
|
||||
export interface InterfaceProps {
|
||||
type: CustomType;
|
||||
sectionName: string;
|
||||
docsInfo: DocsInfo;
|
||||
}
|
||||
|
||||
export function Interface(props: InterfaceProps) {
|
||||
const type = props.type;
|
||||
const properties = _.map(type.children, property => {
|
||||
return (
|
||||
<span key={`property-${property.name}-${property.type}-${type.name}`}>
|
||||
{property.name}:{' '}
|
||||
{property.type.typeDocType !== TypeDocTypes.Reflection ? (
|
||||
<Type type={property.type} sectionName={props.sectionName} docsInfo={props.docsInfo} />
|
||||
) : (
|
||||
<MethodSignature
|
||||
method={property.type.method}
|
||||
sectionName={props.sectionName}
|
||||
shouldHideMethodName={true}
|
||||
shouldUseArrowSyntax={true}
|
||||
docsInfo={props.docsInfo}
|
||||
/>
|
||||
)},
|
||||
</span>
|
||||
);
|
||||
});
|
||||
const hasIndexSignature = !_.isUndefined(type.indexSignature);
|
||||
if (hasIndexSignature) {
|
||||
const is = type.indexSignature;
|
||||
const param = (
|
||||
<span key={`indexSigParams-${is.keyName}-${is.keyType}-${type.name}`}>
|
||||
{is.keyName}: <Type type={is.keyType} sectionName={props.sectionName} docsInfo={props.docsInfo} />
|
||||
</span>
|
||||
);
|
||||
properties.push(
|
||||
<span key={`indexSignature-${type.name}-${is.keyType.name}`}>
|
||||
[{param}]: {is.valueName},
|
||||
</span>,
|
||||
);
|
||||
}
|
||||
const propertyList = _.reduce(properties, (prev: React.ReactNode, curr: React.ReactNode) => {
|
||||
return [prev, '\n\t', curr];
|
||||
});
|
||||
return (
|
||||
<span>
|
||||
{`{`}
|
||||
<br />
|
||||
{'\t'}
|
||||
{propertyList}
|
||||
<br />
|
||||
{`}`}
|
||||
</span>
|
||||
);
|
||||
}
|
149
packages/react-docs/src/ts/components/method_block.tsx
Normal file
149
packages/react-docs/src/ts/components/method_block.tsx
Normal file
@@ -0,0 +1,149 @@
|
||||
import { AnchorTitle, colors, HeaderSizes, Styles } from '@0xproject/react-shared';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { Parameter, SolidityMethod, TypeDefinitionByName, TypescriptMethod } from '../types';
|
||||
import { typeDocUtils } from '../utils/typedoc_utils';
|
||||
|
||||
import { Comment } from './comment';
|
||||
import { DocsInfo } from './docs_info';
|
||||
import { MethodSignature } from './method_signature';
|
||||
import { SourceLink } from './source_link';
|
||||
|
||||
export interface MethodBlockProps {
|
||||
method: SolidityMethod | TypescriptMethod;
|
||||
sectionName: string;
|
||||
libraryVersion: string;
|
||||
typeDefinitionByName: TypeDefinitionByName;
|
||||
docsInfo: DocsInfo;
|
||||
sourceUrl: string;
|
||||
}
|
||||
|
||||
export interface MethodBlockState {
|
||||
shouldShowAnchor: boolean;
|
||||
}
|
||||
|
||||
const styles: Styles = {
|
||||
chip: {
|
||||
fontSize: 13,
|
||||
backgroundColor: colors.lightBlueA700,
|
||||
color: colors.white,
|
||||
height: 11,
|
||||
borderRadius: 14,
|
||||
lineHeight: 0.9,
|
||||
},
|
||||
};
|
||||
|
||||
export class MethodBlock extends React.Component<MethodBlockProps, MethodBlockState> {
|
||||
constructor(props: MethodBlockProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
shouldShowAnchor: false,
|
||||
};
|
||||
}
|
||||
public render() {
|
||||
const method = this.props.method;
|
||||
if (typeDocUtils.isPrivateOrProtectedProperty(method.name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
id={`${this.props.sectionName}-${method.name}`}
|
||||
style={{ overflow: 'hidden', width: '100%' }}
|
||||
className="pb4"
|
||||
onMouseOver={this._setAnchorVisibility.bind(this, true)}
|
||||
onMouseOut={this._setAnchorVisibility.bind(this, false)}
|
||||
>
|
||||
{!method.isConstructor && (
|
||||
<div className="flex pb2 pt2">
|
||||
{(method as TypescriptMethod).isStatic && this._renderChip('Static')}
|
||||
{(method as SolidityMethod).isConstant && this._renderChip('Constant')}
|
||||
{(method as SolidityMethod).isPayable && this._renderChip('Payable')}
|
||||
<div style={{ lineHeight: 1.3 }}>
|
||||
<AnchorTitle
|
||||
headerSize={HeaderSizes.H3}
|
||||
title={method.name}
|
||||
id={`${this.props.sectionName}-${method.name}`}
|
||||
shouldShowAnchor={this.state.shouldShowAnchor}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<code className="hljs">
|
||||
<MethodSignature
|
||||
method={method}
|
||||
sectionName={this.props.sectionName}
|
||||
typeDefinitionByName={this.props.typeDefinitionByName}
|
||||
docsInfo={this.props.docsInfo}
|
||||
/>
|
||||
</code>
|
||||
{(method as TypescriptMethod).source && (
|
||||
<SourceLink
|
||||
version={this.props.libraryVersion}
|
||||
source={(method as TypescriptMethod).source}
|
||||
sourceUrl={this.props.sourceUrl}
|
||||
/>
|
||||
)}
|
||||
{method.comment && <Comment comment={method.comment} className="py2" />}
|
||||
{method.parameters &&
|
||||
!_.isEmpty(method.parameters) && (
|
||||
<div>
|
||||
<h4 className="pb1 thin" style={{ borderBottom: '1px solid #e1e8ed' }}>
|
||||
ARGUMENTS
|
||||
</h4>
|
||||
{this._renderParameterDescriptions(method.parameters)}
|
||||
</div>
|
||||
)}
|
||||
{method.returnComment && (
|
||||
<div className="pt1 comment">
|
||||
<h4 className="pb1 thin" style={{ borderBottom: '1px solid #e1e8ed' }}>
|
||||
RETURNS
|
||||
</h4>
|
||||
<Comment comment={method.returnComment} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
private _renderChip(text: string) {
|
||||
return (
|
||||
<div className="p1 mr1" style={styles.chip}>
|
||||
{text}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
private _renderParameterDescriptions(parameters: Parameter[]) {
|
||||
const descriptions = _.map(parameters, parameter => {
|
||||
const isOptional = parameter.isOptional;
|
||||
return (
|
||||
<div
|
||||
key={`param-description-${parameter.name}`}
|
||||
className="flex pb1 mb2"
|
||||
style={{ borderBottom: '1px solid #f0f4f7' }}
|
||||
>
|
||||
<div className="pl2 col lg-col-4 md-col-4 sm-col-12 col-12">
|
||||
<div
|
||||
className="bold"
|
||||
style={{ overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' }}
|
||||
>
|
||||
{parameter.name}
|
||||
</div>
|
||||
<div className="pt1" style={{ color: colors.grey, fontSize: 14 }}>
|
||||
{isOptional && 'optional'}
|
||||
</div>
|
||||
</div>
|
||||
<div className="col lg-col-8 md-col-8 sm-col-12 col-12" style={{ paddingLeft: 5 }}>
|
||||
{parameter.comment && <Comment comment={parameter.comment} />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
return descriptions;
|
||||
}
|
||||
private _setAnchorVisibility(shouldShowAnchor: boolean) {
|
||||
this.setState({
|
||||
shouldShowAnchor,
|
||||
});
|
||||
}
|
||||
}
|
128
packages/react-docs/src/ts/components/method_signature.tsx
Normal file
128
packages/react-docs/src/ts/components/method_signature.tsx
Normal file
@@ -0,0 +1,128 @@
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
|
||||
import { Parameter, SolidityMethod, TypeDefinitionByName, TypescriptMethod } from '../types';
|
||||
import { constants } from '../utils/constants';
|
||||
|
||||
import { DocsInfo } from './docs_info';
|
||||
import { Type } from './type';
|
||||
|
||||
export interface MethodSignatureProps {
|
||||
method: TypescriptMethod | SolidityMethod;
|
||||
sectionName: string;
|
||||
shouldHideMethodName?: boolean;
|
||||
shouldUseArrowSyntax?: boolean;
|
||||
typeDefinitionByName?: TypeDefinitionByName;
|
||||
docsInfo: DocsInfo;
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
shouldHideMethodName: false,
|
||||
shouldUseArrowSyntax: false,
|
||||
};
|
||||
|
||||
export const MethodSignature: React.SFC<MethodSignatureProps> = (props: MethodSignatureProps) => {
|
||||
const sectionName = constants.TYPES_SECTION_NAME;
|
||||
const parameters = renderParameters(props.method, props.docsInfo, sectionName, props.typeDefinitionByName);
|
||||
const paramStringArray: any[] = [];
|
||||
// HACK: For now we don't put params on newlines if there are less then 2 of them.
|
||||
// Ideally we would check the character length of the resulting method signature and
|
||||
// if it exceeds the available space, put params on their own lines.
|
||||
const hasMoreThenTwoParams = parameters.length > 2;
|
||||
_.each(parameters, (param: React.ReactNode, i: number) => {
|
||||
const finalParam = hasMoreThenTwoParams ? (
|
||||
<span className="pl2" key={`param-${i}`}>
|
||||
{param}
|
||||
</span>
|
||||
) : (
|
||||
param
|
||||
);
|
||||
paramStringArray.push(finalParam);
|
||||
const comma = hasMoreThenTwoParams ? (
|
||||
<span key={`param-comma-${i}`}>
|
||||
, <br />
|
||||
</span>
|
||||
) : (
|
||||
', '
|
||||
);
|
||||
paramStringArray.push(comma);
|
||||
});
|
||||
if (!hasMoreThenTwoParams) {
|
||||
paramStringArray.pop();
|
||||
}
|
||||
const methodName = props.shouldHideMethodName ? '' : props.method.name;
|
||||
const typeParameterIfExists = _.isUndefined((props.method as TypescriptMethod).typeParameter)
|
||||
? undefined
|
||||
: renderTypeParameter(props.method, props.docsInfo, sectionName, props.typeDefinitionByName);
|
||||
return (
|
||||
<span style={{ fontSize: 15 }}>
|
||||
{props.method.callPath}
|
||||
{methodName}
|
||||
{typeParameterIfExists}({hasMoreThenTwoParams && <br />}
|
||||
{paramStringArray})
|
||||
{props.method.returnType && (
|
||||
<span>
|
||||
{props.shouldUseArrowSyntax ? ' => ' : ': '}{' '}
|
||||
<Type
|
||||
type={props.method.returnType}
|
||||
sectionName={sectionName}
|
||||
typeDefinitionByName={props.typeDefinitionByName}
|
||||
docsInfo={props.docsInfo}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
MethodSignature.defaultProps = defaultProps;
|
||||
|
||||
function renderParameters(
|
||||
method: TypescriptMethod | SolidityMethod,
|
||||
docsInfo: DocsInfo,
|
||||
sectionName: string,
|
||||
typeDefinitionByName?: TypeDefinitionByName,
|
||||
) {
|
||||
const parameters = method.parameters;
|
||||
const params = _.map(parameters, (p: Parameter) => {
|
||||
const isOptional = p.isOptional;
|
||||
const type = (
|
||||
<Type
|
||||
type={p.type}
|
||||
sectionName={sectionName}
|
||||
typeDefinitionByName={typeDefinitionByName}
|
||||
docsInfo={docsInfo}
|
||||
/>
|
||||
);
|
||||
return (
|
||||
<span key={`param-${p.type}-${p.name}`}>
|
||||
{p.name}
|
||||
{isOptional && '?'}: {type}
|
||||
</span>
|
||||
);
|
||||
});
|
||||
return params;
|
||||
}
|
||||
|
||||
function renderTypeParameter(
|
||||
method: TypescriptMethod,
|
||||
docsInfo: DocsInfo,
|
||||
sectionName: string,
|
||||
typeDefinitionByName?: TypeDefinitionByName,
|
||||
) {
|
||||
const typeParameter = method.typeParameter;
|
||||
const typeParam = (
|
||||
<span>
|
||||
{`<${typeParameter.name} extends `}
|
||||
<Type
|
||||
type={typeParameter.type}
|
||||
sectionName={sectionName}
|
||||
typeDefinitionByName={typeDefinitionByName}
|
||||
docsInfo={docsInfo}
|
||||
/>
|
||||
{`>`}
|
||||
</span>
|
||||
);
|
||||
return typeParam;
|
||||
}
|
23
packages/react-docs/src/ts/components/source_link.tsx
Normal file
23
packages/react-docs/src/ts/components/source_link.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { colors } from '@0xproject/react-shared';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { Source } from '../types';
|
||||
|
||||
export interface SourceLinkProps {
|
||||
source: Source;
|
||||
sourceUrl: string;
|
||||
version: string;
|
||||
}
|
||||
|
||||
export function SourceLink(props: SourceLinkProps) {
|
||||
const src = props.source;
|
||||
const sourceCodeUrl = `${props.sourceUrl}/${src.fileName}#L${src.line}`;
|
||||
return (
|
||||
<div className="pt2" style={{ fontSize: 14 }}>
|
||||
<a href={sourceCodeUrl} target="_blank" className="underline" style={{ color: colors.grey }}>
|
||||
Source
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
231
packages/react-docs/src/ts/components/type.tsx
Normal file
231
packages/react-docs/src/ts/components/type.tsx
Normal file
@@ -0,0 +1,231 @@
|
||||
import { colors, constants as sharedConstants, utils as sharedUtils } from '@0xproject/react-shared';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
import { Link as ScrollLink } from 'react-scroll';
|
||||
import * as ReactTooltip from 'react-tooltip';
|
||||
|
||||
import { Type as TypeDef, TypeDefinitionByName, TypeDocTypes } from '../types';
|
||||
import { constants } from '../utils/constants';
|
||||
import { utils } from '../utils/utils';
|
||||
|
||||
import { DocsInfo } from './docs_info';
|
||||
import { TypeDefinition } from './type_definition';
|
||||
|
||||
// Some types reference other libraries. For these types, we want to link the user to the relevant documentation.
|
||||
const typeToUrl: { [typeName: string]: string } = {
|
||||
Web3: constants.URL_WEB3_DOCS,
|
||||
Provider: constants.URL_WEB3_PROVIDER_DOCS,
|
||||
BigNumber: constants.URL_BIGNUMBERJS_GITHUB,
|
||||
DecodedLogEntryEvent: constants.URL_WEB3_DECODED_LOG_ENTRY_EVENT,
|
||||
LogEntryEvent: constants.URL_WEB3_LOG_ENTRY_EVENT,
|
||||
};
|
||||
|
||||
const typePrefix: { [typeName: string]: string } = {
|
||||
Provider: 'Web3',
|
||||
DecodedLogEntryEvent: 'Web3',
|
||||
LogEntryEvent: 'Web3',
|
||||
};
|
||||
|
||||
const typeToSection: { [typeName: string]: string } = {
|
||||
ExchangeWrapper: 'exchange',
|
||||
TokenWrapper: 'token',
|
||||
TokenRegistryWrapper: 'tokenRegistry',
|
||||
EtherTokenWrapper: 'etherToken',
|
||||
ProxyWrapper: 'proxy',
|
||||
TokenTransferProxyWrapper: 'proxy',
|
||||
OrderStateWatcher: 'orderWatcher',
|
||||
};
|
||||
|
||||
export interface TypeProps {
|
||||
type: TypeDef;
|
||||
docsInfo: DocsInfo;
|
||||
sectionName: string;
|
||||
typeDefinitionByName?: TypeDefinitionByName;
|
||||
}
|
||||
|
||||
// The return type needs to be `any` here so that we can recursively define <Type /> components within
|
||||
// <Type /> components (e.g when rendering the union type).
|
||||
export function Type(props: TypeProps): any {
|
||||
const type = props.type;
|
||||
const isReference = type.typeDocType === TypeDocTypes.Reference;
|
||||
const isArray = type.typeDocType === TypeDocTypes.Array;
|
||||
let typeNameColor = 'inherit';
|
||||
let typeName: string | React.ReactNode;
|
||||
let typeArgs: React.ReactNode[] = [];
|
||||
switch (type.typeDocType) {
|
||||
case TypeDocTypes.Intrinsic:
|
||||
case TypeDocTypes.Unknown:
|
||||
typeName = type.name;
|
||||
typeNameColor = colors.orange;
|
||||
break;
|
||||
|
||||
case TypeDocTypes.Reference:
|
||||
typeName = type.name;
|
||||
typeArgs = _.map(type.typeArguments, (arg: TypeDef) => {
|
||||
if (arg.typeDocType === TypeDocTypes.Array) {
|
||||
const key = `type-${arg.elementType.name}-${arg.elementType.typeDocType}`;
|
||||
return (
|
||||
<span>
|
||||
<Type
|
||||
key={key}
|
||||
type={arg.elementType}
|
||||
sectionName={props.sectionName}
|
||||
typeDefinitionByName={props.typeDefinitionByName}
|
||||
docsInfo={props.docsInfo}
|
||||
/>[]
|
||||
</span>
|
||||
);
|
||||
} else {
|
||||
const subType = (
|
||||
<Type
|
||||
key={`type-${arg.name}-${arg.value}-${arg.typeDocType}`}
|
||||
type={arg}
|
||||
sectionName={props.sectionName}
|
||||
typeDefinitionByName={props.typeDefinitionByName}
|
||||
docsInfo={props.docsInfo}
|
||||
/>
|
||||
);
|
||||
return subType;
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case TypeDocTypes.StringLiteral:
|
||||
typeName = `'${type.value}'`;
|
||||
typeNameColor = colors.green;
|
||||
break;
|
||||
|
||||
case TypeDocTypes.Array:
|
||||
typeName = type.elementType.name;
|
||||
break;
|
||||
|
||||
case TypeDocTypes.Union:
|
||||
const unionTypes = _.map(type.types, t => {
|
||||
return (
|
||||
<Type
|
||||
key={`type-${t.name}-${t.value}-${t.typeDocType}`}
|
||||
type={t}
|
||||
sectionName={props.sectionName}
|
||||
typeDefinitionByName={props.typeDefinitionByName}
|
||||
docsInfo={props.docsInfo}
|
||||
/>
|
||||
);
|
||||
});
|
||||
typeName = _.reduce(unionTypes, (prev: React.ReactNode, curr: React.ReactNode) => {
|
||||
return [prev, '|', curr];
|
||||
});
|
||||
break;
|
||||
|
||||
case TypeDocTypes.TypeParameter:
|
||||
typeName = type.name;
|
||||
break;
|
||||
|
||||
case TypeDocTypes.Intersection:
|
||||
const intersectionsTypes = _.map(type.types, t => {
|
||||
return (
|
||||
<Type
|
||||
key={`type-${t.name}-${t.value}-${t.typeDocType}`}
|
||||
type={t}
|
||||
sectionName={props.sectionName}
|
||||
typeDefinitionByName={props.typeDefinitionByName}
|
||||
docsInfo={props.docsInfo}
|
||||
/>
|
||||
);
|
||||
});
|
||||
typeName = _.reduce(intersectionsTypes, (prev: React.ReactNode, curr: React.ReactNode) => {
|
||||
return [prev, '&', curr];
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
throw utils.spawnSwitchErr('type.typeDocType', type.typeDocType);
|
||||
}
|
||||
// HACK: Normalize BigNumber to simply BigNumber. For some reason the type
|
||||
// name is unpredictably one or the other.
|
||||
if (typeName === 'BigNumber') {
|
||||
typeName = 'BigNumber';
|
||||
}
|
||||
const commaSeparatedTypeArgs = _.reduce(typeArgs, (prev: React.ReactNode, curr: React.ReactNode) => {
|
||||
return [prev, ', ', curr];
|
||||
});
|
||||
|
||||
const typeNameUrlIfExists = typeToUrl[typeName as string];
|
||||
const typePrefixIfExists = typePrefix[typeName as string];
|
||||
const sectionNameIfExists = typeToSection[typeName as string];
|
||||
if (!_.isUndefined(typeNameUrlIfExists)) {
|
||||
typeName = (
|
||||
<a
|
||||
href={typeNameUrlIfExists}
|
||||
target="_blank"
|
||||
className="text-decoration-none"
|
||||
style={{ color: colors.lightBlueA700 }}
|
||||
>
|
||||
{!_.isUndefined(typePrefixIfExists) ? `${typePrefixIfExists}.` : ''}
|
||||
{typeName}
|
||||
</a>
|
||||
);
|
||||
} else if (
|
||||
(isReference || isArray) &&
|
||||
(props.docsInfo.isPublicType(typeName as string) || !_.isUndefined(sectionNameIfExists))
|
||||
) {
|
||||
const id = Math.random().toString();
|
||||
const typeDefinitionAnchorId = _.isUndefined(sectionNameIfExists)
|
||||
? `${props.sectionName}-${typeName}`
|
||||
: sectionNameIfExists;
|
||||
let typeDefinition;
|
||||
if (props.typeDefinitionByName) {
|
||||
typeDefinition = props.typeDefinitionByName[typeName as string];
|
||||
}
|
||||
typeName = (
|
||||
<ScrollLink
|
||||
to={typeDefinitionAnchorId}
|
||||
offset={0}
|
||||
duration={sharedConstants.DOCS_SCROLL_DURATION_MS}
|
||||
containerId={sharedConstants.DOCS_CONTAINER_ID}
|
||||
>
|
||||
{_.isUndefined(typeDefinition) || sharedUtils.isUserOnMobile() ? (
|
||||
<span
|
||||
onClick={sharedUtils.setUrlHash.bind(null, typeDefinitionAnchorId)}
|
||||
style={{ color: colors.lightBlueA700, cursor: 'pointer' }}
|
||||
>
|
||||
{typeName}
|
||||
</span>
|
||||
) : (
|
||||
<span
|
||||
data-tip={true}
|
||||
data-for={id}
|
||||
onClick={sharedUtils.setUrlHash.bind(null, typeDefinitionAnchorId)}
|
||||
style={{
|
||||
color: colors.lightBlueA700,
|
||||
cursor: 'pointer',
|
||||
display: 'inline-block',
|
||||
}}
|
||||
>
|
||||
{typeName}
|
||||
<ReactTooltip type="light" effect="solid" id={id} className="typeTooltip">
|
||||
<TypeDefinition
|
||||
sectionName={props.sectionName}
|
||||
customType={typeDefinition}
|
||||
shouldAddId={false}
|
||||
docsInfo={props.docsInfo}
|
||||
/>
|
||||
</ReactTooltip>
|
||||
</span>
|
||||
)}
|
||||
</ScrollLink>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<span>
|
||||
<span style={{ color: typeNameColor }}>{typeName}</span>
|
||||
{isArray && '[]'}
|
||||
{!_.isEmpty(typeArgs) && (
|
||||
<span>
|
||||
{'<'}
|
||||
{commaSeparatedTypeArgs}
|
||||
{'>'}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
}
|
128
packages/react-docs/src/ts/components/type_definition.tsx
Normal file
128
packages/react-docs/src/ts/components/type_definition.tsx
Normal file
@@ -0,0 +1,128 @@
|
||||
import { AnchorTitle, colors, HeaderSizes } from '@0xproject/react-shared';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { CustomType, CustomTypeChild, KindString, TypeDocTypes } from '../types';
|
||||
import { utils } from '../utils/utils';
|
||||
|
||||
import { Comment } from './comment';
|
||||
import { CustomEnum } from './custom_enum';
|
||||
import { DocsInfo } from './docs_info';
|
||||
import { Enum } from './enum';
|
||||
import { Interface } from './interface';
|
||||
import { MethodSignature } from './method_signature';
|
||||
import { Type } from './type';
|
||||
|
||||
export interface TypeDefinitionProps {
|
||||
sectionName: string;
|
||||
customType: CustomType;
|
||||
shouldAddId?: boolean;
|
||||
docsInfo: DocsInfo;
|
||||
}
|
||||
|
||||
export interface TypeDefinitionState {
|
||||
shouldShowAnchor: boolean;
|
||||
}
|
||||
|
||||
export class TypeDefinition extends React.Component<TypeDefinitionProps, TypeDefinitionState> {
|
||||
public static defaultProps: Partial<TypeDefinitionProps> = {
|
||||
shouldAddId: true,
|
||||
};
|
||||
constructor(props: TypeDefinitionProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
shouldShowAnchor: false,
|
||||
};
|
||||
}
|
||||
public render() {
|
||||
const customType = this.props.customType;
|
||||
if (!this.props.docsInfo.isPublicType(customType.name)) {
|
||||
return null; // no-op
|
||||
}
|
||||
|
||||
let typePrefix: string;
|
||||
let codeSnippet: React.ReactNode;
|
||||
switch (customType.kindString) {
|
||||
case KindString.Interface:
|
||||
typePrefix = 'Interface';
|
||||
codeSnippet = (
|
||||
<Interface type={customType} sectionName={this.props.sectionName} docsInfo={this.props.docsInfo} />
|
||||
);
|
||||
break;
|
||||
|
||||
case KindString.Variable:
|
||||
typePrefix = 'Enum';
|
||||
codeSnippet = <CustomEnum type={customType} />;
|
||||
break;
|
||||
|
||||
case KindString.Enumeration:
|
||||
typePrefix = 'Enum';
|
||||
const enumValues = _.map(customType.children, (c: CustomTypeChild) => {
|
||||
return {
|
||||
name: c.name,
|
||||
defaultValue: c.defaultValue,
|
||||
};
|
||||
});
|
||||
codeSnippet = <Enum values={enumValues} />;
|
||||
break;
|
||||
|
||||
case KindString.TypeAlias:
|
||||
typePrefix = 'Type Alias';
|
||||
codeSnippet = (
|
||||
<span>
|
||||
<span style={{ color: colors.lightPurple }}>type</span> {customType.name} ={' '}
|
||||
{customType.type.typeDocType !== TypeDocTypes.Reflection ? (
|
||||
<Type
|
||||
type={customType.type}
|
||||
sectionName={this.props.sectionName}
|
||||
docsInfo={this.props.docsInfo}
|
||||
/>
|
||||
) : (
|
||||
<MethodSignature
|
||||
method={customType.type.method}
|
||||
sectionName={this.props.sectionName}
|
||||
shouldHideMethodName={true}
|
||||
shouldUseArrowSyntax={true}
|
||||
docsInfo={this.props.docsInfo}
|
||||
/>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw utils.spawnSwitchErr('type.kindString', customType.kindString);
|
||||
}
|
||||
|
||||
const typeDefinitionAnchorId = `${this.props.sectionName}-${customType.name}`;
|
||||
return (
|
||||
<div
|
||||
id={this.props.shouldAddId ? typeDefinitionAnchorId : ''}
|
||||
className="pb2"
|
||||
style={{ overflow: 'hidden', width: '100%' }}
|
||||
onMouseOver={this._setAnchorVisibility.bind(this, true)}
|
||||
onMouseOut={this._setAnchorVisibility.bind(this, false)}
|
||||
>
|
||||
<AnchorTitle
|
||||
headerSize={HeaderSizes.H3}
|
||||
title={`${typePrefix} ${customType.name}`}
|
||||
id={this.props.shouldAddId ? typeDefinitionAnchorId : ''}
|
||||
shouldShowAnchor={this.state.shouldShowAnchor}
|
||||
/>
|
||||
<div style={{ fontSize: 16 }}>
|
||||
<pre>
|
||||
<code className="hljs">{codeSnippet}</code>
|
||||
</pre>
|
||||
</div>
|
||||
<div style={{ maxWidth: 620 }}>
|
||||
{customType.comment && <Comment comment={customType.comment} className="py2" />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
private _setAnchorVisibility(shouldShowAnchor: boolean) {
|
||||
this.setState({
|
||||
shouldShowAnchor,
|
||||
});
|
||||
}
|
||||
}
|
7
packages/react-docs/src/ts/globals.d.ts
vendored
Normal file
7
packages/react-docs/src/ts/globals.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
declare module 'react-tooltip';
|
||||
|
||||
// compare-version declarations
|
||||
declare function compareVersions(firstVersion: string, secondVersion: string): number;
|
||||
declare module 'compare-versions' {
|
||||
export = compareVersions;
|
||||
}
|
20
packages/react-docs/src/ts/index.ts
Normal file
20
packages/react-docs/src/ts/index.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
export { Documentation } from './components/documentation';
|
||||
export { DocsInfo } from './components/docs_info';
|
||||
|
||||
// Exported to give users of this library added flexibility if they want to build
|
||||
// a docs page from scratch using the individual components.
|
||||
export { Badge } from './components/badge';
|
||||
export { Comment } from './components/comment';
|
||||
export { CustomEnum } from './components/custom_enum';
|
||||
export { Enum } from './components/enum';
|
||||
export { EventDefinition } from './components/event_definition';
|
||||
export { Interface } from './components/interface';
|
||||
export { MethodBlock } from './components/method_block';
|
||||
export { MethodSignature } from './components/method_signature';
|
||||
export { SourceLink } from './components/source_link';
|
||||
export { TypeDefinition } from './components/type_definition';
|
||||
export { Type } from './components/type';
|
||||
|
||||
export { DocsInfoConfig, DocAgnosticFormat, DoxityDocObj, DocsMenu, SupportedDocJson, TypeDocNode } from './types';
|
||||
|
||||
export { constants } from './utils/constants';
|
266
packages/react-docs/src/ts/types.ts
Normal file
266
packages/react-docs/src/ts/types.ts
Normal file
@@ -0,0 +1,266 @@
|
||||
export interface DocsInfoConfig {
|
||||
id: string;
|
||||
type: SupportedDocJson;
|
||||
displayName: string;
|
||||
packageUrl: string;
|
||||
menu: DocsMenu;
|
||||
sections: SectionsMap;
|
||||
sectionNameToMarkdown: { [sectionName: string]: string };
|
||||
visibleConstructors: string[];
|
||||
subPackageName?: string;
|
||||
publicTypes?: string[];
|
||||
sectionNameToModulePath?: { [sectionName: string]: string[] };
|
||||
menuSubsectionToVersionWhenIntroduced?: { [sectionName: string]: string };
|
||||
contractsByVersionByNetworkId?: ContractsByVersionByNetworkId;
|
||||
}
|
||||
|
||||
export interface DocsMenu {
|
||||
[sectionName: string]: string[];
|
||||
}
|
||||
|
||||
export interface SectionsMap {
|
||||
[sectionName: string]: string;
|
||||
}
|
||||
|
||||
export interface TypeDocType {
|
||||
type: TypeDocTypes;
|
||||
value: string;
|
||||
name: string;
|
||||
types: TypeDocType[];
|
||||
typeArguments?: TypeDocType[];
|
||||
declaration: TypeDocNode;
|
||||
elementType?: TypeDocType;
|
||||
}
|
||||
|
||||
export interface TypeDocFlags {
|
||||
isStatic?: boolean;
|
||||
isOptional?: boolean;
|
||||
isPublic?: boolean;
|
||||
}
|
||||
|
||||
export interface TypeDocGroup {
|
||||
title: string;
|
||||
children: number[];
|
||||
}
|
||||
|
||||
export interface TypeDocNode {
|
||||
id?: number;
|
||||
name?: string;
|
||||
kind?: string;
|
||||
defaultValue?: string;
|
||||
kindString?: string;
|
||||
type?: TypeDocType;
|
||||
fileName?: string;
|
||||
line?: number;
|
||||
comment?: TypeDocNode;
|
||||
text?: string;
|
||||
shortText?: string;
|
||||
returns?: string;
|
||||
declaration: TypeDocNode;
|
||||
flags?: TypeDocFlags;
|
||||
indexSignature?: TypeDocNode | TypeDocNode[]; // TypeDocNode in TypeDoc <V0.9.0, TypeDocNode[] in >V0.9.0
|
||||
signatures?: TypeDocNode[];
|
||||
parameters?: TypeDocNode[];
|
||||
typeParameter?: TypeDocNode[];
|
||||
sources?: TypeDocNode[];
|
||||
children?: TypeDocNode[];
|
||||
groups?: TypeDocGroup[];
|
||||
}
|
||||
|
||||
export enum TypeDocTypes {
|
||||
Intrinsic = 'intrinsic',
|
||||
Reference = 'reference',
|
||||
Array = 'array',
|
||||
StringLiteral = 'stringLiteral',
|
||||
Reflection = 'reflection',
|
||||
Union = 'union',
|
||||
TypeParameter = 'typeParameter',
|
||||
Intersection = 'intersection',
|
||||
Unknown = 'unknown',
|
||||
}
|
||||
|
||||
// Exception: We don't make the values uppercase because these KindString's need to
|
||||
// match up those returned by TypeDoc
|
||||
export enum KindString {
|
||||
Constructor = 'Constructor',
|
||||
Property = 'Property',
|
||||
Method = 'Method',
|
||||
Interface = 'Interface',
|
||||
TypeAlias = 'Type alias',
|
||||
Variable = 'Variable',
|
||||
Function = 'Function',
|
||||
Enumeration = 'Enumeration',
|
||||
}
|
||||
|
||||
export interface DocAgnosticFormat {
|
||||
[sectionName: string]: DocSection;
|
||||
}
|
||||
|
||||
export interface DocSection {
|
||||
comment: string;
|
||||
constructors: Array<TypescriptMethod | SolidityMethod>;
|
||||
methods: Array<TypescriptMethod | SolidityMethod>;
|
||||
properties: Property[];
|
||||
types: CustomType[];
|
||||
events?: Event[];
|
||||
}
|
||||
|
||||
export interface TypescriptMethod extends BaseMethod {
|
||||
source?: Source;
|
||||
isStatic?: boolean;
|
||||
typeParameter?: TypeParameter;
|
||||
}
|
||||
|
||||
export interface SolidityMethod extends BaseMethod {
|
||||
isConstant?: boolean;
|
||||
isPayable?: boolean;
|
||||
}
|
||||
|
||||
export interface Source {
|
||||
fileName: string;
|
||||
line: number;
|
||||
}
|
||||
|
||||
export interface Parameter {
|
||||
name: string;
|
||||
comment: string;
|
||||
isOptional: boolean;
|
||||
type: Type;
|
||||
}
|
||||
|
||||
export interface TypeParameter {
|
||||
name: string;
|
||||
type: Type;
|
||||
}
|
||||
|
||||
export interface Type {
|
||||
name: string;
|
||||
typeDocType: TypeDocTypes;
|
||||
value?: string;
|
||||
typeArguments?: Type[];
|
||||
elementType?: ElementType;
|
||||
types?: Type[];
|
||||
method?: TypescriptMethod;
|
||||
}
|
||||
|
||||
export interface ElementType {
|
||||
name: string;
|
||||
typeDocType: TypeDocTypes;
|
||||
}
|
||||
|
||||
export interface IndexSignature {
|
||||
keyName: string;
|
||||
keyType: Type;
|
||||
valueName: string;
|
||||
}
|
||||
|
||||
export interface CustomType {
|
||||
name: string;
|
||||
kindString: string;
|
||||
type?: Type;
|
||||
method?: TypescriptMethod;
|
||||
indexSignature?: IndexSignature;
|
||||
defaultValue?: string;
|
||||
comment?: string;
|
||||
children?: CustomTypeChild[];
|
||||
}
|
||||
|
||||
export interface CustomTypeChild {
|
||||
name: string;
|
||||
type?: Type;
|
||||
defaultValue?: string;
|
||||
}
|
||||
|
||||
export interface Event {
|
||||
name: string;
|
||||
eventArgs: EventArg[];
|
||||
}
|
||||
|
||||
export interface EventArg {
|
||||
isIndexed: boolean;
|
||||
name: string;
|
||||
type: Type;
|
||||
}
|
||||
|
||||
export interface Property {
|
||||
name: string;
|
||||
type: Type;
|
||||
source?: Source;
|
||||
comment?: string;
|
||||
}
|
||||
|
||||
export interface BaseMethod {
|
||||
isConstructor: boolean;
|
||||
name: string;
|
||||
returnComment?: string | undefined;
|
||||
callPath: string;
|
||||
parameters: Parameter[];
|
||||
returnType: Type;
|
||||
comment?: string;
|
||||
}
|
||||
|
||||
export interface TypeDefinitionByName {
|
||||
[typeName: string]: CustomType;
|
||||
}
|
||||
|
||||
export enum SupportedDocJson {
|
||||
Doxity = 'DOXITY',
|
||||
TypeDoc = 'TYPEDOC',
|
||||
}
|
||||
|
||||
export interface ContractsByVersionByNetworkId {
|
||||
[version: string]: {
|
||||
[networkName: string]: {
|
||||
[contractName: string]: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface DoxityDocObj {
|
||||
[contractName: string]: DoxityContractObj;
|
||||
}
|
||||
|
||||
export interface DoxityContractObj {
|
||||
title: string;
|
||||
fileName: string;
|
||||
name: string;
|
||||
abiDocs: DoxityAbiDoc[];
|
||||
}
|
||||
|
||||
export interface DoxityAbiDoc {
|
||||
constant: boolean;
|
||||
inputs: DoxityInput[];
|
||||
name: string;
|
||||
outputs: DoxityOutput[];
|
||||
payable: boolean;
|
||||
type: string;
|
||||
details?: string;
|
||||
return?: string;
|
||||
}
|
||||
|
||||
export interface DoxityOutput {
|
||||
name: string;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface DoxityInput {
|
||||
name: string;
|
||||
type: string;
|
||||
description: string;
|
||||
indexed?: boolean;
|
||||
}
|
||||
|
||||
export interface AddressByContractName {
|
||||
[contractName: string]: string;
|
||||
}
|
||||
|
||||
export interface EnumValue {
|
||||
name: string;
|
||||
defaultValue?: string;
|
||||
}
|
||||
|
||||
export enum AbiTypes {
|
||||
Constructor = 'constructor',
|
||||
Function = 'function',
|
||||
Event = 'event',
|
||||
}
|
9
packages/react-docs/src/ts/utils/constants.ts
Normal file
9
packages/react-docs/src/ts/utils/constants.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export const constants = {
|
||||
TYPES_SECTION_NAME: 'types',
|
||||
URL_WEB3_DOCS: 'https://github.com/ethereum/wiki/wiki/JavaScript-API',
|
||||
URL_WEB3_DECODED_LOG_ENTRY_EVENT:
|
||||
'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L123',
|
||||
URL_WEB3_LOG_ENTRY_EVENT: 'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L127',
|
||||
URL_WEB3_PROVIDER_DOCS: 'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L150',
|
||||
URL_BIGNUMBERJS_GITHUB: 'http://mikemcl.github.io/bignumber.js',
|
||||
};
|
175
packages/react-docs/src/ts/utils/doxity_utils.ts
Normal file
175
packages/react-docs/src/ts/utils/doxity_utils.ts
Normal file
@@ -0,0 +1,175 @@
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {
|
||||
AbiTypes,
|
||||
DocAgnosticFormat,
|
||||
DocSection,
|
||||
DoxityAbiDoc,
|
||||
DoxityContractObj,
|
||||
DoxityDocObj,
|
||||
DoxityInput,
|
||||
EventArg,
|
||||
Parameter,
|
||||
Property,
|
||||
SolidityMethod,
|
||||
Type,
|
||||
TypeDocTypes,
|
||||
} from '../types';
|
||||
|
||||
export const doxityUtils = {
|
||||
convertToDocAgnosticFormat(doxityDocObj: DoxityDocObj): DocAgnosticFormat {
|
||||
const docAgnosticFormat: DocAgnosticFormat = {};
|
||||
_.each(doxityDocObj, (doxityContractObj: DoxityContractObj, contractName: string) => {
|
||||
const doxityConstructor = _.find(doxityContractObj.abiDocs, (abiDoc: DoxityAbiDoc) => {
|
||||
return abiDoc.type === AbiTypes.Constructor;
|
||||
});
|
||||
const constructors = [];
|
||||
if (!_.isUndefined(doxityConstructor)) {
|
||||
const constructor = {
|
||||
isConstructor: true,
|
||||
name: doxityContractObj.name,
|
||||
comment: doxityConstructor.details,
|
||||
returnComment: doxityConstructor.return,
|
||||
callPath: '',
|
||||
parameters: this._convertParameters(doxityConstructor.inputs),
|
||||
returnType: this._convertType(doxityContractObj.name),
|
||||
};
|
||||
constructors.push(constructor);
|
||||
}
|
||||
|
||||
const doxityMethods: DoxityAbiDoc[] = _.filter<DoxityAbiDoc>(
|
||||
doxityContractObj.abiDocs,
|
||||
(abiDoc: DoxityAbiDoc) => {
|
||||
return this._isMethod(abiDoc);
|
||||
},
|
||||
);
|
||||
const methods: SolidityMethod[] = _.map<DoxityAbiDoc, SolidityMethod>(
|
||||
doxityMethods,
|
||||
(doxityMethod: DoxityAbiDoc) => {
|
||||
const outputs = !_.isUndefined(doxityMethod.outputs) ? doxityMethod.outputs : [];
|
||||
let returnTypeIfExists: Type;
|
||||
if (outputs.length === 0) {
|
||||
// no-op. It's already undefined
|
||||
} else if (outputs.length === 1) {
|
||||
const outputsType = outputs[0].type;
|
||||
returnTypeIfExists = this._convertType(outputsType);
|
||||
} else {
|
||||
const outputsType = `[${_.map(outputs, output => output.type).join(', ')}]`;
|
||||
returnTypeIfExists = this._convertType(outputsType);
|
||||
}
|
||||
// For ZRXToken, we want to convert it to zrxToken, rather then simply zRXToken
|
||||
const callPath =
|
||||
contractName !== 'ZRXToken'
|
||||
? `${contractName[0].toLowerCase()}${contractName.slice(1)}.`
|
||||
: `${contractName.slice(0, 3).toLowerCase()}${contractName.slice(3)}.`;
|
||||
const method = {
|
||||
isConstructor: false,
|
||||
isConstant: doxityMethod.constant,
|
||||
isPayable: doxityMethod.payable,
|
||||
name: doxityMethod.name,
|
||||
comment: doxityMethod.details,
|
||||
returnComment: doxityMethod.return,
|
||||
callPath,
|
||||
parameters: this._convertParameters(doxityMethod.inputs),
|
||||
returnType: returnTypeIfExists,
|
||||
};
|
||||
return method;
|
||||
},
|
||||
);
|
||||
|
||||
const doxityProperties: DoxityAbiDoc[] = _.filter<DoxityAbiDoc>(
|
||||
doxityContractObj.abiDocs,
|
||||
(abiDoc: DoxityAbiDoc) => {
|
||||
return this._isProperty(abiDoc);
|
||||
},
|
||||
);
|
||||
const properties = _.map<DoxityAbiDoc, Property>(doxityProperties, (doxityProperty: DoxityAbiDoc) => {
|
||||
// We assume that none of our functions return more then a single return value
|
||||
let typeName = doxityProperty.outputs[0].type;
|
||||
if (!_.isEmpty(doxityProperty.inputs)) {
|
||||
// Properties never have more then a single input
|
||||
typeName = `(${doxityProperty.inputs[0].type} => ${typeName})`;
|
||||
}
|
||||
const property = {
|
||||
name: doxityProperty.name,
|
||||
type: this._convertType(typeName),
|
||||
comment: doxityProperty.details,
|
||||
};
|
||||
return property;
|
||||
});
|
||||
|
||||
const doxityEvents = _.filter(
|
||||
doxityContractObj.abiDocs,
|
||||
(abiDoc: DoxityAbiDoc) => abiDoc.type === AbiTypes.Event,
|
||||
);
|
||||
const events = _.map(doxityEvents, doxityEvent => {
|
||||
const event = {
|
||||
name: doxityEvent.name,
|
||||
eventArgs: this._convertEventArgs(doxityEvent.inputs),
|
||||
};
|
||||
return event;
|
||||
});
|
||||
|
||||
const docSection: DocSection = {
|
||||
comment: doxityContractObj.title,
|
||||
constructors,
|
||||
methods,
|
||||
properties,
|
||||
types: [],
|
||||
events,
|
||||
};
|
||||
docAgnosticFormat[contractName] = docSection;
|
||||
});
|
||||
return docAgnosticFormat;
|
||||
},
|
||||
_convertParameters(inputs: DoxityInput[]): Parameter[] {
|
||||
const parameters = _.map(inputs, input => {
|
||||
const parameter = {
|
||||
name: input.name,
|
||||
comment: input.description,
|
||||
isOptional: false,
|
||||
type: this._convertType(input.type),
|
||||
};
|
||||
return parameter;
|
||||
});
|
||||
return parameters;
|
||||
},
|
||||
_convertType(typeName: string): Type {
|
||||
const type = {
|
||||
name: typeName,
|
||||
typeDocType: TypeDocTypes.Intrinsic,
|
||||
};
|
||||
return type;
|
||||
},
|
||||
_isMethod(abiDoc: DoxityAbiDoc) {
|
||||
if (abiDoc.type !== AbiTypes.Function) {
|
||||
return false;
|
||||
}
|
||||
const hasInputs = !_.isEmpty(abiDoc.inputs);
|
||||
const hasNamedOutputIfExists = !hasInputs || !_.isEmpty(abiDoc.inputs[0].name);
|
||||
const isNameAllCaps = abiDoc.name === abiDoc.name.toUpperCase();
|
||||
const isMethod = hasNamedOutputIfExists && !isNameAllCaps;
|
||||
return isMethod;
|
||||
},
|
||||
_isProperty(abiDoc: DoxityAbiDoc) {
|
||||
if (abiDoc.type !== AbiTypes.Function) {
|
||||
return false;
|
||||
}
|
||||
const hasInputs = !_.isEmpty(abiDoc.inputs);
|
||||
const hasNamedOutputIfExists = !hasInputs || !_.isEmpty(abiDoc.inputs[0].name);
|
||||
const isNameAllCaps = abiDoc.name === abiDoc.name.toUpperCase();
|
||||
const isProperty = !hasNamedOutputIfExists || isNameAllCaps;
|
||||
return isProperty;
|
||||
},
|
||||
_convertEventArgs(inputs: DoxityInput[]): EventArg[] {
|
||||
const eventArgs = _.map(inputs, input => {
|
||||
const eventArg = {
|
||||
isIndexed: input.indexed,
|
||||
name: input.name,
|
||||
type: this._convertType(input.type),
|
||||
};
|
||||
return eventArg;
|
||||
});
|
||||
return eventArgs;
|
||||
},
|
||||
};
|
370
packages/react-docs/src/ts/utils/typedoc_utils.ts
Normal file
370
packages/react-docs/src/ts/utils/typedoc_utils.ts
Normal file
@@ -0,0 +1,370 @@
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { DocsInfo } from '../components/docs_info';
|
||||
import {
|
||||
CustomType,
|
||||
CustomTypeChild,
|
||||
DocAgnosticFormat,
|
||||
DocSection,
|
||||
IndexSignature,
|
||||
KindString,
|
||||
Parameter,
|
||||
Property,
|
||||
SectionsMap,
|
||||
Type,
|
||||
TypeDocNode,
|
||||
TypeDocType,
|
||||
TypeParameter,
|
||||
TypescriptMethod,
|
||||
} from '../types';
|
||||
import { utils } from '../utils/utils';
|
||||
|
||||
export const typeDocUtils = {
|
||||
isType(entity: TypeDocNode): boolean {
|
||||
return (
|
||||
entity.kindString === KindString.Interface ||
|
||||
entity.kindString === KindString.Function ||
|
||||
entity.kindString === KindString.TypeAlias ||
|
||||
entity.kindString === KindString.Variable ||
|
||||
entity.kindString === KindString.Enumeration
|
||||
);
|
||||
},
|
||||
isMethod(entity: TypeDocNode): boolean {
|
||||
return entity.kindString === KindString.Method;
|
||||
},
|
||||
isConstructor(entity: TypeDocNode): boolean {
|
||||
return entity.kindString === KindString.Constructor;
|
||||
},
|
||||
isProperty(entity: TypeDocNode): boolean {
|
||||
return entity.kindString === KindString.Property;
|
||||
},
|
||||
isPrivateOrProtectedProperty(propertyName: string): boolean {
|
||||
return _.startsWith(propertyName, '_');
|
||||
},
|
||||
getModuleDefinitionsBySectionName(versionDocObj: TypeDocNode, configModulePaths: string[]): TypeDocNode[] {
|
||||
const moduleDefinitions: TypeDocNode[] = [];
|
||||
const jsonModules = versionDocObj.children;
|
||||
_.each(jsonModules, jsonMod => {
|
||||
_.each(configModulePaths, configModulePath => {
|
||||
if (_.includes(configModulePath, jsonMod.name)) {
|
||||
moduleDefinitions.push(jsonMod);
|
||||
}
|
||||
});
|
||||
});
|
||||
return moduleDefinitions;
|
||||
},
|
||||
convertToDocAgnosticFormat(typeDocJson: TypeDocNode, docsInfo: DocsInfo): DocAgnosticFormat {
|
||||
const subMenus = _.values(docsInfo.getMenu());
|
||||
const orderedSectionNames = _.flatten(subMenus);
|
||||
const docAgnosticFormat: DocAgnosticFormat = {};
|
||||
_.each(orderedSectionNames, sectionName => {
|
||||
const modulePathsIfExists = docsInfo.getModulePathsIfExists(sectionName);
|
||||
if (_.isUndefined(modulePathsIfExists)) {
|
||||
return; // no-op
|
||||
}
|
||||
const packageDefinitions = typeDocUtils.getModuleDefinitionsBySectionName(typeDocJson, modulePathsIfExists);
|
||||
let packageDefinitionWithMergedChildren;
|
||||
if (_.isEmpty(packageDefinitions)) {
|
||||
return; // no-op
|
||||
} else if (packageDefinitions.length === 1) {
|
||||
packageDefinitionWithMergedChildren = packageDefinitions[0];
|
||||
} else {
|
||||
// HACK: For now, if there are two modules to display in a single section,
|
||||
// we simply concat the children. This works for our limited use-case where
|
||||
// we want to display types stored in two files under a single section
|
||||
packageDefinitionWithMergedChildren = packageDefinitions[0];
|
||||
for (let i = 1; i < packageDefinitions.length; i++) {
|
||||
packageDefinitionWithMergedChildren.children = [
|
||||
...packageDefinitionWithMergedChildren.children,
|
||||
...packageDefinitions[i].children,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Since the `types.ts` file is the only file that does not export a module/class but
|
||||
// instead has each type export itself, we do not need to go down two levels of nesting
|
||||
// for it.
|
||||
let entities;
|
||||
let packageComment = '';
|
||||
if (sectionName === docsInfo.sections.types) {
|
||||
entities = packageDefinitionWithMergedChildren.children;
|
||||
} else {
|
||||
entities = packageDefinitionWithMergedChildren.children[0].children;
|
||||
const commentObj = packageDefinitionWithMergedChildren.children[0].comment;
|
||||
packageComment = !_.isUndefined(commentObj) ? commentObj.shortText : packageComment;
|
||||
}
|
||||
|
||||
const docSection = typeDocUtils._convertEntitiesToDocSection(entities, docsInfo, sectionName);
|
||||
docSection.comment = packageComment;
|
||||
docAgnosticFormat[sectionName] = docSection;
|
||||
});
|
||||
return docAgnosticFormat;
|
||||
},
|
||||
_convertEntitiesToDocSection(entities: TypeDocNode[], docsInfo: DocsInfo, sectionName: string) {
|
||||
const docSection: DocSection = {
|
||||
comment: '',
|
||||
constructors: [],
|
||||
methods: [],
|
||||
properties: [],
|
||||
types: [],
|
||||
};
|
||||
|
||||
let isConstructor;
|
||||
_.each(entities, entity => {
|
||||
switch (entity.kindString) {
|
||||
case KindString.Constructor:
|
||||
isConstructor = true;
|
||||
const constructor = typeDocUtils._convertMethod(
|
||||
entity,
|
||||
isConstructor,
|
||||
docsInfo.sections,
|
||||
sectionName,
|
||||
docsInfo.id,
|
||||
);
|
||||
docSection.constructors.push(constructor);
|
||||
break;
|
||||
|
||||
case KindString.Method:
|
||||
if (entity.flags.isPublic) {
|
||||
isConstructor = false;
|
||||
const method = typeDocUtils._convertMethod(
|
||||
entity,
|
||||
isConstructor,
|
||||
docsInfo.sections,
|
||||
sectionName,
|
||||
docsInfo.id,
|
||||
);
|
||||
docSection.methods.push(method);
|
||||
}
|
||||
break;
|
||||
|
||||
case KindString.Property:
|
||||
if (!typeDocUtils.isPrivateOrProtectedProperty(entity.name)) {
|
||||
const property = typeDocUtils._convertProperty(
|
||||
entity,
|
||||
docsInfo.sections,
|
||||
sectionName,
|
||||
docsInfo.id,
|
||||
);
|
||||
docSection.properties.push(property);
|
||||
}
|
||||
break;
|
||||
|
||||
case KindString.Interface:
|
||||
case KindString.Function:
|
||||
case KindString.Variable:
|
||||
case KindString.Enumeration:
|
||||
case KindString.TypeAlias:
|
||||
if (docsInfo.isPublicType(entity.name)) {
|
||||
const customType = typeDocUtils._convertCustomType(
|
||||
entity,
|
||||
docsInfo.sections,
|
||||
sectionName,
|
||||
docsInfo.id,
|
||||
);
|
||||
docSection.types.push(customType);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw utils.spawnSwitchErr('kindString', entity.kindString);
|
||||
}
|
||||
});
|
||||
return docSection;
|
||||
},
|
||||
_convertCustomType(entity: TypeDocNode, sections: SectionsMap, sectionName: string, docId: string): CustomType {
|
||||
const typeIfExists = !_.isUndefined(entity.type)
|
||||
? typeDocUtils._convertType(entity.type, sections, sectionName, docId)
|
||||
: undefined;
|
||||
const isConstructor = false;
|
||||
const methodIfExists = !_.isUndefined(entity.declaration)
|
||||
? typeDocUtils._convertMethod(entity.declaration, isConstructor, sections, sectionName, docId)
|
||||
: undefined;
|
||||
const doesIndexSignatureExist = !_.isUndefined(entity.indexSignature);
|
||||
const isIndexSignatureArray = _.isArray(entity.indexSignature);
|
||||
// HACK: TypeDoc Versions <0.9.0 indexSignature is of type TypeDocNode[]
|
||||
// Versions >0.9.0 have it as type TypeDocNode
|
||||
const indexSignature =
|
||||
doesIndexSignatureExist && isIndexSignatureArray
|
||||
? (entity.indexSignature as TypeDocNode[])[0]
|
||||
: (entity.indexSignature as TypeDocNode);
|
||||
const indexSignatureIfExists = doesIndexSignatureExist
|
||||
? typeDocUtils._convertIndexSignature(indexSignature, sections, sectionName, docId)
|
||||
: undefined;
|
||||
const commentIfExists =
|
||||
!_.isUndefined(entity.comment) && !_.isUndefined(entity.comment.shortText)
|
||||
? entity.comment.shortText
|
||||
: undefined;
|
||||
|
||||
const childrenIfExist = !_.isUndefined(entity.children)
|
||||
? _.map(entity.children, (child: TypeDocNode) => {
|
||||
const childTypeIfExists = !_.isUndefined(child.type)
|
||||
? typeDocUtils._convertType(child.type, sections, sectionName, docId)
|
||||
: undefined;
|
||||
const c: CustomTypeChild = {
|
||||
name: child.name,
|
||||
type: childTypeIfExists,
|
||||
defaultValue: child.defaultValue,
|
||||
};
|
||||
return c;
|
||||
})
|
||||
: undefined;
|
||||
|
||||
const customType = {
|
||||
name: entity.name,
|
||||
kindString: entity.kindString,
|
||||
type: typeIfExists,
|
||||
method: methodIfExists,
|
||||
indexSignature: indexSignatureIfExists,
|
||||
defaultValue: entity.defaultValue,
|
||||
comment: commentIfExists,
|
||||
children: childrenIfExist,
|
||||
};
|
||||
return customType;
|
||||
},
|
||||
_convertIndexSignature(
|
||||
entity: TypeDocNode,
|
||||
sections: SectionsMap,
|
||||
sectionName: string,
|
||||
docId: string,
|
||||
): IndexSignature {
|
||||
const key = entity.parameters[0];
|
||||
const indexSignature = {
|
||||
keyName: key.name,
|
||||
keyType: typeDocUtils._convertType(key.type, sections, sectionName, docId),
|
||||
valueName: entity.type.name,
|
||||
};
|
||||
return indexSignature;
|
||||
},
|
||||
_convertProperty(entity: TypeDocNode, sections: SectionsMap, sectionName: string, docId: string): Property {
|
||||
const source = entity.sources[0];
|
||||
const commentIfExists = !_.isUndefined(entity.comment) ? entity.comment.shortText : undefined;
|
||||
const property = {
|
||||
name: entity.name,
|
||||
type: typeDocUtils._convertType(entity.type, sections, sectionName, docId),
|
||||
source: {
|
||||
fileName: source.fileName,
|
||||
line: source.line,
|
||||
},
|
||||
comment: commentIfExists,
|
||||
};
|
||||
return property;
|
||||
},
|
||||
_convertMethod(
|
||||
entity: TypeDocNode,
|
||||
isConstructor: boolean,
|
||||
sections: SectionsMap,
|
||||
sectionName: string,
|
||||
docId: string,
|
||||
): TypescriptMethod {
|
||||
const signature = entity.signatures[0];
|
||||
const source = entity.sources[0];
|
||||
const hasComment = !_.isUndefined(signature.comment);
|
||||
const isStatic = _.isUndefined(entity.flags.isStatic) ? false : entity.flags.isStatic;
|
||||
|
||||
// HACK: we use the fact that the sectionName is the same as the property name at the top-level
|
||||
// of the public interface. In the future, we shouldn't use this hack but rather get it from the JSON.
|
||||
let callPath;
|
||||
if (isConstructor || entity.name === '__type') {
|
||||
callPath = '';
|
||||
// TODO: Get rid of this 0x-specific logic
|
||||
} else if (docId === 'ZERO_EX_JS') {
|
||||
const topLevelInterface = isStatic ? 'ZeroEx.' : 'zeroEx.';
|
||||
callPath =
|
||||
!_.isUndefined(sections.zeroEx) && sectionName !== sections.zeroEx
|
||||
? `${topLevelInterface}${sectionName}.`
|
||||
: topLevelInterface;
|
||||
} else {
|
||||
callPath = `${sectionName}.`;
|
||||
}
|
||||
|
||||
const parameters = _.map(signature.parameters, param => {
|
||||
return typeDocUtils._convertParameter(param, sections, sectionName, docId);
|
||||
});
|
||||
const returnType = typeDocUtils._convertType(signature.type, sections, sectionName, docId);
|
||||
const typeParameter = _.isUndefined(signature.typeParameter)
|
||||
? undefined
|
||||
: typeDocUtils._convertTypeParameter(signature.typeParameter[0], sections, sectionName, docId);
|
||||
|
||||
const method = {
|
||||
isConstructor,
|
||||
isStatic,
|
||||
name: signature.name,
|
||||
comment: hasComment ? signature.comment.shortText : undefined,
|
||||
returnComment: hasComment && signature.comment.returns ? signature.comment.returns : undefined,
|
||||
source: {
|
||||
fileName: source.fileName,
|
||||
line: source.line,
|
||||
},
|
||||
callPath,
|
||||
parameters,
|
||||
returnType,
|
||||
typeParameter,
|
||||
};
|
||||
return method;
|
||||
},
|
||||
_convertTypeParameter(
|
||||
entity: TypeDocNode,
|
||||
sections: SectionsMap,
|
||||
sectionName: string,
|
||||
docId: string,
|
||||
): TypeParameter {
|
||||
const type = typeDocUtils._convertType(entity.type, sections, sectionName, docId);
|
||||
const parameter = {
|
||||
name: entity.name,
|
||||
type,
|
||||
};
|
||||
return parameter;
|
||||
},
|
||||
_convertParameter(entity: TypeDocNode, sections: SectionsMap, sectionName: string, docId: string): Parameter {
|
||||
let comment = '<No comment>';
|
||||
if (entity.comment && entity.comment.shortText) {
|
||||
comment = entity.comment.shortText;
|
||||
} else if (entity.comment && entity.comment.text) {
|
||||
comment = entity.comment.text;
|
||||
}
|
||||
|
||||
const isOptional = !_.isUndefined(entity.flags.isOptional) ? entity.flags.isOptional : false;
|
||||
|
||||
const type = typeDocUtils._convertType(entity.type, sections, sectionName, docId);
|
||||
|
||||
const parameter = {
|
||||
name: entity.name,
|
||||
comment,
|
||||
isOptional,
|
||||
type,
|
||||
};
|
||||
return parameter;
|
||||
},
|
||||
_convertType(entity: TypeDocType, sections: SectionsMap, sectionName: string, docId: string): Type {
|
||||
const typeArguments = _.map(entity.typeArguments, typeArgument => {
|
||||
return typeDocUtils._convertType(typeArgument, sections, sectionName, docId);
|
||||
});
|
||||
const types = _.map(entity.types, t => {
|
||||
return typeDocUtils._convertType(t, sections, sectionName, docId);
|
||||
});
|
||||
|
||||
const isConstructor = false;
|
||||
const methodIfExists = !_.isUndefined(entity.declaration)
|
||||
? typeDocUtils._convertMethod(entity.declaration, isConstructor, sections, sectionName, docId)
|
||||
: undefined;
|
||||
|
||||
const elementTypeIfExists = !_.isUndefined(entity.elementType)
|
||||
? {
|
||||
name: entity.elementType.name,
|
||||
typeDocType: entity.elementType.type,
|
||||
}
|
||||
: undefined;
|
||||
|
||||
const type = {
|
||||
name: entity.name,
|
||||
value: entity.value,
|
||||
typeDocType: entity.type,
|
||||
typeArguments,
|
||||
elementType: elementTypeIfExists,
|
||||
types,
|
||||
method: methodIfExists,
|
||||
};
|
||||
return type;
|
||||
},
|
||||
};
|
10
packages/react-docs/src/ts/utils/utils.ts
Normal file
10
packages/react-docs/src/ts/utils/utils.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export const utils = {
|
||||
consoleLog(message: string) {
|
||||
/* tslint:disable */
|
||||
console.log(message);
|
||||
/* tslint:enable */
|
||||
},
|
||||
spawnSwitchErr(name: string, value: any) {
|
||||
return new Error(`Unexpected switch value: ${value} encountered for ${name}`);
|
||||
},
|
||||
};
|
14
packages/react-docs/tsconfig.json
Normal file
14
packages/react-docs/tsconfig.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"extends": "../../tsconfig",
|
||||
"compilerOptions": {
|
||||
"outDir": "./lib/",
|
||||
"jsx": "react",
|
||||
"baseUrl": "./",
|
||||
"strictNullChecks": false,
|
||||
"noImplicitThis": false,
|
||||
"paths": {
|
||||
"*": ["node_modules/@types/*", "*"]
|
||||
}
|
||||
},
|
||||
"include": ["./src/ts/**/*"]
|
||||
}
|
9
packages/react-docs/tslint.json
Normal file
9
packages/react-docs/tslint.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": ["@0xproject/tslint-config"],
|
||||
"rules": {
|
||||
"no-implicit-dependencies": false,
|
||||
"no-object-literal-type-assertion": false,
|
||||
"completed-docs": false,
|
||||
"prefer-function-over-method": false
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user