diff options
author | Fabio Berger <me@fabioberger.com> | 2017-11-29 06:06:09 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-29 06:06:09 +0800 |
commit | e71c7fdb16b3477e75c10d349ebeccab394ef9b1 (patch) | |
tree | 34cf4b44c4d70e10d55ea242e61b7ecce4e071d5 /packages/website | |
parent | 840557be0dd8466aa6a49a8fa3e0ff8d1850f323 (diff) | |
parent | 4258e6dab18a7149d199bcbcb55b83a29f42bca0 (diff) | |
download | dexon-0x-contracts-e71c7fdb16b3477e75c10d349ebeccab394ef9b1.tar.gz dexon-0x-contracts-e71c7fdb16b3477e75c10d349ebeccab394ef9b1.tar.zst dexon-0x-contracts-e71c7fdb16b3477e75c10d349ebeccab394ef9b1.zip |
Merge pull request #243 from 0xProject/fix/refactorDocs
Refactor docs
Diffstat (limited to 'packages/website')
21 files changed, 548 insertions, 691 deletions
diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 38a2ef532..e71f61ead 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -643,7 +643,7 @@ export class Blockchain { // of the ZeroEx instance. private async postInstantiationOrUpdatingProviderZeroExAsync() { utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.'); - this.exchangeAddress = await this.zeroEx.exchange.getContractAddress(); + this.exchangeAddress = this.zeroEx.exchange.getContractAddress(); } private updateProviderName(injectedWeb3: Web3) { const doesInjectedWeb3Exist = !_.isUndefined(injectedWeb3); diff --git a/packages/website/ts/components/top_bar.tsx b/packages/website/ts/components/top_bar.tsx index a84f1324d..7b81253e2 100644 --- a/packages/website/ts/components/top_bar.tsx +++ b/packages/website/ts/components/top_bar.tsx @@ -15,8 +15,9 @@ import {PortalMenu} from 'ts/components/portal_menu'; import {TopBarMenuItem} from 'ts/components/top_bar_menu_item'; import {DropDownMenuItem} from 'ts/components/ui/drop_down_menu_item'; import {Identicon} from 'ts/components/ui/identicon'; +import {DocsInfo} from 'ts/pages/documentation/docs_info'; import {NestedSidebarMenu} from 'ts/pages/shared/nested_sidebar_menu'; -import {Docs, MenuSubsectionsBySection, Styles, TypeDocNode, WebsitePaths} from 'ts/types'; +import {DocsMenu, MenuSubsectionsBySection, Styles, TypeDocNode, WebsitePaths} from 'ts/types'; import {configs} from 'ts/utils/configs'; import {constants} from 'ts/utils/constants'; import {typeDocUtils} from 'ts/utils/typedoc_utils'; @@ -30,9 +31,10 @@ interface TopBarProps { location: Location; docsVersion?: string; availableDocVersions?: string[]; + menu?: DocsMenu; menuSubsectionsBySection?: MenuSubsectionsBySection; shouldFullWidth?: boolean; - doc?: Docs; + docPath?: string; style?: React.CSSProperties; isNightVersion?: boolean; } @@ -272,25 +274,21 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { ); } private renderDocsMenu() { - if (!this.isViewing0xjsDocs() && !this.isViewingSmartContractsDocs()) { + if (!this.isViewing0xjsDocs() && !this.isViewingSmartContractsDocs() || _.isUndefined(this.props.menu)) { return; } - const topLevelMenu = this.isViewing0xjsDocs() ? - typeDocUtils.getFinal0xjsMenu(this.props.docsVersion) : - constants.menuSmartContracts; - const sectionTitle = this.isViewing0xjsDocs() ? '0x.js Docs' : 'Smart contract Docs'; return ( <div className="lg-hide md-hide"> <div className="pl1 py1" style={{backgroundColor: SECTION_HEADER_COLOR}}>{sectionTitle}</div> <NestedSidebarMenu - topLevelMenu={topLevelMenu} + topLevelMenu={this.props.menu} menuSubsectionsBySection={this.props.menuSubsectionsBySection} shouldDisplaySectionHeaders={false} onMenuItemClick={this.onMenuButtonClick.bind(this)} selectedVersion={this.props.docsVersion} - doc={this.props.doc} + docPath={this.props.docPath} versions={this.props.availableDocVersions} /> </div> diff --git a/packages/website/ts/containers/smart_contracts_documentation.tsx b/packages/website/ts/containers/smart_contracts_documentation.tsx index ccf3c4a65..4623c976b 100644 --- a/packages/website/ts/containers/smart_contracts_documentation.tsx +++ b/packages/website/ts/containers/smart_contracts_documentation.tsx @@ -2,12 +2,54 @@ import * as _ from 'lodash'; import * as React from 'react'; import {connect} from 'react-redux'; import {Dispatch, Store as ReduxStore} from 'redux'; +import {DocsInfo} from 'ts/pages/documentation/docs_info'; import { - SmartContractsDocumentation as SmartContractsDocumentationComponent, - SmartContractsDocumentationAllProps, -} from 'ts/pages/documentation/smart_contracts_documentation'; + Documentation as DocumentationComponent, + DocumentationAllProps, +} from 'ts/pages/documentation/documentation'; import {Dispatcher} from 'ts/redux/dispatcher'; import {State} from 'ts/redux/reducer'; +import {DocsInfoConfig, WebsitePaths} from 'ts/types'; +import {constants} from 'ts/utils/constants'; +import {doxityUtils} from 'ts/utils/doxity_utils'; + +/* tslint:disable:no-var-requires */ +const IntroMarkdown = require('md/docs/smart_contracts/introduction'); +/* tslint:enable:no-var-requires */ + +const sections = constants.smartContractDocSections; + +const docsInfoConfig: DocsInfoConfig = { + packageName: '0x Smart Contracts', + packageUrl: 'https://github.com/0xProject/contracts', + websitePath: WebsitePaths.SmartContracts, + docsJsonRoot: 'https://s3.amazonaws.com/smart-contracts-docs-json', + menu: { + introduction: [ + sections.Introduction, + ], + contracts: [ + sections.Exchange, + sections.TokenRegistry, + sections.ZRXToken, + sections.EtherToken, + sections.TokenTransferProxy, + ], + }, + sectionNameToMarkdown: { + [sections.Introduction]: IntroMarkdown, + }, + sections, + visibleConstructors: [ + sections.Exchange, + sections.TokenRegistry, + sections.ZRXToken, + sections.EtherToken, + sections.TokenTransferProxy, + ], + convertToDocAgnosticFormatFn: doxityUtils.convertToDocAgnosticFormat.bind(doxityUtils), +}; +const docsInfo = new DocsInfo(docsInfoConfig); interface ConnectedState { docsVersion: string; @@ -16,16 +58,18 @@ interface ConnectedState { interface ConnectedDispatch { dispatcher: Dispatcher; + docsInfo: DocsInfo; } -const mapStateToProps = (state: State, ownProps: SmartContractsDocumentationAllProps): ConnectedState => ({ +const mapStateToProps = (state: State, ownProps: DocumentationAllProps): ConnectedState => ({ docsVersion: state.docsVersion, availableDocVersions: state.availableDocVersions, }); const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({ dispatcher: new Dispatcher(dispatch), + docsInfo, }); -export const SmartContractsDocumentation: React.ComponentClass<SmartContractsDocumentationAllProps> = - connect(mapStateToProps, mapDispatchToProps)(SmartContractsDocumentationComponent); +export const Documentation: React.ComponentClass<DocumentationAllProps> = + connect(mapStateToProps, mapDispatchToProps)(DocumentationComponent); diff --git a/packages/website/ts/containers/zero_ex_js_documentation.tsx b/packages/website/ts/containers/zero_ex_js_documentation.tsx index ecf0451c0..15a137de1 100644 --- a/packages/website/ts/containers/zero_ex_js_documentation.tsx +++ b/packages/website/ts/containers/zero_ex_js_documentation.tsx @@ -4,30 +4,165 @@ import * as React from 'react'; import {connect} from 'react-redux'; import {Dispatch, Store as ReduxStore} from 'redux'; import {Blockchain} from 'ts/blockchain'; +import {DocsInfo} from 'ts/pages/documentation/docs_info'; import { - ZeroExJSDocumentation as ZeroExJSDocumentationComponent, - ZeroExJSDocumentationAllProps, -} from 'ts/pages/documentation/zero_ex_js_documentation'; + Documentation as DocumentationComponent, + DocumentationAllProps, +} from 'ts/pages/documentation/documentation'; import {Dispatcher} from 'ts/redux/dispatcher'; import {State} from 'ts/redux/reducer'; +import {DocsInfoConfig, WebsitePaths} from 'ts/types'; +import {typeDocUtils} from 'ts/utils/typedoc_utils'; + +/* tslint:disable:no-var-requires */ +const IntroMarkdown = require('md/docs/0xjs/introduction'); +const InstallationMarkdown = require('md/docs/0xjs/installation'); +const AsyncMarkdown = require('md/docs/0xjs/async'); +const ErrorsMarkdown = require('md/docs/0xjs/errors'); +const versioningMarkdown = require('md/docs/0xjs/versioning'); +/* tslint:enable:no-var-requires */ + +const zeroExJsDocSections = { + introduction: 'introduction', + installation: 'installation', + testrpc: 'testrpc', + async: 'async', + errors: 'errors', + versioning: 'versioning', + zeroEx: 'zeroEx', + exchange: 'exchange', + token: 'token', + tokenRegistry: 'tokenRegistry', + etherToken: 'etherToken', + proxy: 'proxy', + types: 'types', +}; + +const docsInfoConfig: DocsInfoConfig = { + packageName: '0x.js', + packageUrl: 'https://github.com/0xProject/0x.js', + websitePath: WebsitePaths.ZeroExJs, + docsJsonRoot: 'https://s3.amazonaws.com/0xjs-docs-jsons', + menu: { + introduction: [ + zeroExJsDocSections.introduction, + ], + install: [ + zeroExJsDocSections.installation, + ], + topics: [ + zeroExJsDocSections.async, + zeroExJsDocSections.errors, + zeroExJsDocSections.versioning, + ], + zeroEx: [ + zeroExJsDocSections.zeroEx, + ], + contracts: [ + zeroExJsDocSections.exchange, + zeroExJsDocSections.token, + zeroExJsDocSections.tokenRegistry, + zeroExJsDocSections.etherToken, + zeroExJsDocSections.proxy, + ], + types: [ + zeroExJsDocSections.types, + ], + }, + sectionNameToMarkdown: { + [zeroExJsDocSections.introduction]: IntroMarkdown, + [zeroExJsDocSections.installation]: InstallationMarkdown, + [zeroExJsDocSections.async]: AsyncMarkdown, + [zeroExJsDocSections.errors]: ErrorsMarkdown, + [zeroExJsDocSections.versioning]: versioningMarkdown, + }, + // Note: This needs to be kept in sync with the types exported in index.ts. Unfortunately there is + // currently no way to extract the re-exported types from index.ts via TypeDoc :( + publicTypes: [ + 'Order', + 'SignedOrder', + 'ECSignature', + 'ZeroExError', + 'EventCallback', + 'EventCallbackAsync', + 'EventCallbackSync', + 'ExchangeContractErrs', + 'ContractEvent', + 'Token', + 'ExchangeEvents', + 'IndexedFilterValues', + 'SubscriptionOpts', + 'BlockParam', + 'OrderFillOrKillRequest', + 'OrderCancellationRequest', + 'OrderFillRequest', + 'ContractEventEmitter', + 'Web3Provider', + 'ContractEventArgs', + 'LogCancelArgs', + 'LogFillArgs', + 'LogErrorContractEventArgs', + 'LogFillContractEventArgs', + 'LogCancelContractEventArgs', + 'TokenEvents', + 'ExchangeContractEventArgs', + 'TransferContractEventArgs', + 'ApprovalContractEventArgs', + 'TokenContractEventArgs', + 'ZeroExConfig', + 'TransactionReceiptWithDecodedLogs', + 'LogWithDecodedArgs', + 'DecodedLogArgs', + 'MethodOpts', + 'ValidateOrderFillableOpts', + 'OrderTransactionOpts', + 'TransactionOpts', + 'ContractEventArg', + 'LogEvent', + 'LogEntry', + 'DecodedLogEvent', + ], + sectionNameToModulePath: { + [zeroExJsDocSections.zeroEx]: ['"src/0x"'], + [zeroExJsDocSections.exchange]: ['"src/contract_wrappers/exchange_wrapper"'], + [zeroExJsDocSections.tokenRegistry]: ['"src/contract_wrappers/token_registry_wrapper"'], + [zeroExJsDocSections.token]: ['"src/contract_wrappers/token_wrapper"'], + [zeroExJsDocSections.etherToken]: ['"src/contract_wrappers/ether_token_wrapper"'], + [zeroExJsDocSections.proxy]: [ + '"src/contract_wrappers/proxy_wrapper"', + '"src/contract_wrappers/token_transfer_proxy_wrapper"', + ], + [zeroExJsDocSections.types]: ['"src/types"'], + }, + menuSubsectionToVersionWhenIntroduced: { + [zeroExJsDocSections.etherToken]: '0.7.1', + [zeroExJsDocSections.proxy]: '0.8.0', + }, + sections: zeroExJsDocSections, + visibleConstructors: [zeroExJsDocSections.zeroEx], + convertToDocAgnosticFormatFn: typeDocUtils.convertToDocAgnosticFormat.bind(typeDocUtils), +}; +const docsInfo = new DocsInfo(docsInfoConfig); interface ConnectedState { docsVersion: string; availableDocVersions: string[]; + docsInfo: DocsInfo; } interface ConnectedDispatch { dispatcher: Dispatcher; } -const mapStateToProps = (state: State, ownProps: ZeroExJSDocumentationAllProps): ConnectedState => ({ +const mapStateToProps = (state: State, ownProps: DocumentationAllProps): ConnectedState => ({ docsVersion: state.docsVersion, availableDocVersions: state.availableDocVersions, + docsInfo, }); const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({ dispatcher: new Dispatcher(dispatch), }); -export const ZeroExJSDocumentation: React.ComponentClass<ZeroExJSDocumentationAllProps> = - connect(mapStateToProps, mapDispatchToProps)(ZeroExJSDocumentationComponent); +export const Documentation: React.ComponentClass<DocumentationAllProps> = + connect(mapStateToProps, mapDispatchToProps)(DocumentationComponent); diff --git a/packages/website/ts/index.tsx b/packages/website/ts/index.tsx index 67a4e0067..eb80a7119 100644 --- a/packages/website/ts/index.tsx +++ b/packages/website/ts/index.tsx @@ -78,11 +78,11 @@ const LazyPortal = createLazyComponent( 'Portal', async () => System.import<any>(/* webpackChunkName: "portal" */'ts/containers/portal'), ); const LazyZeroExJSDocumentation = createLazyComponent( - 'ZeroExJSDocumentation', + 'Documentation', async () => System.import<any>(/* webpackChunkName: "zeroExDocs" */'ts/containers/zero_ex_js_documentation'), ); const LazySmartContractsDocumentation = createLazyComponent( - 'SmartContractsDocumentation', + 'Documentation', async () => System.import<any>( /* webpackChunkName: "smartContractDocs" */'ts/containers/smart_contracts_documentation', ), diff --git a/packages/website/ts/lazy_component.tsx b/packages/website/ts/lazy_component.tsx index 1dfe4db95..359a1fe65 100644 --- a/packages/website/ts/lazy_component.tsx +++ b/packages/website/ts/lazy_component.tsx @@ -56,6 +56,9 @@ export const createLazyComponent = (componentName: string, lazyImport: () => Pro const reactComponentPromise = (async (): Promise<React.ComponentClass<any>> => { const mod = await lazyImport(); const component = mod[componentName]; + if (_.isUndefined(component)) { + throw new Error(`Did not find exported component: ${componentName}`); + } return component; })(); return ( diff --git a/packages/website/ts/pages/documentation/docs_info.ts b/packages/website/ts/pages/documentation/docs_info.ts new file mode 100644 index 000000000..f607c2185 --- /dev/null +++ b/packages/website/ts/pages/documentation/docs_info.ts @@ -0,0 +1,105 @@ +import compareVersions = require('compare-versions'); +import * as _ from 'lodash'; +import { + DocAgnosticFormat, + DocsInfoConfig, + DocsMenu, + DoxityDocObj, + MenuSubsectionsBySection, + SectionsMap, + TypeDocNode, +} from 'ts/types'; + +export class DocsInfo { + public packageName: string; + public packageUrl: string; + public websitePath: string; + public docsJsonRoot: string; + public menu: DocsMenu; + public sections: SectionsMap; + public sectionNameToMarkdown: {[sectionName: string]: string}; + private docsInfo: DocsInfoConfig; + constructor(config: DocsInfoConfig) { + this.packageName = config.packageName; + this.packageUrl = config.packageUrl; + this.websitePath = config.websitePath; + this.docsJsonRoot = config.docsJsonRoot; + this.sections = config.sections; + this.sectionNameToMarkdown = config.sectionNameToMarkdown; + 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); + 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 { + return this.docsInfo.convertToDocAgnosticFormatFn(docObj, this); + } +} diff --git a/packages/website/ts/pages/documentation/smart_contracts_documentation.tsx b/packages/website/ts/pages/documentation/documentation.tsx index 0d5751ffb..288a8f79c 100644 --- a/packages/website/ts/pages/documentation/smart_contracts_documentation.tsx +++ b/packages/website/ts/pages/documentation/documentation.tsx @@ -11,6 +11,7 @@ import semverSort = require('semver-sort'); import {TopBar} from 'ts/components/top_bar'; import {Badge} from 'ts/components/ui/badge'; import {Comment} from 'ts/pages/documentation/comment'; +import {DocsInfo} from 'ts/pages/documentation/docs_info'; import {EventDefinition} from 'ts/pages/documentation/event_definition'; import {MethodBlock} from 'ts/pages/documentation/method_block'; import {SourceLink} from 'ts/pages/documentation/source_link'; @@ -26,49 +27,46 @@ import { CustomType, DocAgnosticFormat, Docs, + DocsInfoConfig, DoxityDocObj, EtherscanLinkSuffixes, Event, MenuSubsectionsBySection, Networks, Property, - SmartContractsDocSections, SolidityMethod, Styles, TypeDefinitionByName, + TypeDocNode, + TypescriptMethod, + WebsitePaths, } from 'ts/types'; import {constants} from 'ts/utils/constants'; import {docUtils} from 'ts/utils/doc_utils'; -import {doxityUtils} from 'ts/utils/doxity_utils'; import {utils} from 'ts/utils/utils'; -/* tslint:disable:no-var-requires */ -const IntroMarkdown = require('md/docs/smart_contracts/introduction'); -/* tslint:enable:no-var-requires */ const SCROLL_TO_TIMEOUT = 500; +const SCROLL_TOP_ID = 'docsScrollTop'; const CUSTOM_PURPLE = '#690596'; const CUSTOM_RED = '#e91751'; const CUSTOM_TURQUOIS = '#058789'; -const DOC_JSON_ROOT = constants.S3_SMART_CONTRACTS_DOCUMENTATION_JSON_ROOT; -const sectionNameToMarkdown = { - [SmartContractsDocSections.Introduction]: IntroMarkdown, -}; const networkNameToColor: {[network: string]: string} = { [Networks.kovan]: CUSTOM_PURPLE, [Networks.ropsten]: CUSTOM_RED, [Networks.mainnet]: CUSTOM_TURQUOIS, }; -export interface SmartContractsDocumentationAllProps { +export interface DocumentationAllProps { source: string; location: Location; dispatcher: Dispatcher; docsVersion: string; availableDocVersions: string[]; + docsInfo: DocsInfo; } -interface SmartContractsDocumentationState { +interface DocumentationState { docAgnosticFormat?: DocAgnosticFormat; } @@ -91,9 +89,9 @@ const styles: Styles = { }, }; -export class SmartContractsDocumentation extends - React.Component<SmartContractsDocumentationAllProps, SmartContractsDocumentationState> { - constructor(props: SmartContractsDocumentationAllProps) { +export class Documentation extends + React.Component<DocumentationAllProps, DocumentationState> { + constructor(props: DocumentationAllProps) { super(props); this.state = { docAgnosticFormat: undefined, @@ -108,20 +106,21 @@ export class SmartContractsDocumentation extends this.fetchJSONDocsFireAndForgetAsync(preferredVersionIfExists); } public render() { - const menuSubsectionsBySection = _.isUndefined(this.state.docAgnosticFormat) - ? {} - : this.getMenuSubsectionsBySection(this.state.docAgnosticFormat); + const menuSubsectionsBySection = _.isUndefined(this.state.docAgnosticFormat) ? + {} : + this.props.docsInfo.getMenuSubsectionsBySection(this.state.docAgnosticFormat); return ( <div> - <DocumentTitle title="0x Smart Contract Documentation"/> + <DocumentTitle title={`${this.props.docsInfo.packageName} Documentation`}/> <TopBar blockchainIsLoaded={false} location={this.props.location} docsVersion={this.props.docsVersion} availableDocVersions={this.props.availableDocVersions} + menu={this.props.docsInfo.getMenu(this.props.docsVersion)} menuSubsectionsBySection={menuSubsectionsBySection} shouldFullWidth={true} - doc={Docs.SmartContracts} + docPath={this.props.docsInfo.websitePath} /> {_.isUndefined(this.state.docAgnosticFormat) ? <div @@ -150,9 +149,9 @@ export class SmartContractsDocumentation extends <NestedSidebarMenu selectedVersion={this.props.docsVersion} versions={this.props.availableDocVersions} - topLevelMenu={constants.menuSmartContracts} + topLevelMenu={this.props.docsInfo.getMenu(this.props.docsVersion)} menuSubsectionsBySection={menuSubsectionsBySection} - doc={Docs.SmartContracts} + docPath={this.props.docsInfo.websitePath} /> </div> </div> @@ -162,10 +161,10 @@ export class SmartContractsDocumentation extends style={styles.mainContainers} className="absolute" > - <div id="smartContractsDocs" /> + <div id={SCROLL_TOP_ID} /> <h1 className="md-pl2 sm-pl3"> - <a href={constants.GITHUB_CONTRACTS_URL} target="_blank"> - 0x Smart Contracts + <a href={this.props.docsInfo.packageUrl} target="_blank"> + {this.props.docsInfo.packageName} </a> </h1> {this.renderDocumentation()} @@ -177,19 +176,16 @@ export class SmartContractsDocumentation extends ); } private renderDocumentation(): React.ReactNode { - const subMenus = _.values(constants.menuSmartContracts); + const subMenus = _.values(this.props.docsInfo.getMenu()); const orderedSectionNames = _.flatten(subMenus); - // Since smart contract method params are all base types, no need to pass - // down the typeDefinitionByName - const typeDefinitionByName = {}; - const sections = _.map(orderedSectionNames, this.renderSection.bind(this, typeDefinitionByName)); - return sections; + const typeDefinitionByName = this.props.docsInfo.getTypeDefinitionsByName(this.state.docAgnosticFormat); + const renderedSections = _.map(orderedSectionNames, this.renderSection.bind(this, typeDefinitionByName)); + + return renderedSections; } private renderSection(typeDefinitionByName: TypeDefinitionByName, sectionName: string): React.ReactNode { - const docSection = this.state.docAgnosticFormat[sectionName]; - - const markdownFileIfExists = sectionNameToMarkdown[sectionName]; + const markdownFileIfExists = this.props.docsInfo.sectionNameToMarkdown[sectionName]; if (!_.isUndefined(markdownFileIfExists)) { return ( <MarkdownSection @@ -200,10 +196,22 @@ export class SmartContractsDocumentation extends ); } + const docSection = this.state.docAgnosticFormat[sectionName]; if (_.isUndefined(docSection)) { return null; } + const sortedTypes = _.sortBy(docSection.types, 'name'); + const typeDefs = _.map(sortedTypes, customType => { + return ( + <TypeDefinition + key={`type-${customType.name}`} + customType={customType} + docsInfo={this.props.docsInfo} + /> + ); + }); + const sortedProperties = _.sortBy(docSection.properties, 'name'); const propertyDefs = _.map(sortedProperties, this.renderProperty.bind(this)); @@ -219,6 +227,7 @@ export class SmartContractsDocumentation extends <EventDefinition key={`event-${event.name}-${i}`} event={event} + docsInfo={this.props.docsInfo} /> ); }); @@ -231,7 +240,7 @@ export class SmartContractsDocumentation extends <div style={{marginRight: 7}}> <SectionHeader sectionName={sectionName} /> </div> - {this.renderNetworkBadges(sectionName)} + {this.renderNetworkBadgesIfExists(sectionName)} </div> {docSection.comment && <Comment @@ -239,9 +248,10 @@ export class SmartContractsDocumentation extends /> } {docSection.constructors.length > 0 && + this.props.docsInfo.isVisibleConstructor(sectionName) && <div> <h2 className="thin">Constructor</h2> - {this.renderConstructors(docSection.constructors, typeDefinitionByName)} + {this.renderConstructors(docSection.constructors, sectionName, typeDefinitionByName)} </div> } {docSection.properties.length > 0 && @@ -256,20 +266,28 @@ export class SmartContractsDocumentation extends <div>{methodDefs}</div> </div> } - {docSection.events.length > 0 && + {!_.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 renderNetworkBadges(sectionName: string) { + private renderNetworkBadgesIfExists(sectionName: string) { const networkToAddressByContractName = constants.contractAddresses[this.props.docsVersion]; const badges = _.map(networkToAddressByContractName, (addressByContractName: AddressByContractName, networkName: string) => { const contractAddress = addressByContractName[sectionName]; + if (_.isUndefined(contractAddress)) { + return null; + } const linkIfExists = utils.getEtherScanLinkIfExists( contractAddress, constants.networkIdByName[networkName], EtherscanLinkSuffixes.address, ); @@ -289,11 +307,12 @@ export class SmartContractsDocumentation extends }); return badges; } - private renderConstructors(constructors: SolidityMethod[], + private renderConstructors(constructors: SolidityMethod[]|TypescriptMethod[], + sectionName: string, typeDefinitionByName: TypeDefinitionByName): React.ReactNode { const constructorDefs = _.map(constructors, constructor => { return this.renderMethodBlocks( - constructor, SmartContractsDocSections.zeroEx, constructor.isConstructor, typeDefinitionByName, + constructor, sectionName, constructor.isConstructor, typeDefinitionByName, ); }); return ( @@ -309,12 +328,13 @@ export class SmartContractsDocumentation extends className="pb3" > <code className="hljs"> - {property.name}: <Type type={property.type} /> + {property.name}: <Type type={property.type} docsInfo={this.props.docsInfo} /> </code> {property.source && <SourceLink version={this.props.docsVersion} source={property.source} + baseUrl={this.props.docsInfo.packageUrl} /> } {property.comment && @@ -326,14 +346,15 @@ export class SmartContractsDocumentation extends </div> ); } - private renderMethodBlocks(method: SolidityMethod, sectionName: string, isConstructor: boolean, - typeDefinitionByName: TypeDefinitionByName): React.ReactNode { + private renderMethodBlocks(method: SolidityMethod|TypescriptMethod, sectionName: string, + isConstructor: boolean, typeDefinitionByName: TypeDefinitionByName): React.ReactNode { return ( <MethodBlock - key={`method-${method.name}`} + key={`method-${method.name}-${sectionName}`} method={method} typeDefinitionByName={typeDefinitionByName} libraryVersion={this.props.docsVersion} + docsInfo={this.props.docsInfo} /> ); } @@ -341,40 +362,13 @@ export class SmartContractsDocumentation extends const hashWithPrefix = this.props.location.hash; let hash = hashWithPrefix.slice(1); if (_.isEmpty(hash)) { - hash = 'smartContractsDocs'; // scroll to the top + hash = SCROLL_TOP_ID; // scroll to the top } scroller.scrollTo(hash, {duration: 0, offset: 0, containerId: 'documentation'}); } - private getMenuSubsectionsBySection(docAgnosticFormat?: DocAgnosticFormat): MenuSubsectionsBySection { - const menuSubsectionsBySection = {} as MenuSubsectionsBySection; - if (_.isUndefined(docAgnosticFormat)) { - return menuSubsectionsBySection; - } - - const docSections = _.keys(SmartContractsDocSections); - _.each(docSections, sectionName => { - const docSection = docAgnosticFormat[sectionName]; - if (_.isUndefined(docSection)) { - return; // no-op - } - - if (sectionName === SmartContractsDocSections.types) { - const sortedTypesNames = _.sortBy(docSection.types, 'name'); - const typeNames = _.map(sortedTypesNames, t => t.name); - menuSubsectionsBySection[sectionName] = typeNames; - } else { - const sortedEventNames = _.sortBy(docSection.events, 'name'); - const 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; - } private async fetchJSONDocsFireAndForgetAsync(preferredVersionIfExists?: string): Promise<void> { - const versionToFileName = await docUtils.getVersionToFileNameAsync(DOC_JSON_ROOT); + const versionToFileName = await docUtils.getVersionToFileNameAsync(this.props.docsInfo.docsJsonRoot); const versions = _.keys(versionToFileName); this.props.dispatcher.updateAvailableDocVersions(versions); const sortedVersions = semverSort.desc(versions); @@ -390,8 +384,10 @@ export class SmartContractsDocumentation extends this.props.dispatcher.updateCurrentDocsVersion(versionToFetch); const versionFileNameToFetch = versionToFileName[versionToFetch]; - const versionDocObj = await docUtils.getJSONDocFileAsync(versionFileNameToFetch, DOC_JSON_ROOT); - const docAgnosticFormat = doxityUtils.convertToDocAgnosticFormat(versionDocObj as DoxityDocObj); + const versionDocObj = await docUtils.getJSONDocFileAsync( + versionFileNameToFetch, this.props.docsInfo.docsJsonRoot, + ); + const docAgnosticFormat = this.props.docsInfo.convertToDocAgnosticFormat(versionDocObj as DoxityDocObj); this.setState({ docAgnosticFormat, diff --git a/packages/website/ts/pages/documentation/event_definition.tsx b/packages/website/ts/pages/documentation/event_definition.tsx index ea75d78bc..469e6bb37 100644 --- a/packages/website/ts/pages/documentation/event_definition.tsx +++ b/packages/website/ts/pages/documentation/event_definition.tsx @@ -1,5 +1,6 @@ import * as _ from 'lodash'; import * as React from 'react'; +import {DocsInfo} from 'ts/pages/documentation/docs_info'; import {Type} from 'ts/pages/documentation/type'; import {AnchorTitle} from 'ts/pages/shared/anchor_title'; import {Event, EventArg, HeaderSizes} from 'ts/types'; @@ -11,6 +12,7 @@ const CUSTOM_GREEN = 'rgb(77, 162, 75)'; interface EventDefinitionProps { event: Event; + docsInfo: DocsInfo; } interface EventDefinitionState { @@ -53,9 +55,15 @@ export class EventDefinition extends React.Component<EventDefinitionProps, Event private renderEventCode() { const indexed = <span style={{color: CUSTOM_GREEN}}> indexed</span>; const eventArgs = _.map(this.props.event.eventArgs, (eventArg: EventArg) => { + const type = ( + <Type + type={eventArg.type} + docsInfo={this.props.docsInfo} + /> + ); return ( <span key={`eventArg-${eventArg.name}`}> - {eventArg.name}{eventArg.isIndexed ? indexed : ''}: <Type type={eventArg.type} />, + {eventArg.name}{eventArg.isIndexed ? indexed : ''}: {type}, </span> ); }); diff --git a/packages/website/ts/pages/documentation/interface.tsx b/packages/website/ts/pages/documentation/interface.tsx index d8d4aec32..e671db2b8 100644 --- a/packages/website/ts/pages/documentation/interface.tsx +++ b/packages/website/ts/pages/documentation/interface.tsx @@ -1,11 +1,13 @@ import * as _ from 'lodash'; import * as React from 'react'; +import {DocsInfo} from 'ts/pages/documentation/docs_info'; import {MethodSignature} from 'ts/pages/documentation/method_signature'; import {Type} from 'ts/pages/documentation/type'; import {CustomType, TypeDocTypes} from 'ts/types'; interface InterfaceProps { type: CustomType; + docsInfo: DocsInfo; } export function Interface(props: InterfaceProps) { @@ -15,11 +17,12 @@ export function Interface(props: InterfaceProps) { <span key={`property-${property.name}-${property.type}-${type.name}`}> {property.name}:{' '} {property.type.typeDocType !== TypeDocTypes.Reflection ? - <Type type={property.type} /> : + <Type type={property.type} docsInfo={props.docsInfo} /> : <MethodSignature method={property.type.method} shouldHideMethodName={true} shouldUseArrowSyntax={true} + docsInfo={props.docsInfo} /> }, </span> @@ -30,7 +33,7 @@ export function Interface(props: InterfaceProps) { const is = type.indexSignature; const param = ( <span key={`indexSigParams-${is.keyName}-${is.keyType}-${type.name}`}> - {is.keyName}: <Type type={is.keyType} /> + {is.keyName}: <Type type={is.keyType} docsInfo={props.docsInfo} /> </span> ); properties.push(( diff --git a/packages/website/ts/pages/documentation/method_block.tsx b/packages/website/ts/pages/documentation/method_block.tsx index 026c46918..3f4eb7164 100644 --- a/packages/website/ts/pages/documentation/method_block.tsx +++ b/packages/website/ts/pages/documentation/method_block.tsx @@ -4,6 +4,7 @@ import {colors} from 'material-ui/styles'; import * as React from 'react'; import * as ReactMarkdown from 'react-markdown'; import {Comment} from 'ts/pages/documentation/comment'; +import {DocsInfo} from 'ts/pages/documentation/docs_info'; import {MethodSignature} from 'ts/pages/documentation/method_signature'; import {SourceLink} from 'ts/pages/documentation/source_link'; import {AnchorTitle} from 'ts/pages/shared/anchor_title'; @@ -23,6 +24,7 @@ interface MethodBlockProps { method: SolidityMethod|TypescriptMethod; libraryVersion: string; typeDefinitionByName: TypeDefinitionByName; + docsInfo: DocsInfo; } interface MethodBlockState { @@ -85,12 +87,14 @@ export class MethodBlock extends React.Component<MethodBlockProps, MethodBlockSt <MethodSignature method={method} typeDefinitionByName={this.props.typeDefinitionByName} + docsInfo={this.props.docsInfo} /> </code> {(method as TypescriptMethod).source && <SourceLink version={this.props.libraryVersion} source={(method as TypescriptMethod).source} + baseUrl={this.props.docsInfo.packageUrl} /> } {method.comment && diff --git a/packages/website/ts/pages/documentation/method_signature.tsx b/packages/website/ts/pages/documentation/method_signature.tsx index e3806b2fa..846c9fa4f 100644 --- a/packages/website/ts/pages/documentation/method_signature.tsx +++ b/packages/website/ts/pages/documentation/method_signature.tsx @@ -1,5 +1,6 @@ import * as _ from 'lodash'; import * as React from 'react'; +import {DocsInfo} from 'ts/pages/documentation/docs_info'; import {Type} from 'ts/pages/documentation/type'; import {Parameter, SolidityMethod, TypeDefinitionByName, TypescriptMethod} from 'ts/types'; @@ -8,6 +9,7 @@ interface MethodSignatureProps { shouldHideMethodName?: boolean; shouldUseArrowSyntax?: boolean; typeDefinitionByName?: TypeDefinitionByName; + docsInfo: DocsInfo; } const defaultProps = { @@ -16,45 +18,64 @@ const defaultProps = { }; export const MethodSignature: React.SFC<MethodSignatureProps> = (props: MethodSignatureProps) => { - const parameters = renderParameters(props.method, props.typeDefinitionByName); + const parameters = renderParameters(props.method, props.docsInfo, props.typeDefinitionByName); const paramString = _.reduce(parameters, (prev: React.ReactNode, curr: React.ReactNode) => { return [prev, ', ', curr]; }); const methodName = props.shouldHideMethodName ? '' : props.method.name; const typeParameterIfExists = _.isUndefined((props.method as TypescriptMethod).typeParameter) ? undefined : - renderTypeParameter(props.method, props.typeDefinitionByName); + renderTypeParameter(props.method, props.docsInfo, props.typeDefinitionByName); return ( <span> {props.method.callPath}{methodName}{typeParameterIfExists}({paramString}) {props.shouldUseArrowSyntax ? ' => ' : ': '} {' '} {props.method.returnType && - <Type type={props.method.returnType} typeDefinitionByName={props.typeDefinitionByName}/> + <Type + type={props.method.returnType} + typeDefinitionByName={props.typeDefinitionByName} + docsInfo={props.docsInfo} + /> } </span> ); }; -function renderParameters(method: TypescriptMethod|SolidityMethod, typeDefinitionByName?: TypeDefinitionByName) { +function renderParameters( + method: TypescriptMethod|SolidityMethod, docsInfo: DocsInfo, typeDefinitionByName?: TypeDefinitionByName, +) { const parameters = method.parameters; const params = _.map(parameters, (p: Parameter) => { const isOptional = p.isOptional; + const type = ( + <Type + type={p.type} + typeDefinitionByName={typeDefinitionByName} + docsInfo={docsInfo} + /> + ); return ( <span key={`param-${p.type}-${p.name}`}> - {p.name}{isOptional && '?'}: <Type type={p.type} typeDefinitionByName={typeDefinitionByName}/> + {p.name}{isOptional && '?'}: {type} </span> ); }); return params; } -function renderTypeParameter(method: TypescriptMethod, typeDefinitionByName?: TypeDefinitionByName) { +function renderTypeParameter( + method: TypescriptMethod, docsInfo: DocsInfo, typeDefinitionByName?: TypeDefinitionByName, +) { const typeParameter = method.typeParameter; const typeParam = ( <span> {`<${typeParameter.name} extends `} - <Type type={typeParameter.type} typeDefinitionByName={typeDefinitionByName}/> + <Type + type={typeParameter.type} + typeDefinitionByName={typeDefinitionByName} + docsInfo={docsInfo} + /> {`>`} </span> ); diff --git a/packages/website/ts/pages/documentation/source_link.tsx b/packages/website/ts/pages/documentation/source_link.tsx index 0d40a4b7a..408dcabc7 100644 --- a/packages/website/ts/pages/documentation/source_link.tsx +++ b/packages/website/ts/pages/documentation/source_link.tsx @@ -5,6 +5,7 @@ import {constants} from 'ts/utils/constants'; interface SourceLinkProps { source: Source; + baseUrl: string; version: string; } @@ -12,7 +13,7 @@ const SUB_PKG = '0x.js'; export function SourceLink(props: SourceLinkProps) { const src = props.source; - const url = constants.GITHUB_0X_JS_URL; + const url = props.baseUrl; const sourceCodeUrl = `${url}/blob/${SUB_PKG}%40${props.version}/packages/${SUB_PKG}/${src.fileName}#L${src.line}`; return ( <div className="pt2" style={{fontSize: 14}}> diff --git a/packages/website/ts/pages/documentation/type.tsx b/packages/website/ts/pages/documentation/type.tsx index b7d56f360..acd46ab72 100644 --- a/packages/website/ts/pages/documentation/type.tsx +++ b/packages/website/ts/pages/documentation/type.tsx @@ -3,6 +3,7 @@ import {colors} from 'material-ui/styles'; import * as React from 'react'; import {Link as ScrollLink} from 'react-scroll'; import * as ReactTooltip from 'react-tooltip'; +import {DocsInfo} from 'ts/pages/documentation/docs_info'; import {TypeDefinition} from 'ts/pages/documentation/type_definition'; import {Type as TypeDef, TypeDefinitionByName, TypeDocTypes} from 'ts/types'; import {constants} from 'ts/utils/constants'; @@ -38,6 +39,7 @@ const typeToSection: {[typeName: string]: string} = { interface TypeProps { type: TypeDef; + docsInfo: DocsInfo; typeDefinitionByName?: TypeDefinitionByName; } @@ -70,6 +72,7 @@ export function Type(props: TypeProps): any { key={key} type={arg.elementType} typeDefinitionByName={props.typeDefinitionByName} + docsInfo={props.docsInfo} />[] </span> ); @@ -79,6 +82,7 @@ export function Type(props: TypeProps): any { key={`type-${arg.name}-${arg.value}-${arg.typeDocType}`} type={arg} typeDefinitionByName={props.typeDefinitionByName} + docsInfo={props.docsInfo} /> ); return subType; @@ -102,6 +106,7 @@ export function Type(props: TypeProps): any { key={`type-${t.name}-${t.value}-${t.typeDocType}`} type={t} typeDefinitionByName={props.typeDefinitionByName} + docsInfo={props.docsInfo} /> ); }); @@ -141,7 +146,7 @@ export function Type(props: TypeProps): any { </a> ); } else if ((isReference || isArray) && - (typeDocUtils.isPublicType(typeName as string) || + (props.docsInfo.isPublicType(typeName as string) || !_.isUndefined(sectionNameIfExists))) { const id = Math.random().toString(); const typeDefinitionAnchorId = _.isUndefined(sectionNameIfExists) ? typeName : sectionNameIfExists; @@ -176,7 +181,11 @@ export function Type(props: TypeProps): any { id={id} className="typeTooltip" > - <TypeDefinition customType={typeDefinition} shouldAddId={false} /> + <TypeDefinition + customType={typeDefinition} + shouldAddId={false} + docsInfo={props.docsInfo} + /> </ReactTooltip> </span> } diff --git a/packages/website/ts/pages/documentation/type_definition.tsx b/packages/website/ts/pages/documentation/type_definition.tsx index 984c223b6..17b182c70 100644 --- a/packages/website/ts/pages/documentation/type_definition.tsx +++ b/packages/website/ts/pages/documentation/type_definition.tsx @@ -2,6 +2,7 @@ import * as _ from 'lodash'; import * as React from 'react'; import {Comment} from 'ts/pages/documentation/comment'; import {CustomEnum} from 'ts/pages/documentation/custom_enum'; +import {DocsInfo} from 'ts/pages/documentation/docs_info'; import {Enum} from 'ts/pages/documentation/enum'; import {Interface} from 'ts/pages/documentation/interface'; import {MethodSignature} from 'ts/pages/documentation/method_signature'; @@ -17,6 +18,7 @@ const KEYWORD_COLOR = '#a81ca6'; interface TypeDefinitionProps { customType: CustomType; shouldAddId?: boolean; + docsInfo: DocsInfo; } interface TypeDefinitionState { @@ -35,7 +37,7 @@ export class TypeDefinition extends React.Component<TypeDefinitionProps, TypeDef } public render() { const customType = this.props.customType; - if (!typeDocUtils.isPublicType(customType.name)) { + if (!this.props.docsInfo.isPublicType(customType.name)) { return null; // no-op } @@ -47,6 +49,7 @@ export class TypeDefinition extends React.Component<TypeDefinitionProps, TypeDef codeSnippet = ( <Interface type={customType} + docsInfo={this.props.docsInfo} /> ); break; @@ -81,11 +84,12 @@ export class TypeDefinition extends React.Component<TypeDefinitionProps, TypeDef <span> <span style={{color: KEYWORD_COLOR}}>type</span> {customType.name} ={' '} {customType.type.typeDocType !== TypeDocTypes.Reflection ? - <Type type={customType.type} /> : + <Type type={customType.type} docsInfo={this.props.docsInfo} /> : <MethodSignature method={customType.type.method} shouldHideMethodName={true} shouldUseArrowSyntax={true} + docsInfo={this.props.docsInfo} /> } </span> diff --git a/packages/website/ts/pages/documentation/zero_ex_js_documentation.tsx b/packages/website/ts/pages/documentation/zero_ex_js_documentation.tsx deleted file mode 100644 index d64b196ed..000000000 --- a/packages/website/ts/pages/documentation/zero_ex_js_documentation.tsx +++ /dev/null @@ -1,341 +0,0 @@ -import findVersions = require('find-versions'); -import * as _ from 'lodash'; -import CircularProgress from 'material-ui/CircularProgress'; -import MenuItem from 'material-ui/MenuItem'; -import Paper from 'material-ui/Paper'; -import {colors} from 'material-ui/styles'; -import * as React from 'react'; -import DocumentTitle = require('react-document-title'); -import * as ReactMarkdown from 'react-markdown'; -import { - Element as ScrollElement, - Link as ScrollLink, - scroller, -} from 'react-scroll'; -import semverSort = require('semver-sort'); -import {TopBar} from 'ts/components/top_bar'; -import {Loading} from 'ts/components/ui/loading'; -import {Comment} from 'ts/pages/documentation/comment'; -import {MethodBlock} from 'ts/pages/documentation/method_block'; -import {SourceLink} from 'ts/pages/documentation/source_link'; -import {Type} from 'ts/pages/documentation/type'; -import {TypeDefinition} from 'ts/pages/documentation/type_definition'; -import {AnchorTitle} from 'ts/pages/shared/anchor_title'; -import {MarkdownSection} from 'ts/pages/shared/markdown_section'; -import {NestedSidebarMenu} from 'ts/pages/shared/nested_sidebar_menu'; -import {SectionHeader} from 'ts/pages/shared/section_header'; -import {Dispatcher} from 'ts/redux/dispatcher'; -import { - CustomType, - DocAgnosticFormat, - Docs, - KindString, - Property, - ScreenWidths, - Styles, - TypeDefinitionByName, - TypeDocNode, - TypescriptMethod, - ZeroExJsDocSections, -} from 'ts/types'; -import {constants} from 'ts/utils/constants'; -import {docUtils} from 'ts/utils/doc_utils'; -import {typeDocUtils} from 'ts/utils/typedoc_utils'; -import {utils} from 'ts/utils/utils'; -/* tslint:disable:no-var-requires */ -const IntroMarkdown = require('md/docs/0xjs/introduction'); -const InstallationMarkdown = require('md/docs/0xjs/installation'); -const AsyncMarkdown = require('md/docs/0xjs/async'); -const ErrorsMarkdown = require('md/docs/0xjs/errors'); -const versioningMarkdown = require('md/docs/0xjs/versioning'); -/* tslint:enable:no-var-requires */ - -const SCROLL_TO_TIMEOUT = 500; -const DOC_JSON_ROOT = constants.S3_0XJS_DOCUMENTATION_JSON_ROOT; - -const sectionNameToMarkdown = { - [ZeroExJsDocSections.introduction]: IntroMarkdown, - [ZeroExJsDocSections.installation]: InstallationMarkdown, - [ZeroExJsDocSections.async]: AsyncMarkdown, - [ZeroExJsDocSections.errors]: ErrorsMarkdown, - [ZeroExJsDocSections.versioning]: versioningMarkdown, -}; - -export interface ZeroExJSDocumentationPassedProps { - source: string; - location: Location; -} - -export interface ZeroExJSDocumentationAllProps { - source: string; - location: Location; - dispatcher: Dispatcher; - docsVersion: string; - availableDocVersions: string[]; -} - -interface ZeroExJSDocumentationState { - docAgnosticFormat?: DocAgnosticFormat; -} - -const styles: Styles = { - mainContainers: { - position: 'absolute', - top: 60, - left: 0, - bottom: 0, - right: 0, - overflowZ: 'hidden', - overflowY: 'scroll', - minHeight: 'calc(100vh - 60px)', - WebkitOverflowScrolling: 'touch', - }, - menuContainer: { - borderColor: colors.grey300, - maxWidth: 330, - marginLeft: 20, - }, -}; - -export class ZeroExJSDocumentation extends React.Component<ZeroExJSDocumentationAllProps, ZeroExJSDocumentationState> { - constructor(props: ZeroExJSDocumentationAllProps) { - super(props); - this.state = { - docAgnosticFormat: undefined, - }; - } - public componentWillMount() { - const pathName = this.props.location.pathname; - const lastSegment = pathName.substr(pathName.lastIndexOf('/') + 1); - const versions = findVersions(lastSegment); - const preferredVersionIfExists = versions.length > 0 ? versions[0] : undefined; - // tslint:disable-next-line:no-floating-promises - this.fetchJSONDocsFireAndForgetAsync(preferredVersionIfExists); - } - public render() { - const menuSubsectionsBySection = _.isUndefined(this.state.docAgnosticFormat) - ? {} - : typeDocUtils.getMenuSubsectionsBySection(this.state.docAgnosticFormat); - return ( - <div> - <DocumentTitle title="0x.js Documentation"/> - <TopBar - blockchainIsLoaded={false} - location={this.props.location} - docsVersion={this.props.docsVersion} - availableDocVersions={this.props.availableDocVersions} - menuSubsectionsBySection={menuSubsectionsBySection} - shouldFullWidth={true} - doc={Docs.ZeroExJs} - /> - {_.isUndefined(this.state.docAgnosticFormat) ? - <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> : - <div - className="mx-auto flex" - style={{color: colors.grey800, height: 43}} - > - <div className="relative col md-col-3 lg-col-3 lg-pl0 md-pl1 sm-hide xs-hide"> - <div - className="border-right absolute" - style={{...styles.menuContainer, ...styles.mainContainers}} - > - <NestedSidebarMenu - selectedVersion={this.props.docsVersion} - versions={this.props.availableDocVersions} - topLevelMenu={typeDocUtils.getFinal0xjsMenu(this.props.docsVersion)} - menuSubsectionsBySection={menuSubsectionsBySection} - doc={Docs.ZeroExJs} - /> - </div> - </div> - <div className="relative col lg-col-9 md-col-9 sm-col-12 col-12"> - <div - id="documentation" - style={styles.mainContainers} - className="absolute" - > - <div id="zeroExJSDocs" /> - <h1 className="md-pl2 sm-pl3"> - <a href={constants.GITHUB_0X_JS_URL} target="_blank"> - 0x.js - </a> - </h1> - {this.renderDocumentation()} - </div> - </div> - </div> - } - </div> - ); - } - private renderDocumentation(): React.ReactNode { - const typeDocSection = this.state.docAgnosticFormat[ZeroExJsDocSections.types]; - const typeDefinitionByName = _.keyBy(typeDocSection.types, 'name'); - - const subMenus = _.values(constants.menu0xjs); - const orderedSectionNames = _.flatten(subMenus); - const sections = _.map(orderedSectionNames, this.renderSection.bind(this, typeDefinitionByName)); - - return sections; - } - private renderSection(typeDefinitionByName: TypeDefinitionByName, sectionName: string): React.ReactNode { - const docSection = this.state.docAgnosticFormat[sectionName]; - - const markdownFileIfExists = sectionNameToMarkdown[sectionName]; - if (!_.isUndefined(markdownFileIfExists)) { - return ( - <MarkdownSection - key={`markdown-section-${sectionName}`} - sectionName={sectionName} - markdownContent={markdownFileIfExists} - /> - ); - } - - if (_.isUndefined(docSection)) { - return null; - } - - const typeDefs = _.map(docSection.types, customType => { - return ( - <TypeDefinition - key={`type-${customType.name}`} - customType={customType} - /> - ); - }); - const propertyDefs = _.map(docSection.properties, this.renderProperty.bind(this)); - const methodDefs = _.map(docSection.methods, method => { - const isConstructor = false; - return this.renderMethodBlocks(method, sectionName, isConstructor, typeDefinitionByName); - }); - return ( - <div - key={`section-${sectionName}`} - className="py2 pr3 md-pl2 sm-pl3" - > - <SectionHeader sectionName={sectionName} /> - <Comment - comment={docSection.comment} - /> - {sectionName === ZeroExJsDocSections.zeroEx && docSection.constructors.length > 0 && - <div> - <h2 className="thin">Constructor</h2> - {this.renderZeroExConstructors(docSection.constructors, 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> - } - {typeDefs.length > 0 && - <div> - <div>{typeDefs}</div> - </div> - } - </div> - ); - } - private renderZeroExConstructors(constructors: TypescriptMethod[], - typeDefinitionByName: TypeDefinitionByName): React.ReactNode { - const constructorDefs = _.map(constructors, constructor => { - return this.renderMethodBlocks( - constructor, ZeroExJsDocSections.zeroEx, constructor.isConstructor, typeDefinitionByName, - ); - }); - return ( - <div> - {constructorDefs} - </div> - ); - } - private renderProperty(property: Property): React.ReactNode { - return ( - <div - key={`property-${property.name}-${property.type.name}`} - className="pb3" - > - <code className="hljs"> - {property.name}: <Type type={property.type} /> - </code> - <SourceLink - version={this.props.docsVersion} - source={property.source} - /> - {property.comment && - <Comment - comment={property.comment} - className="py2" - /> - } - </div> - ); - } - private renderMethodBlocks(method: TypescriptMethod, sectionName: string, isConstructor: boolean, - typeDefinitionByName: TypeDefinitionByName): React.ReactNode { - return ( - <MethodBlock - key={`method-${method.name}-${!_.isUndefined(method.source) ? method.source.line : ''}`} - method={method} - typeDefinitionByName={typeDefinitionByName} - libraryVersion={this.props.docsVersion} - /> - ); - } - private scrollToHash(): void { - const hashWithPrefix = this.props.location.hash; - let hash = hashWithPrefix.slice(1); - if (_.isEmpty(hash)) { - hash = 'zeroExJSDocs'; // scroll to the top - } - - scroller.scrollTo(hash, {duration: 0, offset: 0, containerId: 'documentation'}); - } - private async fetchJSONDocsFireAndForgetAsync(preferredVersionIfExists?: string): Promise<void> { - const versionToFileName = await docUtils.getVersionToFileNameAsync(DOC_JSON_ROOT); - const versions = _.keys(versionToFileName); - this.props.dispatcher.updateAvailableDocVersions(versions); - const sortedVersions = semverSort.desc(versions); - const latestVersion = sortedVersions[0]; - - let versionToFetch = latestVersion; - if (!_.isUndefined(preferredVersionIfExists)) { - const preferredVersionFileNameIfExists = versionToFileName[preferredVersionIfExists]; - if (!_.isUndefined(preferredVersionFileNameIfExists)) { - versionToFetch = preferredVersionIfExists; - } - } - this.props.dispatcher.updateCurrentDocsVersion(versionToFetch); - - const versionFileNameToFetch = versionToFileName[versionToFetch]; - const versionDocObj = await docUtils.getJSONDocFileAsync(versionFileNameToFetch, DOC_JSON_ROOT); - const docAgnosticFormat = typeDocUtils.convertToDocAgnosticFormat((versionDocObj as TypeDocNode)); - - this.setState({ - docAgnosticFormat, - }, () => { - this.scrollToHash(); - }); - } -} diff --git a/packages/website/ts/pages/shared/nested_sidebar_menu.tsx b/packages/website/ts/pages/shared/nested_sidebar_menu.tsx index 69e32aecb..cbb863f3e 100644 --- a/packages/website/ts/pages/shared/nested_sidebar_menu.tsx +++ b/packages/website/ts/pages/shared/nested_sidebar_menu.tsx @@ -4,7 +4,7 @@ import {colors} from 'material-ui/styles'; import * as React from 'react'; import {Link as ScrollLink} from 'react-scroll'; import {VersionDropDown} from 'ts/pages/shared/version_drop_down'; -import {Docs, MenuSubsectionsBySection, Styles, ZeroExJsDocSections} from 'ts/types'; +import {Docs, MenuSubsectionsBySection, Styles} from 'ts/types'; import {constants} from 'ts/utils/constants'; import {typeDocUtils} from 'ts/utils/typedoc_utils'; import {utils} from 'ts/utils/utils'; @@ -16,7 +16,7 @@ interface NestedSidebarMenuProps { onMenuItemClick?: () => void; selectedVersion?: string; versions?: string[]; - doc?: Docs; + docPath?: string; isSectionHeaderClickable?: boolean; } @@ -77,11 +77,11 @@ export class NestedSidebarMenu extends React.Component<NestedSidebarMenuProps, N <div> {!_.isUndefined(this.props.versions) && !_.isUndefined(this.props.selectedVersion) && - !_.isUndefined(this.props.doc) && + !_.isUndefined(this.props.docPath) && <VersionDropDown selectedVersion={this.props.selectedVersion} versions={this.props.versions} - doc={this.props.doc} + docPath={this.props.docPath} /> } {navigation} diff --git a/packages/website/ts/pages/shared/version_drop_down.tsx b/packages/website/ts/pages/shared/version_drop_down.tsx index 8f4f1a35b..4af9a834f 100644 --- a/packages/website/ts/pages/shared/version_drop_down.tsx +++ b/packages/website/ts/pages/shared/version_drop_down.tsx @@ -8,7 +8,7 @@ import {constants} from 'ts/utils/constants'; interface VersionDropDownProps { selectedVersion: string; versions: string[]; - doc: Docs; + docPath: string; } interface VersionDropDownState {} @@ -40,7 +40,6 @@ export class VersionDropDown extends React.Component<VersionDropDownProps, Versi return items; } private updateSelectedVersion(e: any, index: number, value: string) { - const docPath = constants.docToPath[this.props.doc]; - window.location.href = `${docPath}/${value}${window.location.hash}`; + window.location.href = `${this.props.docPath}/${value}${window.location.hash}`; } } diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts index 403af9e78..e9af8cb81 100644 --- a/packages/website/ts/types.ts +++ b/packages/website/ts/types.ts @@ -468,33 +468,6 @@ export interface CustomTypeChild { defaultValue?: string; } -export const ZeroExJsDocSections = strEnum([ - 'introduction', - 'installation', - 'testrpc', - 'async', - 'errors', - 'versioning', - 'zeroEx', - 'exchange', - 'token', - 'tokenRegistry', - 'etherToken', - 'proxy', - 'types', -]); -export type ZeroExJsDocSections = keyof typeof ZeroExJsDocSections; - -export const SmartContractsDocSections = strEnum([ - 'Introduction', - 'Exchange', - 'TokenTransferProxy', - 'TokenRegistry', - 'ZRXToken', - 'EtherToken', -]); -export type SmartContractsDocSections = keyof typeof SmartContractsDocSections; - export interface FAQQuestion { prompt: string; answer: React.ReactNode; @@ -689,4 +662,29 @@ export enum WebsitePaths { About = '/about', Whitepaper = '/pdfs/0x_white_paper.pdf', SmartContracts = '/docs/contracts', -} // tslint:disable:max-file-line-count +} + +export interface DocsMenu { + [sectionName: string]: string[]; +} + +export interface SectionsMap { + [sectionName: string]: string; +} + +export interface DocsInfoConfig { + packageName: string; + packageUrl: string; + websitePath: string; + docsJsonRoot: string; + menu: DocsMenu; + sections: SectionsMap; + sectionNameToMarkdown: {[sectionName: string]: string}; + visibleConstructors: string[]; + convertToDocAgnosticFormatFn: (docObj: DoxityDocObj|TypeDocNode, docsInfo?: any) => DocAgnosticFormat; + publicTypes?: string[]; + sectionNameToModulePath?: {[sectionName: string]: string[]}; + menuSubsectionToVersionWhenIntroduced?: {[sectionName: string]: string}; +} + +// tslint:disable:max-file-line-count diff --git a/packages/website/ts/utils/constants.ts b/packages/website/ts/utils/constants.ts index e39df5558..cae59af5f 100644 --- a/packages/website/ts/utils/constants.ts +++ b/packages/website/ts/utils/constants.ts @@ -5,12 +5,18 @@ import { ExchangeContractErrs, Networks, PublicNodeUrlsByNetworkId, - SmartContractsDocSections, WebsitePaths, - ZeroExJsDocSections, } from 'ts/types'; const INFURA_API_KEY = 'T5WSC8cautR4KXyYgsRs'; +const smartContractDocSections = { + Introduction: 'Introduction', + Exchange: 'Exchange', + TokenTransferProxy: 'TokenTransferProxy', + TokenRegistry: 'TokenRegistry', + ZRXToken: 'ZRXToken', + EtherToken: 'EtherToken', +}; export const constants = { ANGELLIST_URL: 'https://angel.co/0xproject/jobs', @@ -27,8 +33,6 @@ export const constants = { FEE_RECIPIENT_ADDRESS: '0x0000000000000000000000000000000000000000', FIREFOX_U2F_ADDON: 'https://addons.mozilla.org/en-US/firefox/addon/u2f-support-add-on/', GITHUB_URL: 'https://github.com/0xProject', - GITHUB_0X_JS_URL: 'https://github.com/0xProject/0x.js', - GITHUB_CONTRACTS_URL: 'https://github.com/0xProject/contracts', GITHUB_WIKI_URL: 'https://github.com/0xProject/wiki', HTTP_NO_CONTENT_STATUS_CODE: 204, ACCEPT_DISCLAIMER_LOCAL_STORAGE_KEY: 'didAcceptPortalDisclaimer', @@ -67,8 +71,6 @@ export const constants = { REDDIT_URL: 'https://reddit.com/r/0xproject', STANDARD_RELAYER_API_GITHUB: 'https://github.com/0xProject/standard-relayer-api/blob/master/README.md', SUCCESS_STATUS: 200, - S3_0XJS_DOCUMENTATION_JSON_ROOT: 'https://s3.amazonaws.com/0xjs-docs-jsons', - S3_SMART_CONTRACTS_DOCUMENTATION_JSON_ROOT: 'https://s3.amazonaws.com/smart-contracts-docs-json', UNAVAILABLE_STATUS: 503, TAKER_FEE: new BigNumber(0), TESTNET_NAME: 'Kovan', @@ -154,120 +156,33 @@ export const constants = { [Networks.rinkeby]: 4, [Networks.kovan]: 42, } as {[networkName: string]: number}, - // Note: This needs to be kept in sync with the types exported in index.ts. Unfortunately there is - // currently no way to extract the re-exported types from index.ts via TypeDoc :( - public0xjsTypes: [ - 'Order', - 'SignedOrder', - 'ECSignature', - 'ZeroExError', - 'EventCallback', - 'EventCallbackAsync', - 'EventCallbackSync', - 'ExchangeContractErrs', - 'ContractEvent', - 'Token', - 'ExchangeEvents', - 'IndexedFilterValues', - 'SubscriptionOpts', - 'BlockParam', - 'OrderFillOrKillRequest', - 'OrderCancellationRequest', - 'OrderFillRequest', - 'ContractEventEmitter', - 'Web3Provider', - 'ContractEventArgs', - 'LogCancelArgs', - 'LogFillArgs', - 'LogErrorContractEventArgs', - 'LogFillContractEventArgs', - 'LogCancelContractEventArgs', - 'TokenEvents', - 'ExchangeContractEventArgs', - 'TransferContractEventArgs', - 'ApprovalContractEventArgs', - 'TokenContractEventArgs', - 'ZeroExConfig', - 'TransactionReceiptWithDecodedLogs', - 'LogWithDecodedArgs', - 'DecodedLogArgs', - 'MethodOpts', - 'ValidateOrderFillableOpts', - 'OrderTransactionOpts', - 'TransactionOpts', - 'ContractEventArg', - 'LogEvent', - 'LogEntry', - 'DecodedLogEvent', - ], - menuSmartContracts: { - introduction: [ - SmartContractsDocSections.Introduction, - ], - contracts: [ - SmartContractsDocSections.Exchange, - SmartContractsDocSections.TokenRegistry, - SmartContractsDocSections.ZRXToken, - SmartContractsDocSections.EtherToken, - SmartContractsDocSections.TokenTransferProxy, - ], - }, - menu0xjs: { - introduction: [ - ZeroExJsDocSections.introduction, - ], - install: [ - ZeroExJsDocSections.installation, - ], - topics: [ - ZeroExJsDocSections.async, - ZeroExJsDocSections.errors, - ZeroExJsDocSections.versioning, - ], - zeroEx: [ - ZeroExJsDocSections.zeroEx, - ], - contracts: [ - ZeroExJsDocSections.exchange, - ZeroExJsDocSections.token, - ZeroExJsDocSections.tokenRegistry, - ZeroExJsDocSections.etherToken, - ZeroExJsDocSections.proxy, - ], - types: [ - ZeroExJsDocSections.types, - ], - }, - menuSubsectionToVersionWhenIntroduced: { - [ZeroExJsDocSections.etherToken]: '0.7.1', - [ZeroExJsDocSections.proxy]: '0.8.0', - }, docToPath: { [Docs.ZeroExJs]: WebsitePaths.ZeroExJs, [Docs.SmartContracts]: WebsitePaths.SmartContracts, }, + smartContractDocSections, contractAddresses: { '1.0.0': { [Networks.mainnet]: { - [SmartContractsDocSections.Exchange]: '0x12459c951127e0c374ff9105dda097662a027093', - [SmartContractsDocSections.TokenTransferProxy]: '0x8da0d80f5007ef1e431dd2127178d224e32c2ef4', - [SmartContractsDocSections.ZRXToken]: '0xe41d2489571d322189246dafa5ebde1f4699f498', - [SmartContractsDocSections.EtherToken]: '0x2956356cd2a2bf3202f771f50d3d14a367b48070', - [SmartContractsDocSections.TokenRegistry]: '0x926a74c5c36adf004c87399e65f75628b0f98d2c', + [smartContractDocSections.Exchange]: '0x12459c951127e0c374ff9105dda097662a027093', + [smartContractDocSections.TokenTransferProxy]: '0x8da0d80f5007ef1e431dd2127178d224e32c2ef4', + [smartContractDocSections.ZRXToken]: '0xe41d2489571d322189246dafa5ebde1f4699f498', + [smartContractDocSections.EtherToken]: '0x2956356cd2a2bf3202f771f50d3d14a367b48070', + [smartContractDocSections.TokenRegistry]: '0x926a74c5c36adf004c87399e65f75628b0f98d2c', }, [Networks.ropsten]: { - [SmartContractsDocSections.Exchange]: '0x479cc461fecd078f766ecc58533d6f69580cf3ac', - [SmartContractsDocSections.TokenTransferProxy]: '0x4e9aad8184de8833365fea970cd9149372fdf1e6', - [SmartContractsDocSections.ZRXToken]: '0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d', - [SmartContractsDocSections.EtherToken]: '0xc00fd9820cd2898cc4c054b7bf142de637ad129a', - [SmartContractsDocSections.TokenRegistry]: '0x6b1a50f0bb5a7995444bd3877b22dc89c62843ed', + [smartContractDocSections.Exchange]: '0x479cc461fecd078f766ecc58533d6f69580cf3ac', + [smartContractDocSections.TokenTransferProxy]: '0x4e9aad8184de8833365fea970cd9149372fdf1e6', + [smartContractDocSections.ZRXToken]: '0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d', + [smartContractDocSections.EtherToken]: '0xc00fd9820cd2898cc4c054b7bf142de637ad129a', + [smartContractDocSections.TokenRegistry]: '0x6b1a50f0bb5a7995444bd3877b22dc89c62843ed', }, [Networks.kovan]: { - [SmartContractsDocSections.Exchange]: '0x90fe2af704b34e0224bf2299c838e04d4dcf1364', - [SmartContractsDocSections.TokenTransferProxy]: '0x087Eed4Bc1ee3DE49BeFbd66C662B434B15d49d4', - [SmartContractsDocSections.ZRXToken]: '0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570', - [SmartContractsDocSections.EtherToken]: '0x05d090b51c40b020eab3bfcb6a2dff130df22e9c', - [SmartContractsDocSections.TokenRegistry]: '0xf18e504561f4347bea557f3d4558f559dddbae7f', + [smartContractDocSections.Exchange]: '0x90fe2af704b34e0224bf2299c838e04d4dcf1364', + [smartContractDocSections.TokenTransferProxy]: '0x087Eed4Bc1ee3DE49BeFbd66C662B434B15d49d4', + [smartContractDocSections.ZRXToken]: '0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570', + [smartContractDocSections.EtherToken]: '0x05d090b51c40b020eab3bfcb6a2dff130df22e9c', + [smartContractDocSections.TokenRegistry]: '0xf18e504561f4347bea557f3d4558f559dddbae7f', }, }, } as ContractAddresses, diff --git a/packages/website/ts/utils/typedoc_utils.ts b/packages/website/ts/utils/typedoc_utils.ts index bb2f7745a..7708efb35 100644 --- a/packages/website/ts/utils/typedoc_utils.ts +++ b/packages/website/ts/utils/typedoc_utils.ts @@ -1,41 +1,27 @@ -import compareVersions = require('compare-versions'); import * as _ from 'lodash'; +import {DocsInfo} from 'ts/pages/documentation/docs_info'; import { CustomType, CustomTypeChild, DocAgnosticFormat, DocSection, + DocsMenu, IndexSignature, KindString, MenuSubsectionsBySection, Parameter, Property, + SectionsMap, Type, TypeDocNode, TypeDocType, TypeDocTypes, TypeParameter, TypescriptMethod, - ZeroExJsDocSections, } from 'ts/types'; import {constants} from 'ts/utils/constants'; import {utils} from 'ts/utils/utils'; -const TYPES_MODULE_PATH = '"src/types"'; - -export const sectionNameToPossibleModulePaths: {[name: string]: string[]} = { - [ZeroExJsDocSections.zeroEx]: ['"src/0x"'], - [ZeroExJsDocSections.exchange]: ['"src/contract_wrappers/exchange_wrapper"'], - [ZeroExJsDocSections.tokenRegistry]: ['"src/contract_wrappers/token_registry_wrapper"'], - [ZeroExJsDocSections.token]: ['"src/contract_wrappers/token_wrapper"'], - [ZeroExJsDocSections.etherToken]: ['"src/contract_wrappers/ether_token_wrapper"'], - [ZeroExJsDocSections.proxy]: [ - '"src/contract_wrappers/proxy_wrapper"', - '"src/contract_wrappers/token_transfer_proxy_wrapper"', - ], - [ZeroExJsDocSections.types]: [TYPES_MODULE_PATH], -}; - export const typeDocUtils = { isType(entity: TypeDocNode): boolean { return entity.kindString === KindString.Interface || @@ -56,65 +42,28 @@ export const typeDocUtils = { isPrivateOrProtectedProperty(propertyName: string): boolean { return _.startsWith(propertyName, '_'); }, - isPublicType(typeName: string): boolean { - return _.includes(constants.public0xjsTypes, typeName); - }, - getModuleDefinitionBySectionNameIfExists(versionDocObj: TypeDocNode, sectionName: string): + getModuleDefinitionBySectionNameIfExists(versionDocObj: TypeDocNode, modulePaths: string[]): TypeDocNode|undefined { - const possibleModulePathNames = sectionNameToPossibleModulePaths[sectionName]; const modules = versionDocObj.children; for (const mod of modules) { - if (_.includes(possibleModulePathNames, mod.name)) { + if (_.includes(modulePaths, mod.name)) { const moduleWithName = mod; return moduleWithName; } } return undefined; }, - getMenuSubsectionsBySection(docAgnosticFormat?: DocAgnosticFormat): MenuSubsectionsBySection { - const menuSubsectionsBySection = {} as MenuSubsectionsBySection; - if (_.isUndefined(docAgnosticFormat)) { - return menuSubsectionsBySection; - } - - const docSections = _.keys(ZeroExJsDocSections); - _.each(docSections, sectionName => { - const docSection = docAgnosticFormat[sectionName]; - if (_.isUndefined(docSection)) { - return; // no-op - } - - if (sectionName === ZeroExJsDocSections.types) { - const typeNames = _.map(docSection.types, t => t.name); - menuSubsectionsBySection[sectionName] = typeNames; - } else { - const methodNames = _.map(docSection.methods, m => m.name); - menuSubsectionsBySection[sectionName] = methodNames; - } - }); - return menuSubsectionsBySection; - }, - getFinal0xjsMenu(selectedVersion: string): {[section: string]: string[]} { - const finalMenu = _.cloneDeep(constants.menu0xjs); - finalMenu.contracts = _.filter(finalMenu.contracts, (contractName: string) => { - const versionIntroducedIfExists = constants.menuSubsectionToVersionWhenIntroduced[contractName]; - if (!_.isUndefined(versionIntroducedIfExists)) { - const existsInSelectedVersion = compareVersions(selectedVersion, - versionIntroducedIfExists) >= 0; - return existsInSelectedVersion; - } else { - return true; - } - }); - return finalMenu; - }, - convertToDocAgnosticFormat(typeDocJson: TypeDocNode): DocAgnosticFormat { - const subMenus = _.values(constants.menu0xjs); + 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 packageDefinitionIfExists = typeDocUtils.getModuleDefinitionBySectionNameIfExists( - typeDocJson, sectionName, + typeDocJson, modulePathsIfExists, ); if (_.isUndefined(packageDefinitionIfExists)) { return; // no-op @@ -125,7 +74,7 @@ export const typeDocUtils = { // for it. let entities; let packageComment = ''; - if (sectionName === ZeroExJsDocSections.types) { + if (sectionName === docsInfo.sections.types) { entities = packageDefinitionIfExists.children; } else { entities = packageDefinitionIfExists.children[0].children; @@ -133,13 +82,13 @@ export const typeDocUtils = { packageComment = !_.isUndefined(commentObj) ? commentObj.shortText : packageComment; } - const docSection = typeDocUtils._convertEntitiesToDocSection(entities, sectionName); + const docSection = typeDocUtils._convertEntitiesToDocSection(entities, docsInfo, sectionName); docSection.comment = packageComment; docAgnosticFormat[sectionName] = docSection; }); return docAgnosticFormat; }, - _convertEntitiesToDocSection(entities: TypeDocNode[], sectionName: string) { + _convertEntitiesToDocSection(entities: TypeDocNode[], docsInfo: DocsInfo, sectionName: string) { const docSection: DocSection = { comment: '', constructors: [], @@ -153,21 +102,25 @@ export const typeDocUtils = { switch (entity.kindString) { case KindString.Constructor: isConstructor = true; - const constructor = typeDocUtils._convertMethod(entity, isConstructor, sectionName); + const constructor = typeDocUtils._convertMethod( + entity, isConstructor, docsInfo.sections, sectionName, + ); docSection.constructors.push(constructor); break; case KindString.Method: if (entity.flags.isPublic) { isConstructor = false; - const method = typeDocUtils._convertMethod(entity, isConstructor, sectionName); + const method = typeDocUtils._convertMethod( + entity, isConstructor, docsInfo.sections, sectionName, + ); docSection.methods.push(method); } break; case KindString.Property: if (!typeDocUtils.isPrivateOrProtectedProperty(entity.name)) { - const property = typeDocUtils._convertProperty(entity, sectionName); + const property = typeDocUtils._convertProperty(entity, docsInfo.sections, sectionName); docSection.properties.push(property); } break; @@ -177,8 +130,8 @@ export const typeDocUtils = { case KindString.Variable: case KindString.Enumeration: case KindString['Type alias']: - if (typeDocUtils.isPublicType(entity.name)) { - const customType = typeDocUtils._convertCustomType(entity, sectionName); + if (docsInfo.isPublicType(entity.name)) { + const customType = typeDocUtils._convertCustomType(entity, docsInfo.sections, sectionName); docSection.types.push(customType); } break; @@ -189,16 +142,16 @@ export const typeDocUtils = { }); return docSection; }, - _convertCustomType(entity: TypeDocNode, sectionName: string): CustomType { + _convertCustomType(entity: TypeDocNode, sections: SectionsMap, sectionName: string): CustomType { const typeIfExists = !_.isUndefined(entity.type) ? - typeDocUtils._convertType(entity.type, sectionName) : + typeDocUtils._convertType(entity.type, sections, sectionName) : undefined; const isConstructor = false; const methodIfExists = !_.isUndefined(entity.declaration) ? - typeDocUtils._convertMethod(entity.declaration, isConstructor, sectionName) : + typeDocUtils._convertMethod(entity.declaration, isConstructor, sections, sectionName) : undefined; const indexSignatureIfExists = !_.isUndefined(entity.indexSignature) ? - typeDocUtils._convertIndexSignature(entity.indexSignature[0], sectionName) : + typeDocUtils._convertIndexSignature(entity.indexSignature[0], sections, sectionName) : undefined; const commentIfExists = !_.isUndefined(entity.comment) && !_.isUndefined(entity.comment.shortText) ? entity.comment.shortText : @@ -207,7 +160,7 @@ export const typeDocUtils = { const childrenIfExist = !_.isUndefined(entity.children) ? _.map(entity.children, (child: TypeDocNode) => { const childTypeIfExists = !_.isUndefined(child.type) ? - typeDocUtils._convertType(child.type, sectionName) : + typeDocUtils._convertType(child.type, sections, sectionName) : undefined; const c: CustomTypeChild = { name: child.name, @@ -230,21 +183,21 @@ export const typeDocUtils = { }; return customType; }, - _convertIndexSignature(entity: TypeDocNode, sectionName: string): IndexSignature { + _convertIndexSignature(entity: TypeDocNode, sections: SectionsMap, sectionName: string): IndexSignature { const key = entity.parameters[0]; const indexSignature = { keyName: key.name, - keyType: typeDocUtils._convertType(key.type, sectionName), + keyType: typeDocUtils._convertType(key.type, sections, sectionName), valueName: entity.type.name, }; return indexSignature; }, - _convertProperty(entity: TypeDocNode, sectionName: string): Property { + _convertProperty(entity: TypeDocNode, sections: SectionsMap, sectionName: 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, sectionName), + type: typeDocUtils._convertType(entity.type, sections, sectionName), source: { fileName: source.fileName, line: source.line, @@ -253,7 +206,9 @@ export const typeDocUtils = { }; return property; }, - _convertMethod(entity: TypeDocNode, isConstructor: boolean, sectionName: string): TypescriptMethod { + _convertMethod( + entity: TypeDocNode, isConstructor: boolean, sections: SectionsMap, sectionName: string, + ): TypescriptMethod { const signature = entity.signatures[0]; const source = entity.sources[0]; const hasComment = !_.isUndefined(signature.comment); @@ -262,18 +217,18 @@ export const typeDocUtils = { const topLevelInterface = isStatic ? 'ZeroEx.' : 'zeroEx.'; // 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 = (sectionName !== ZeroExJsDocSections.zeroEx) ? + let callPath = (!_.isUndefined(sections.zeroEx) && sectionName !== sections.zeroEx) ? `${topLevelInterface}${sectionName}.` : topLevelInterface; callPath = isConstructor ? '' : callPath; const parameters = _.map(signature.parameters, param => { - return typeDocUtils._convertParameter(param, sectionName); + return typeDocUtils._convertParameter(param, sections, sectionName); }); - const returnType = typeDocUtils._convertType(signature.type, sectionName); + const returnType = typeDocUtils._convertType(signature.type, sections, sectionName); const typeParameter = _.isUndefined(signature.typeParameter) ? undefined : - typeDocUtils._convertTypeParameter(signature.typeParameter[0], sectionName); + typeDocUtils._convertTypeParameter(signature.typeParameter[0], sections, sectionName); const method = { isConstructor, @@ -292,15 +247,15 @@ export const typeDocUtils = { }; return method; }, - _convertTypeParameter(entity: TypeDocNode, sectionName: string): TypeParameter { - const type = typeDocUtils._convertType(entity.type, sectionName); + _convertTypeParameter(entity: TypeDocNode, sections: SectionsMap, sectionName: string): TypeParameter { + const type = typeDocUtils._convertType(entity.type, sections, sectionName); const parameter = { name: entity.name, type, }; return parameter; }, - _convertParameter(entity: TypeDocNode, sectionName: string): Parameter { + _convertParameter(entity: TypeDocNode, sections: SectionsMap, sectionName: string): Parameter { let comment = '<No comment>'; if (entity.comment && entity.comment.shortText) { comment = entity.comment.shortText; @@ -312,7 +267,7 @@ export const typeDocUtils = { entity.flags.isOptional : false; - const type = typeDocUtils._convertType(entity.type, sectionName); + const type = typeDocUtils._convertType(entity.type, sections, sectionName); const parameter = { name: entity.name, @@ -322,17 +277,17 @@ export const typeDocUtils = { }; return parameter; }, - _convertType(entity: TypeDocType, sectionName: string): Type { + _convertType(entity: TypeDocType, sections: SectionsMap, sectionName: string): Type { const typeArguments = _.map(entity.typeArguments, typeArgument => { - return typeDocUtils._convertType(typeArgument, sectionName); + return typeDocUtils._convertType(typeArgument, sections, sectionName); }); const types = _.map(entity.types, t => { - return typeDocUtils._convertType(t, sectionName); + return typeDocUtils._convertType(t, sections, sectionName); }); const isConstructor = false; const methodIfExists = !_.isUndefined(entity.declaration) ? - typeDocUtils._convertMethod(entity.declaration, isConstructor, sectionName) : + typeDocUtils._convertMethod(entity.declaration, isConstructor, sections, sectionName) : undefined; const elementTypeIfExists = !_.isUndefined(entity.elementType) ? |