From c6dece6bd1e5f5afa56b290557eb7a6245c76cb6 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Tue, 30 Jan 2018 13:26:46 +0100 Subject: Add config file specifically in prettier command and fix files --- packages/website/ts/pages/about/about.tsx | 416 +++--- packages/website/ts/pages/about/profile.tsx | 116 +- .../website/ts/pages/documentation/comment.tsx | 16 +- .../website/ts/pages/documentation/custom_enum.tsx | 34 +- .../website/ts/pages/documentation/docs_info.ts | 198 +-- .../ts/pages/documentation/documentation.tsx | 648 ++++----- packages/website/ts/pages/documentation/enum.tsx | 26 +- .../ts/pages/documentation/event_definition.tsx | 132 +- .../website/ts/pages/documentation/interface.tsx | 98 +- .../ts/pages/documentation/method_block.tsx | 238 ++-- .../ts/pages/documentation/method_signature.tsx | 148 +- .../website/ts/pages/documentation/source_link.tsx | 38 +- packages/website/ts/pages/documentation/type.tsx | 354 ++--- .../ts/pages/documentation/type_definition.tsx | 194 +-- packages/website/ts/pages/faq/faq.tsx | 846 ++++++------ packages/website/ts/pages/faq/question.tsx | 76 +- packages/website/ts/pages/landing/landing.tsx | 1420 ++++++++++---------- packages/website/ts/pages/not_found.tsx | 52 +- packages/website/ts/pages/shared/anchor_title.tsx | 142 +- .../ts/pages/shared/markdown_code_block.tsx | 28 +- .../website/ts/pages/shared/markdown_section.tsx | 112 +- .../ts/pages/shared/nested_sidebar_menu.tsx | 268 ++-- .../website/ts/pages/shared/section_header.tsx | 72 +- .../website/ts/pages/shared/version_drop_down.tsx | 50 +- packages/website/ts/pages/wiki/wiki.tsx | 344 ++--- 25 files changed, 3033 insertions(+), 3033 deletions(-) (limited to 'packages/website/ts/pages') diff --git a/packages/website/ts/pages/about/about.tsx b/packages/website/ts/pages/about/about.tsx index 411456427..c929673f5 100644 --- a/packages/website/ts/pages/about/about.tsx +++ b/packages/website/ts/pages/about/about.tsx @@ -10,239 +10,239 @@ import { constants } from 'ts/utils/constants'; import { utils } from 'ts/utils/utils'; const teamRow1: ProfileInfo[] = [ - { - name: 'Will Warren', - title: 'Co-founder & CEO', - description: `Smart contract R&D. Previously applied physics at Los Alamos \ + { + name: 'Will Warren', + title: 'Co-founder & CEO', + description: `Smart contract R&D. Previously applied physics at Los Alamos \ Nat Lab. Mechanical engineering at UC San Diego. PhD dropout.`, - image: '/images/team/will.jpg', - linkedIn: 'https://www.linkedin.com/in/will-warren-92aab62b/', - github: 'https://github.com/willwarren89', - medium: 'https://medium.com/@willwarren89', - }, - { - name: 'Amir Bandeali', - title: 'Co-founder & CTO', - description: `Smart contract R&D. Previously fixed income trader at DRW. \ + image: '/images/team/will.jpg', + linkedIn: 'https://www.linkedin.com/in/will-warren-92aab62b/', + github: 'https://github.com/willwarren89', + medium: 'https://medium.com/@willwarren89', + }, + { + name: 'Amir Bandeali', + title: 'Co-founder & CTO', + description: `Smart contract R&D. Previously fixed income trader at DRW. \ Finance at University of Illinois, Urbana-Champaign.`, - image: '/images/team/amir.jpeg', - linkedIn: 'https://www.linkedin.com/in/abandeali1/', - github: 'https://github.com/abandeali1', - medium: 'https://medium.com/@abandeali1', - }, - { - name: 'Fabio Berger', - title: 'Senior Engineer', - description: `Full-stack blockchain engineer. Previously software engineer \ + image: '/images/team/amir.jpeg', + linkedIn: 'https://www.linkedin.com/in/abandeali1/', + github: 'https://github.com/abandeali1', + medium: 'https://medium.com/@abandeali1', + }, + { + name: 'Fabio Berger', + title: 'Senior Engineer', + description: `Full-stack blockchain engineer. Previously software engineer \ at Airtable and founder of WealthLift. Computer science at Duke.`, - image: '/images/team/fabio.jpg', - linkedIn: 'https://www.linkedin.com/in/fabio-berger-03ab261a/', - github: 'https://github.com/fabioberger', - medium: 'https://medium.com/@fabioberger', - }, + image: '/images/team/fabio.jpg', + linkedIn: 'https://www.linkedin.com/in/fabio-berger-03ab261a/', + github: 'https://github.com/fabioberger', + medium: 'https://medium.com/@fabioberger', + }, ]; const teamRow2: ProfileInfo[] = [ - { - name: 'Alex Xu', - title: 'Director of Operations', - description: `Strategy and operations. Previously digital marketing at Google \ + { + name: 'Alex Xu', + title: 'Director of Operations', + description: `Strategy and operations. Previously digital marketing at Google \ and vendor management at Amazon. Economics at UC San Diego.`, - image: '/images/team/alex.jpg', - linkedIn: 'https://www.linkedin.com/in/alex-xu/', - github: '', - medium: 'https://medium.com/@aqxu', - }, - { - name: 'Leonid Logvinov', - title: 'Engineer', - description: `Full-stack blockchain engineer. Previously blockchain engineer \ + image: '/images/team/alex.jpg', + linkedIn: 'https://www.linkedin.com/in/alex-xu/', + github: '', + medium: 'https://medium.com/@aqxu', + }, + { + name: 'Leonid Logvinov', + title: 'Engineer', + description: `Full-stack blockchain engineer. Previously blockchain engineer \ at Neufund. Computer science at University of Warsaw.`, - image: '/images/team/leonid.png', - linkedIn: 'https://www.linkedin.com/in/leonidlogvinov/', - github: 'https://github.com/LogvinovLeon', - medium: 'https://medium.com/@Logvinov', - }, - { - name: 'Ben Burns', - title: 'Designer', - description: `Product, motion, and graphic designer. Previously designer \ + image: '/images/team/leonid.png', + linkedIn: 'https://www.linkedin.com/in/leonidlogvinov/', + github: 'https://github.com/LogvinovLeon', + medium: 'https://medium.com/@Logvinov', + }, + { + name: 'Ben Burns', + title: 'Designer', + description: `Product, motion, and graphic designer. Previously designer \ at Airtable and Apple. Digital Design at University of Cincinnati.`, - image: '/images/team/ben.jpg', - linkedIn: 'https://www.linkedin.com/in/ben-burns-30170478/', - github: '', - medium: '', - }, + image: '/images/team/ben.jpg', + linkedIn: 'https://www.linkedin.com/in/ben-burns-30170478/', + github: '', + medium: '', + }, ]; const teamRow3: ProfileInfo[] = [ - { - name: 'Brandon Millman', - title: 'Senior Engineer', - description: `Full-stack engineer. Previously senior software engineer at \ + { + name: 'Brandon Millman', + title: 'Senior Engineer', + description: `Full-stack engineer. Previously senior software engineer at \ Twitter. Electrical and Computer Engineering at Duke.`, - image: '/images/team/brandon.png', - linkedIn: 'https://www.linkedin.com/in/brandon-millman-b093a022/', - github: 'https://github.com/BMillman19', - medium: 'https://medium.com/@bchillman', - }, - { - name: 'Tom Schmidt', - title: 'Product Manager', - description: `Previously engineering at Apple, product management at Facebook and Instagram. Computer Science at Stanford.`, - image: '/images/team/tom.jpg', - linkedIn: 'https://www.linkedin.com/in/tomhschmidt/', - github: 'https://github.com/tomhschmidt', - medium: '', - }, - { - name: 'Jacob Evans', - title: 'Blockchain Engineer', - description: `Previously software engineer at Qantas and RSA Security.`, - image: '/images/team/jacob.jpg', - linkedIn: 'https://www.linkedin.com/in/dekzter/', - github: 'https://github.com/dekz', - medium: '', - }, + image: '/images/team/brandon.png', + linkedIn: 'https://www.linkedin.com/in/brandon-millman-b093a022/', + github: 'https://github.com/BMillman19', + medium: 'https://medium.com/@bchillman', + }, + { + name: 'Tom Schmidt', + title: 'Product Manager', + description: `Previously engineering at Apple, product management at Facebook and Instagram. Computer Science at Stanford.`, + image: '/images/team/tom.jpg', + linkedIn: 'https://www.linkedin.com/in/tomhschmidt/', + github: 'https://github.com/tomhschmidt', + medium: '', + }, + { + name: 'Jacob Evans', + title: 'Blockchain Engineer', + description: `Previously software engineer at Qantas and RSA Security.`, + image: '/images/team/jacob.jpg', + linkedIn: 'https://www.linkedin.com/in/dekzter/', + github: 'https://github.com/dekz', + medium: '', + }, ]; const advisors: ProfileInfo[] = [ - { - name: 'Fred Ehrsam', - description: 'Co-founder of Coinbase. Previously FX trader at Goldman Sachs.', - image: '/images/advisors/fred.jpg', - linkedIn: 'https://www.linkedin.com/in/fredehrsam/', - medium: 'https://medium.com/@FEhrsam', - twitter: 'https://twitter.com/FEhrsam', - }, - { - name: 'Olaf Carlson-Wee', - image: '/images/advisors/olaf.png', - description: 'Founder of Polychain Capital. First hire at Coinbase. Angel investor.', - linkedIn: 'https://www.linkedin.com/in/olafcw/', - angellist: 'https://angel.co/olafcw', - }, - { - name: 'Joey Krug', - description: `Co-CIO at Pantera Capital. Founder of Augur. Thiel 20 Under 20 Fellow.`, - image: '/images/advisors/joey.jpg', - linkedIn: 'https://www.linkedin.com/in/joeykrug/', - github: 'https://github.com/joeykrug', - angellist: 'https://angel.co/joeykrug', - }, - { - name: 'Linda Xie', - description: 'Co-founder of Scalar Capital. Previously PM at Coinbase.', - image: '/images/advisors/linda.jpg', - linkedIn: 'https://www.linkedin.com/in/lindaxie/', - medium: 'https://medium.com/@linda.xie', - twitter: 'https://twitter.com/ljxie', - }, + { + name: 'Fred Ehrsam', + description: 'Co-founder of Coinbase. Previously FX trader at Goldman Sachs.', + image: '/images/advisors/fred.jpg', + linkedIn: 'https://www.linkedin.com/in/fredehrsam/', + medium: 'https://medium.com/@FEhrsam', + twitter: 'https://twitter.com/FEhrsam', + }, + { + name: 'Olaf Carlson-Wee', + image: '/images/advisors/olaf.png', + description: 'Founder of Polychain Capital. First hire at Coinbase. Angel investor.', + linkedIn: 'https://www.linkedin.com/in/olafcw/', + angellist: 'https://angel.co/olafcw', + }, + { + name: 'Joey Krug', + description: `Co-CIO at Pantera Capital. Founder of Augur. Thiel 20 Under 20 Fellow.`, + image: '/images/advisors/joey.jpg', + linkedIn: 'https://www.linkedin.com/in/joeykrug/', + github: 'https://github.com/joeykrug', + angellist: 'https://angel.co/joeykrug', + }, + { + name: 'Linda Xie', + description: 'Co-founder of Scalar Capital. Previously PM at Coinbase.', + image: '/images/advisors/linda.jpg', + linkedIn: 'https://www.linkedin.com/in/lindaxie/', + medium: 'https://medium.com/@linda.xie', + twitter: 'https://twitter.com/ljxie', + }, ]; export interface AboutProps { - source: string; - location: Location; + source: string; + location: Location; } interface AboutState {} const styles: Styles = { - header: { - fontFamily: 'Roboto Mono', - fontSize: 36, - color: 'black', - paddingTop: 110, - }, - weAreHiring: { - fontSize: 30, - color: colors.darkestGrey, - fontFamily: 'Roboto Mono', - letterSpacing: 7.5, - }, + header: { + fontFamily: 'Roboto Mono', + fontSize: 36, + color: 'black', + paddingTop: 110, + }, + weAreHiring: { + fontSize: 30, + color: colors.darkestGrey, + fontFamily: 'Roboto Mono', + letterSpacing: 7.5, + }, }; export class About extends React.Component { - public componentDidMount() { - window.scrollTo(0, 0); - } - public render() { - return ( -
- - -
-
-
About us:
-
- Our team is a diverse and globally distributed group with backgrounds in engineering, - research, business and design. We are passionate about decentralized technology and its - potential to act as an equalizing force in the world. -
-
-
-
{this._renderProfiles(teamRow1)}
-
{this._renderProfiles(teamRow2)}
-
{this._renderProfiles(teamRow3)}
-
-
-
- Advisors: -
-
{this._renderProfiles(advisors)}
-
-
-
- WE'RE HIRING -
-
- We are seeking outstanding candidates to{' '} - - join our team - - . We value passion, diversity and unique perspectives. -
-
-
-
-
- ); - } - private _renderProfiles(profiles: ProfileInfo[]) { - const numIndiv = profiles.length; - const colSize = utils.getColSize(numIndiv); - return _.map(profiles, profile => { - return ( -
- -
- ); - }); - } + public componentDidMount() { + window.scrollTo(0, 0); + } + public render() { + return ( +
+ + +
+
+
About us:
+
+ Our team is a diverse and globally distributed group with backgrounds in engineering, + research, business and design. We are passionate about decentralized technology and its + potential to act as an equalizing force in the world. +
+
+
+
{this._renderProfiles(teamRow1)}
+
{this._renderProfiles(teamRow2)}
+
{this._renderProfiles(teamRow3)}
+
+
+
+ Advisors: +
+
{this._renderProfiles(advisors)}
+
+
+
+ WE'RE HIRING +
+
+ We are seeking outstanding candidates to{' '} + + join our team + + . We value passion, diversity and unique perspectives. +
+
+
+
+
+ ); + } + private _renderProfiles(profiles: ProfileInfo[]) { + const numIndiv = profiles.length; + const colSize = utils.getColSize(numIndiv); + return _.map(profiles, profile => { + return ( +
+ +
+ ); + }); + } } diff --git a/packages/website/ts/pages/about/profile.tsx b/packages/website/ts/pages/about/profile.tsx index f1830851f..18b4e0d5a 100644 --- a/packages/website/ts/pages/about/profile.tsx +++ b/packages/website/ts/pages/about/profile.tsx @@ -5,75 +5,75 @@ import { colors } from 'ts/utils/colors'; const IMAGE_DIMENSION = 149; const styles: Styles = { - subheader: { - textTransform: 'uppercase', - fontSize: 32, - margin: 0, - }, - imageContainer: { - width: IMAGE_DIMENSION, - height: IMAGE_DIMENSION, - boxShadow: 'rgba(0, 0, 0, 0.19) 2px 5px 10px', - }, + subheader: { + textTransform: 'uppercase', + fontSize: 32, + margin: 0, + }, + imageContainer: { + width: IMAGE_DIMENSION, + height: IMAGE_DIMENSION, + boxShadow: 'rgba(0, 0, 0, 0.19) 2px 5px 10px', + }, }; interface ProfileProps { - colSize: number; - profileInfo: ProfileInfo; + colSize: number; + profileInfo: ProfileInfo; } export function Profile(props: ProfileProps) { - return ( -
-
-
- -
-
- {props.profileInfo.name} -
- {!_.isUndefined(props.profileInfo.title) && ( -
- {props.profileInfo.title.toUpperCase()} -
- )} -
- {props.profileInfo.description} -
-
- {renderSocialMediaIcons(props.profileInfo)} -
-
-
- ); + return ( +
+
+
+ +
+
+ {props.profileInfo.name} +
+ {!_.isUndefined(props.profileInfo.title) && ( +
+ {props.profileInfo.title.toUpperCase()} +
+ )} +
+ {props.profileInfo.description} +
+
+ {renderSocialMediaIcons(props.profileInfo)} +
+
+
+ ); } function renderSocialMediaIcons(profileInfo: ProfileInfo) { - const icons = [ - renderSocialMediaIcon('zmdi-github-box', profileInfo.github), - renderSocialMediaIcon('zmdi-linkedin-box', profileInfo.linkedIn), - renderSocialMediaIcon('zmdi-twitter-box', profileInfo.twitter), - ]; - return icons; + const icons = [ + renderSocialMediaIcon('zmdi-github-box', profileInfo.github), + renderSocialMediaIcon('zmdi-linkedin-box', profileInfo.linkedIn), + renderSocialMediaIcon('zmdi-twitter-box', profileInfo.twitter), + ]; + return icons; } function renderSocialMediaIcon(iconName: string, url: string) { - if (_.isEmpty(url)) { - return null; - } + if (_.isEmpty(url)) { + return null; + } - return ( -
- - - -
- ); + return ( +
+ + + +
+ ); } diff --git a/packages/website/ts/pages/documentation/comment.tsx b/packages/website/ts/pages/documentation/comment.tsx index 6be39f586..23cfd96bd 100644 --- a/packages/website/ts/pages/documentation/comment.tsx +++ b/packages/website/ts/pages/documentation/comment.tsx @@ -4,20 +4,20 @@ import * as ReactMarkdown from 'react-markdown'; import { MarkdownCodeBlock } from 'ts/pages/shared/markdown_code_block'; interface CommentProps { - comment: string; - className?: string; + comment: string; + className?: string; } const defaultProps = { - className: '', + className: '', }; export const Comment: React.SFC = (props: CommentProps) => { - return ( -
- -
- ); + return ( +
+ +
+ ); }; Comment.defaultProps = defaultProps; diff --git a/packages/website/ts/pages/documentation/custom_enum.tsx b/packages/website/ts/pages/documentation/custom_enum.tsx index 0006b8d7e..8d50a2f52 100644 --- a/packages/website/ts/pages/documentation/custom_enum.tsx +++ b/packages/website/ts/pages/documentation/custom_enum.tsx @@ -6,27 +6,27 @@ import { utils } from 'ts/utils/utils'; const STRING_ENUM_CODE_PREFIX = ' strEnum('; interface CustomEnumProps { - type: CustomType; + 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 ( - - {`{`} - {'\t'} - {enumValues} -
- {`}`} -
- ); + 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 ( + + {`{`} + {'\t'} + {enumValues} +
+ {`}`} +
+ ); } diff --git a/packages/website/ts/pages/documentation/docs_info.ts b/packages/website/ts/pages/documentation/docs_info.ts index e1080f3a0..4b1ec122a 100644 --- a/packages/website/ts/pages/documentation/docs_info.ts +++ b/packages/website/ts/pages/documentation/docs_info.ts @@ -1,111 +1,111 @@ import compareVersions = require('compare-versions'); import * as _ from 'lodash'; import { - DocAgnosticFormat, - DocsInfoConfig, - DocsMenu, - DoxityDocObj, - MenuSubsectionsBySection, - SectionsMap, - TypeDocNode, + DocAgnosticFormat, + DocsInfoConfig, + DocsMenu, + DoxityDocObj, + MenuSubsectionsBySection, + SectionsMap, + TypeDocNode, } from 'ts/types'; export class DocsInfo { - public displayName: string; - public packageUrl: string; - public subPackageName?: 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.displayName = config.displayName; - this.packageUrl = config.packageUrl; - this.subPackageName = config.subPackageName; - 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; - } + public displayName: string; + public packageUrl: string; + public subPackageName?: 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.displayName = config.displayName; + this.packageUrl = config.packageUrl; + this.subPackageName = config.subPackageName; + 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); - if (_.isUndefined(finalMenu.contracts)) { - return finalMenu; - } + 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; - } + // 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 - } + 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 {}; - } + 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); - } + 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/documentation.tsx b/packages/website/ts/pages/documentation/documentation.tsx index 0fc41d775..2315847ad 100644 --- a/packages/website/ts/pages/documentation/documentation.tsx +++ b/packages/website/ts/pages/documentation/documentation.tsx @@ -19,17 +19,17 @@ import { NestedSidebarMenu } from 'ts/pages/shared/nested_sidebar_menu'; import { SectionHeader } from 'ts/pages/shared/section_header'; import { Dispatcher } from 'ts/redux/dispatcher'; import { - AddressByContractName, - DocAgnosticFormat, - DoxityDocObj, - EtherscanLinkSuffixes, - Event, - Networks, - Property, - SolidityMethod, - Styles, - TypeDefinitionByName, - TypescriptMethod, + AddressByContractName, + DocAgnosticFormat, + DoxityDocObj, + EtherscanLinkSuffixes, + Event, + Networks, + Property, + SolidityMethod, + Styles, + TypeDefinitionByName, + TypescriptMethod, } from 'ts/types'; import { colors } from 'ts/utils/colors'; import { configs } from 'ts/utils/configs'; @@ -40,340 +40,340 @@ import { utils } from 'ts/utils/utils'; const SCROLL_TOP_ID = 'docsScrollTop'; const networkNameToColor: { [network: string]: string } = { - [Networks.kovan]: colors.purple, - [Networks.ropsten]: colors.red, - [Networks.mainnet]: colors.turquois, + [Networks.kovan]: colors.purple, + [Networks.ropsten]: colors.red, + [Networks.mainnet]: colors.turquois, }; export interface DocumentationAllProps { - source: string; - location: Location; - dispatcher: Dispatcher; - docsVersion: string; - availableDocVersions: string[]; - docsInfo: DocsInfo; + source: string; + location: Location; + dispatcher: Dispatcher; + docsVersion: string; + availableDocVersions: string[]; + docsInfo: DocsInfo; } interface DocumentationState { - docAgnosticFormat?: DocAgnosticFormat; + docAgnosticFormat?: DocAgnosticFormat; } const styles: Styles = { - mainContainers: { - position: 'absolute', - top: 1, - left: 0, - bottom: 0, - right: 0, - overflowZ: 'hidden', - overflowY: 'scroll', - minHeight: 'calc(100vh - 1px)', - WebkitOverflowScrolling: 'touch', - }, - menuContainer: { - borderColor: colors.grey300, - maxWidth: 330, - marginLeft: 20, - }, + mainContainers: { + position: 'absolute', + top: 1, + left: 0, + bottom: 0, + right: 0, + overflowZ: 'hidden', + overflowY: 'scroll', + minHeight: 'calc(100vh - 1px)', + WebkitOverflowScrolling: 'touch', + }, + menuContainer: { + borderColor: colors.grey300, + maxWidth: 330, + marginLeft: 20, + }, }; export class Documentation extends React.Component { - constructor(props: DocumentationAllProps) { - 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) - ? {} - : this.props.docsInfo.getMenuSubsectionsBySection(this.state.docAgnosticFormat); - return ( -
- - - {_.isUndefined(this.state.docAgnosticFormat) ? ( -
-
-
- -
-
- Loading documentation... -
-
-
- ) : ( -
-
-
- -
-
-
-
-
-

- - {this.props.docsInfo.displayName} - -

- {this._renderDocumentation()} -
-
-
- )} -
- ); - } - private _renderDocumentation(): React.ReactNode { - const subMenus = _.values(this.props.docsInfo.getMenu()); - const orderedSectionNames = _.flatten(subMenus); + constructor(props: DocumentationAllProps) { + 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) + ? {} + : this.props.docsInfo.getMenuSubsectionsBySection(this.state.docAgnosticFormat); + return ( +
+ + + {_.isUndefined(this.state.docAgnosticFormat) ? ( +
+
+
+ +
+
+ Loading documentation... +
+
+
+ ) : ( +
+
+
+ +
+
+
+
+
+

+ + {this.props.docsInfo.displayName} + +

+ {this._renderDocumentation()} +
+
+
+ )} +
+ ); + } + private _renderDocumentation(): React.ReactNode { + const subMenus = _.values(this.props.docsInfo.getMenu()); + const orderedSectionNames = _.flatten(subMenus); - const typeDefinitionByName = this.props.docsInfo.getTypeDefinitionsByName(this.state.docAgnosticFormat); - const renderedSections = _.map(orderedSectionNames, this._renderSection.bind(this, typeDefinitionByName)); + 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 markdownFileIfExists = this.props.docsInfo.sectionNameToMarkdown[sectionName]; - if (!_.isUndefined(markdownFileIfExists)) { - return ( - - ); - } + return renderedSections; + } + private _renderSection(typeDefinitionByName: TypeDefinitionByName, sectionName: string): React.ReactNode { + const markdownFileIfExists = this.props.docsInfo.sectionNameToMarkdown[sectionName]; + if (!_.isUndefined(markdownFileIfExists)) { + return ( + + ); + } - const docSection = this.state.docAgnosticFormat[sectionName]; - if (_.isUndefined(docSection)) { - return null; - } + const docSection = this.state.docAgnosticFormat[sectionName]; + if (_.isUndefined(docSection)) { + return null; + } - const sortedTypes = _.sortBy(docSection.types, 'name'); - const typeDefs = _.map(sortedTypes, customType => { - return ( - - ); - }); + const sortedTypes = _.sortBy(docSection.types, 'name'); + const typeDefs = _.map(sortedTypes, customType => { + return ( + + ); + }); - const sortedProperties = _.sortBy(docSection.properties, 'name'); - const propertyDefs = _.map(sortedProperties, this._renderProperty.bind(this, sectionName)); + 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 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 ( - - ); - }); - return ( -
-
-
- -
- {this._renderNetworkBadgesIfExists(sectionName)} -
- {docSection.comment && } - {docSection.constructors.length > 0 && - this.props.docsInfo.isVisibleConstructor(sectionName) && ( -
-

Constructor

- {this._renderConstructors(docSection.constructors, sectionName, typeDefinitionByName)} -
- )} - {docSection.properties.length > 0 && ( -
-

Properties

-
{propertyDefs}
-
- )} - {docSection.methods.length > 0 && ( -
-

Methods

-
{methodDefs}
-
- )} - {!_.isUndefined(docSection.events) && - docSection.events.length > 0 && ( -
-

Events

-
{eventDefs}
-
- )} - {!_.isUndefined(typeDefs) && - typeDefs.length > 0 && ( -
-
{typeDefs}
-
- )} -
- ); - } - private _renderNetworkBadgesIfExists(sectionName: string) { - const networkToAddressByContractName = configs.CONTRACT_ADDRESS[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.NETWORK_ID_BY_NAME[networkName], - EtherscanLinkSuffixes.Address, - ); - return ( - - - - ); - }, - ); - 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
{constructorDefs}
; - } - private _renderProperty(sectionName: string, property: Property): React.ReactNode { - return ( -
- - {property.name}: - - - {property.source && ( - - )} - {property.comment && } -
- ); - } - private _renderMethodBlocks( - method: SolidityMethod | TypescriptMethod, - sectionName: string, - isConstructor: boolean, - typeDefinitionByName: TypeDefinitionByName, - ): React.ReactNode { - return ( - - ); - } - private _scrollToHash(): void { - const hashWithPrefix = this.props.location.hash; - let hash = hashWithPrefix.slice(1); - if (_.isEmpty(hash)) { - hash = SCROLL_TOP_ID; // scroll to the top - } + const sortedEvents = _.sortBy(docSection.events, 'name'); + const eventDefs = _.map(sortedEvents, (event: Event, i: number) => { + return ( + + ); + }); + return ( +
+
+
+ +
+ {this._renderNetworkBadgesIfExists(sectionName)} +
+ {docSection.comment && } + {docSection.constructors.length > 0 && + this.props.docsInfo.isVisibleConstructor(sectionName) && ( +
+

Constructor

+ {this._renderConstructors(docSection.constructors, sectionName, typeDefinitionByName)} +
+ )} + {docSection.properties.length > 0 && ( +
+

Properties

+
{propertyDefs}
+
+ )} + {docSection.methods.length > 0 && ( +
+

Methods

+
{methodDefs}
+
+ )} + {!_.isUndefined(docSection.events) && + docSection.events.length > 0 && ( +
+

Events

+
{eventDefs}
+
+ )} + {!_.isUndefined(typeDefs) && + typeDefs.length > 0 && ( +
+
{typeDefs}
+
+ )} +
+ ); + } + private _renderNetworkBadgesIfExists(sectionName: string) { + const networkToAddressByContractName = configs.CONTRACT_ADDRESS[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.NETWORK_ID_BY_NAME[networkName], + EtherscanLinkSuffixes.Address, + ); + return ( + + + + ); + }, + ); + 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
{constructorDefs}
; + } + private _renderProperty(sectionName: string, property: Property): React.ReactNode { + return ( +
+ + {property.name}: + + + {property.source && ( + + )} + {property.comment && } +
+ ); + } + private _renderMethodBlocks( + method: SolidityMethod | TypescriptMethod, + sectionName: string, + isConstructor: boolean, + typeDefinitionByName: TypeDefinitionByName, + ): React.ReactNode { + return ( + + ); + } + private _scrollToHash(): void { + const hashWithPrefix = this.props.location.hash; + let hash = hashWithPrefix.slice(1); + if (_.isEmpty(hash)) { + hash = SCROLL_TOP_ID; // scroll to the top + } - scroller.scrollTo(hash, { - duration: 0, - offset: 0, - containerId: 'documentation', - }); - } - private async _fetchJSONDocsFireAndForgetAsync(preferredVersionIfExists?: string): Promise { - const versionToFileName = await docUtils.getVersionToFileNameAsync(this.props.docsInfo.docsJsonRoot); - const versions = _.keys(versionToFileName); - this.props.dispatcher.updateAvailableDocVersions(versions); - const sortedVersions = semverSort.desc(versions); - const latestVersion = sortedVersions[0]; + scroller.scrollTo(hash, { + duration: 0, + offset: 0, + containerId: 'documentation', + }); + } + private async _fetchJSONDocsFireAndForgetAsync(preferredVersionIfExists?: string): Promise { + const versionToFileName = await docUtils.getVersionToFileNameAsync(this.props.docsInfo.docsJsonRoot); + 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); + 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, - this.props.docsInfo.docsJsonRoot, - ); - const docAgnosticFormat = this.props.docsInfo.convertToDocAgnosticFormat(versionDocObj as DoxityDocObj); + const versionFileNameToFetch = versionToFileName[versionToFetch]; + const versionDocObj = await docUtils.getJSONDocFileAsync( + versionFileNameToFetch, + this.props.docsInfo.docsJsonRoot, + ); + const docAgnosticFormat = this.props.docsInfo.convertToDocAgnosticFormat(versionDocObj as DoxityDocObj); - this.setState( - { - docAgnosticFormat, - }, - () => { - this._scrollToHash(); - }, - ); - } + this.setState( + { + docAgnosticFormat, + }, + () => { + this._scrollToHash(); + }, + ); + } } diff --git a/packages/website/ts/pages/documentation/enum.tsx b/packages/website/ts/pages/documentation/enum.tsx index cfcc7f8d7..7dfdee771 100644 --- a/packages/website/ts/pages/documentation/enum.tsx +++ b/packages/website/ts/pages/documentation/enum.tsx @@ -3,20 +3,20 @@ import * as React from 'react'; import { EnumValue } from 'ts/types'; interface EnumProps { - values: EnumValue[]; + 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 ( - - {`{`} - {values} -
- {`}`} -
- ); + const values = _.map(props.values, (value, i) => { + const defaultValueIfAny = !_.isUndefined(value.defaultValue) ? ` = ${value.defaultValue}` : ''; + return `\n\t${value.name}${defaultValueIfAny},`; + }); + return ( + + {`{`} + {values} +
+ {`}`} +
+ ); } diff --git a/packages/website/ts/pages/documentation/event_definition.tsx b/packages/website/ts/pages/documentation/event_definition.tsx index 9274ae512..0e53e38e7 100644 --- a/packages/website/ts/pages/documentation/event_definition.tsx +++ b/packages/website/ts/pages/documentation/event_definition.tsx @@ -7,76 +7,76 @@ import { Event, EventArg, HeaderSizes } from 'ts/types'; import { colors } from 'ts/utils/colors'; interface EventDefinitionProps { - event: Event; - sectionName: string; - docsInfo: DocsInfo; + event: Event; + sectionName: string; + docsInfo: DocsInfo; } interface EventDefinitionState { - shouldShowAnchor: boolean; + shouldShowAnchor: boolean; } export class EventDefinition extends React.Component { - constructor(props: EventDefinitionProps) { - super(props); - this.state = { - shouldShowAnchor: false, - }; - } - public render() { - const event = this.props.event; - return ( -
- -
-
-						{this._renderEventCode()}
-					
-
-
- ); - } - private _renderEventCode() { - const indexed = indexed; - const eventArgs = _.map(this.props.event.eventArgs, (eventArg: EventArg) => { - const type = ( - - ); - return ( - - {eventArg.name} - {eventArg.isIndexed ? indexed : ''}: {type}, - - ); - }); - const argList = _.reduce(eventArgs, (prev: React.ReactNode, curr: React.ReactNode) => { - return [prev, '\n\t', curr]; - }); - return ( - - {`{`} -
- {'\t'} - {argList} -
- {`}`} -
- ); - } - private _setAnchorVisibility(shouldShowAnchor: boolean) { - this.setState({ - shouldShowAnchor, - }); - } + constructor(props: EventDefinitionProps) { + super(props); + this.state = { + shouldShowAnchor: false, + }; + } + public render() { + const event = this.props.event; + return ( +
+ +
+
+                        {this._renderEventCode()}
+                    
+
+
+ ); + } + private _renderEventCode() { + const indexed = indexed; + const eventArgs = _.map(this.props.event.eventArgs, (eventArg: EventArg) => { + const type = ( + + ); + return ( + + {eventArg.name} + {eventArg.isIndexed ? indexed : ''}: {type}, + + ); + }); + const argList = _.reduce(eventArgs, (prev: React.ReactNode, curr: React.ReactNode) => { + return [prev, '\n\t', curr]; + }); + return ( + + {`{`} +
+ {'\t'} + {argList} +
+ {`}`} +
+ ); + } + private _setAnchorVisibility(shouldShowAnchor: boolean) { + this.setState({ + shouldShowAnchor, + }); + } } diff --git a/packages/website/ts/pages/documentation/interface.tsx b/packages/website/ts/pages/documentation/interface.tsx index ee07a2c50..16a772125 100644 --- a/packages/website/ts/pages/documentation/interface.tsx +++ b/packages/website/ts/pages/documentation/interface.tsx @@ -6,56 +6,56 @@ import { Type } from 'ts/pages/documentation/type'; import { CustomType, TypeDocTypes } from 'ts/types'; interface InterfaceProps { - type: CustomType; - sectionName: string; - docsInfo: DocsInfo; + type: CustomType; + sectionName: string; + docsInfo: DocsInfo; } export function Interface(props: InterfaceProps) { - const type = props.type; - const properties = _.map(type.children, property => { - return ( - - {property.name}:{' '} - {property.type.typeDocType !== TypeDocTypes.Reflection ? ( - - ) : ( - - )}, - - ); - }); - const hasIndexSignature = !_.isUndefined(type.indexSignature); - if (hasIndexSignature) { - const is = type.indexSignature; - const param = ( - - {is.keyName}: - - ); - properties.push( - - [{param}]: {is.valueName}, - , - ); - } - const propertyList = _.reduce(properties, (prev: React.ReactNode, curr: React.ReactNode) => { - return [prev, '\n\t', curr]; - }); - return ( - - {`{`} -
- {'\t'} - {propertyList} -
- {`}`} -
- ); + const type = props.type; + const properties = _.map(type.children, property => { + return ( + + {property.name}:{' '} + {property.type.typeDocType !== TypeDocTypes.Reflection ? ( + + ) : ( + + )}, + + ); + }); + const hasIndexSignature = !_.isUndefined(type.indexSignature); + if (hasIndexSignature) { + const is = type.indexSignature; + const param = ( + + {is.keyName}: + + ); + properties.push( + + [{param}]: {is.valueName}, + , + ); + } + const propertyList = _.reduce(properties, (prev: React.ReactNode, curr: React.ReactNode) => { + return [prev, '\n\t', curr]; + }); + return ( + + {`{`} +
+ {'\t'} + {propertyList} +
+ {`}`} +
+ ); } diff --git a/packages/website/ts/pages/documentation/method_block.tsx b/packages/website/ts/pages/documentation/method_block.tsx index fb03cf5be..dfde5931b 100644 --- a/packages/website/ts/pages/documentation/method_block.tsx +++ b/packages/website/ts/pages/documentation/method_block.tsx @@ -10,133 +10,133 @@ import { colors } from 'ts/utils/colors'; import { typeDocUtils } from 'ts/utils/typedoc_utils'; interface MethodBlockProps { - method: SolidityMethod | TypescriptMethod; - sectionName: string; - libraryVersion: string; - typeDefinitionByName: TypeDefinitionByName; - docsInfo: DocsInfo; + method: SolidityMethod | TypescriptMethod; + sectionName: string; + libraryVersion: string; + typeDefinitionByName: TypeDefinitionByName; + docsInfo: DocsInfo; } interface MethodBlockState { - shouldShowAnchor: boolean; + shouldShowAnchor: boolean; } const styles: Styles = { - chip: { - fontSize: 13, - backgroundColor: colors.lightBlueA700, - color: colors.white, - height: 11, - borderRadius: 14, - marginTop: 19, - lineHeight: 0.8, - }, + chip: { + fontSize: 13, + backgroundColor: colors.lightBlueA700, + color: colors.white, + height: 11, + borderRadius: 14, + marginTop: 19, + lineHeight: 0.8, + }, }; export class MethodBlock extends React.Component { - constructor(props: MethodBlockProps) { - super(props); - this.state = { - shouldShowAnchor: false, - }; - } - public render() { - const method = this.props.method; - if (typeDocUtils.isPrivateOrProtectedProperty(method.name)) { - return null; - } + constructor(props: MethodBlockProps) { + super(props); + this.state = { + shouldShowAnchor: false, + }; + } + public render() { + const method = this.props.method; + if (typeDocUtils.isPrivateOrProtectedProperty(method.name)) { + return null; + } - return ( -
- {!method.isConstructor && ( -
- {(method as TypescriptMethod).isStatic && this._renderChip('Static')} - {(method as SolidityMethod).isConstant && this._renderChip('Constant')} - {(method as SolidityMethod).isPayable && this._renderChip('Payable')} - -
- )} - - - - {(method as TypescriptMethod).source && ( - - )} - {method.comment && } - {method.parameters && - !_.isEmpty(method.parameters) && ( -
-

- ARGUMENTS -

- {this._renderParameterDescriptions(method.parameters)} -
- )} - {method.returnComment && ( -
-

- RETURNS -

- -
- )} -
- ); - } - private _renderChip(text: string) { - return ( -
- {text} -
- ); - } - private _renderParameterDescriptions(parameters: Parameter[]) { - const descriptions = _.map(parameters, parameter => { - const isOptional = parameter.isOptional; - return ( -
-
-
{parameter.name}
-
- {isOptional && 'optional'} -
-
-
- {parameter.comment && } -
-
- ); - }); - return descriptions; - } - private _setAnchorVisibility(shouldShowAnchor: boolean) { - this.setState({ - shouldShowAnchor, - }); - } + return ( +
+ {!method.isConstructor && ( +
+ {(method as TypescriptMethod).isStatic && this._renderChip('Static')} + {(method as SolidityMethod).isConstant && this._renderChip('Constant')} + {(method as SolidityMethod).isPayable && this._renderChip('Payable')} + +
+ )} + + + + {(method as TypescriptMethod).source && ( + + )} + {method.comment && } + {method.parameters && + !_.isEmpty(method.parameters) && ( +
+

+ ARGUMENTS +

+ {this._renderParameterDescriptions(method.parameters)} +
+ )} + {method.returnComment && ( +
+

+ RETURNS +

+ +
+ )} +
+ ); + } + private _renderChip(text: string) { + return ( +
+ {text} +
+ ); + } + private _renderParameterDescriptions(parameters: Parameter[]) { + const descriptions = _.map(parameters, parameter => { + const isOptional = parameter.isOptional; + return ( +
+
+
{parameter.name}
+
+ {isOptional && 'optional'} +
+
+
+ {parameter.comment && } +
+
+ ); + }); + return descriptions; + } + private _setAnchorVisibility(shouldShowAnchor: boolean) { + this.setState({ + shouldShowAnchor, + }); + } } diff --git a/packages/website/ts/pages/documentation/method_signature.tsx b/packages/website/ts/pages/documentation/method_signature.tsx index 7c6bf96d2..041dcd093 100644 --- a/packages/website/ts/pages/documentation/method_signature.tsx +++ b/packages/website/ts/pages/documentation/method_signature.tsx @@ -6,94 +6,94 @@ import { Parameter, SolidityMethod, TypeDefinitionByName, TypescriptMethod } fro import { constants } from 'ts/utils/constants'; interface MethodSignatureProps { - method: TypescriptMethod | SolidityMethod; - sectionName: string; - shouldHideMethodName?: boolean; - shouldUseArrowSyntax?: boolean; - typeDefinitionByName?: TypeDefinitionByName; - docsInfo: DocsInfo; + method: TypescriptMethod | SolidityMethod; + sectionName: string; + shouldHideMethodName?: boolean; + shouldUseArrowSyntax?: boolean; + typeDefinitionByName?: TypeDefinitionByName; + docsInfo: DocsInfo; } const defaultProps = { - shouldHideMethodName: false, - shouldUseArrowSyntax: false, + shouldHideMethodName: false, + shouldUseArrowSyntax: false, }; export const MethodSignature: React.SFC = (props: MethodSignatureProps) => { - const sectionName = constants.TYPES_SECTION_NAME; - const parameters = renderParameters(props.method, props.docsInfo, sectionName, 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.docsInfo, sectionName, props.typeDefinitionByName); - return ( - - {props.method.callPath} - {methodName} - {typeParameterIfExists}({paramString}) - {props.shouldUseArrowSyntax ? ' => ' : ': '}{' '} - {props.method.returnType && ( - - )} - - ); + const sectionName = constants.TYPES_SECTION_NAME; + const parameters = renderParameters(props.method, props.docsInfo, sectionName, 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.docsInfo, sectionName, props.typeDefinitionByName); + return ( + + {props.method.callPath} + {methodName} + {typeParameterIfExists}({paramString}) + {props.shouldUseArrowSyntax ? ' => ' : ': '}{' '} + {props.method.returnType && ( + + )} + + ); }; MethodSignature.defaultProps = defaultProps; function renderParameters( - method: TypescriptMethod | SolidityMethod, - docsInfo: DocsInfo, - sectionName: string, - typeDefinitionByName?: TypeDefinitionByName, + 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 = ( - - ); - return ( - - {p.name} - {isOptional && '?'}: {type} - - ); - }); - return params; + const parameters = method.parameters; + const params = _.map(parameters, (p: Parameter) => { + const isOptional = p.isOptional; + const type = ( + + ); + return ( + + {p.name} + {isOptional && '?'}: {type} + + ); + }); + return params; } function renderTypeParameter( - method: TypescriptMethod, - docsInfo: DocsInfo, - sectionName: string, - typeDefinitionByName?: TypeDefinitionByName, + method: TypescriptMethod, + docsInfo: DocsInfo, + sectionName: string, + typeDefinitionByName?: TypeDefinitionByName, ) { - const typeParameter = method.typeParameter; - const typeParam = ( - - {`<${typeParameter.name} extends `} - - {`>`} - - ); - return typeParam; + const typeParameter = method.typeParameter; + const typeParam = ( + + {`<${typeParameter.name} extends `} + + {`>`} + + ); + return typeParam; } diff --git a/packages/website/ts/pages/documentation/source_link.tsx b/packages/website/ts/pages/documentation/source_link.tsx index 32126b7da..6588ee39e 100644 --- a/packages/website/ts/pages/documentation/source_link.tsx +++ b/packages/website/ts/pages/documentation/source_link.tsx @@ -4,28 +4,28 @@ import { Source } from 'ts/types'; import { colors } from 'ts/utils/colors'; interface SourceLinkProps { - source: Source; - baseUrl: string; - version: string; - subPackageName: string; + source: Source; + baseUrl: string; + version: string; + subPackageName: string; } const packagesWithNamespace = ['connect']; export function SourceLink(props: SourceLinkProps) { - const src = props.source; - const url = props.baseUrl; - const pkg = props.subPackageName; - let tagPrefix = pkg; - if (_.includes(packagesWithNamespace, pkg)) { - tagPrefix = `@0xproject/${pkg}`; - } - const sourceCodeUrl = `${url}/blob/${tagPrefix}%40${props.version}/packages/${pkg}/${src.fileName}#L${src.line}`; - return ( - - ); + const src = props.source; + const url = props.baseUrl; + const pkg = props.subPackageName; + let tagPrefix = pkg; + if (_.includes(packagesWithNamespace, pkg)) { + tagPrefix = `@0xproject/${pkg}`; + } + const sourceCodeUrl = `${url}/blob/${tagPrefix}%40${props.version}/packages/${pkg}/${src.fileName}#L${src.line}`; + return ( + + ); } diff --git a/packages/website/ts/pages/documentation/type.tsx b/packages/website/ts/pages/documentation/type.tsx index 9a2696e22..e989e7129 100644 --- a/packages/website/ts/pages/documentation/type.tsx +++ b/packages/website/ts/pages/documentation/type.tsx @@ -11,202 +11,202 @@ import { utils } from 'ts/utils/utils'; // 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, + 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', + 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', + ExchangeWrapper: 'exchange', + TokenWrapper: 'token', + TokenRegistryWrapper: 'tokenRegistry', + EtherTokenWrapper: 'etherToken', + ProxyWrapper: 'proxy', + TokenTransferProxyWrapper: 'proxy', + OrderStateWatcher: 'orderWatcher', }; interface TypeProps { - type: TypeDef; - docsInfo: DocsInfo; - sectionName: string; - typeDefinitionByName?: TypeDefinitionByName; + type: TypeDef; + docsInfo: DocsInfo; + sectionName: string; + typeDefinitionByName?: TypeDefinitionByName; } // The return type needs to be `any` here so that we can recursively define components within // 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; + 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 ( - - [] - - ); - } else { - const subType = ( - - ); - return subType; - } - }); - 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 ( + + [] + + ); + } else { + const subType = ( + + ); + return subType; + } + }); + break; - case TypeDocTypes.StringLiteral: - typeName = `'${type.value}'`; - typeNameColor = colors.green; - break; + case TypeDocTypes.StringLiteral: + typeName = `'${type.value}'`; + typeNameColor = colors.green; + break; - case TypeDocTypes.Array: - typeName = type.elementType.name; - break; + case TypeDocTypes.Array: + typeName = type.elementType.name; + break; - case TypeDocTypes.Union: - const unionTypes = _.map(type.types, t => { - return ( - - ); - }); - typeName = _.reduce(unionTypes, (prev: React.ReactNode, curr: React.ReactNode) => { - return [prev, '|', curr]; - }); - break; + case TypeDocTypes.Union: + const unionTypes = _.map(type.types, t => { + return ( + + ); + }); + typeName = _.reduce(unionTypes, (prev: React.ReactNode, curr: React.ReactNode) => { + return [prev, '|', curr]; + }); + break; - case TypeDocTypes.TypeParameter: - typeName = type.name; - break; + case TypeDocTypes.TypeParameter: + typeName = type.name; + 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]; - }); + 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 = ( - - {!_.isUndefined(typePrefixIfExists) ? `${typePrefixIfExists}.` : ''} - {typeName} - - ); - } 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 = ( - - {_.isUndefined(typeDefinition) || utils.isUserOnMobile() ? ( - - {typeName} - - ) : ( - - {typeName} - - - - - )} - - ); - } - return ( - - {typeName} - {isArray && '[]'} - {!_.isEmpty(typeArgs) && ( - - {'<'} - {commaSeparatedTypeArgs} - {'>'} - - )} - - ); + const typeNameUrlIfExists = typeToUrl[typeName as string]; + const typePrefixIfExists = typePrefix[typeName as string]; + const sectionNameIfExists = typeToSection[typeName as string]; + if (!_.isUndefined(typeNameUrlIfExists)) { + typeName = ( + + {!_.isUndefined(typePrefixIfExists) ? `${typePrefixIfExists}.` : ''} + {typeName} + + ); + } 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 = ( + + {_.isUndefined(typeDefinition) || utils.isUserOnMobile() ? ( + + {typeName} + + ) : ( + + {typeName} + + + + + )} + + ); + } + return ( + + {typeName} + {isArray && '[]'} + {!_.isEmpty(typeArgs) && ( + + {'<'} + {commaSeparatedTypeArgs} + {'>'} + + )} + + ); } diff --git a/packages/website/ts/pages/documentation/type_definition.tsx b/packages/website/ts/pages/documentation/type_definition.tsx index 356926157..d46eec76c 100644 --- a/packages/website/ts/pages/documentation/type_definition.tsx +++ b/packages/website/ts/pages/documentation/type_definition.tsx @@ -13,113 +13,113 @@ import { colors } from 'ts/utils/colors'; import { utils } from 'ts/utils/utils'; interface TypeDefinitionProps { - sectionName: string; - customType: CustomType; - shouldAddId?: boolean; - docsInfo: DocsInfo; + sectionName: string; + customType: CustomType; + shouldAddId?: boolean; + docsInfo: DocsInfo; } interface TypeDefinitionState { - shouldShowAnchor: boolean; + shouldShowAnchor: boolean; } export class TypeDefinition extends React.Component { - public static defaultProps: Partial = { - 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 - } + public static defaultProps: Partial = { + 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 = ( - - ); - break; + let typePrefix: string; + let codeSnippet: React.ReactNode; + switch (customType.kindString) { + case KindString.Interface: + typePrefix = 'Interface'; + codeSnippet = ( + + ); + break; - case KindString.Variable: - typePrefix = 'Enum'; - codeSnippet = ; - break; + case KindString.Variable: + typePrefix = 'Enum'; + codeSnippet = ; + break; - case KindString.Enumeration: - typePrefix = 'Enum'; - const enumValues = _.map(customType.children, (c: CustomTypeChild) => { - return { - name: c.name, - defaultValue: c.defaultValue, - }; - }); - codeSnippet = ; - break; + case KindString.Enumeration: + typePrefix = 'Enum'; + const enumValues = _.map(customType.children, (c: CustomTypeChild) => { + return { + name: c.name, + defaultValue: c.defaultValue, + }; + }); + codeSnippet = ; + break; - case KindString.TypeAlias: - typePrefix = 'Type Alias'; - codeSnippet = ( - - type {customType.name} ={' '} - {customType.type.typeDocType !== TypeDocTypes.Reflection ? ( - - ) : ( - - )} - - ); - break; + case KindString.TypeAlias: + typePrefix = 'Type Alias'; + codeSnippet = ( + + type {customType.name} ={' '} + {customType.type.typeDocType !== TypeDocTypes.Reflection ? ( + + ) : ( + + )} + + ); + break; - default: - throw utils.spawnSwitchErr('type.kindString', customType.kindString); - } + default: + throw utils.spawnSwitchErr('type.kindString', customType.kindString); + } - const typeDefinitionAnchorId = `${this.props.sectionName}-${customType.name}`; - return ( -
- -
-
-						{codeSnippet}
-					
-
- {customType.comment && } -
- ); - } - private _setAnchorVisibility(shouldShowAnchor: boolean) { - this.setState({ - shouldShowAnchor, - }); - } + const typeDefinitionAnchorId = `${this.props.sectionName}-${customType.name}`; + return ( +
+ +
+
+                        {codeSnippet}
+                    
+
+ {customType.comment && } +
+ ); + } + private _setAnchorVisibility(shouldShowAnchor: boolean) { + this.setState({ + shouldShowAnchor, + }); + } } diff --git a/packages/website/ts/pages/faq/faq.tsx b/packages/website/ts/pages/faq/faq.tsx index f437f5a8d..b4b5214a2 100644 --- a/packages/website/ts/pages/faq/faq.tsx +++ b/packages/website/ts/pages/faq/faq.tsx @@ -10,438 +10,438 @@ import { configs } from 'ts/utils/configs'; import { constants } from 'ts/utils/constants'; export interface FAQProps { - source: string; - location: Location; + source: string; + location: Location; } interface FAQState {} const styles: Styles = { - thin: { - fontWeight: 100, - }, + thin: { + fontWeight: 100, + }, }; const sections: FAQSection[] = [ - { - name: '0x Protocol', - questions: [ - { - prompt: 'What is 0x?', - answer: ( -
- At its core, 0x is an open and non-rent seeking protocol that facilitates trustless, low - friction exchange of Ethereum-based assets. Developers can use 0x as a platform to build - exchange applications on top of ( - 0x.js - {' '} - is a Javascript library for interacting with the 0x protocol). For end users, 0x will be the - infrastructure of a wide variety of user-facing applications i.e.{' '} - - 0x Portal - , a decentralized application that facilitates trustless trading of Ethereum-based tokens - between known counterparties. -
- ), - }, - { - prompt: 'What problem does 0x solve?', - answer: ( -
- In the two years since the Ethereum blockchain’s genesis block, numerous decentralized - applications (dApps) have created Ethereum smart contracts for peer-to-peer exchange. Rapid - iteration and a lack of best practices have left the blockchain scattered with proprietary and - application-specific implementations. As a result, end users are exposed to numerous smart - contracts of varying quality and security, with unique configuration processes and learning - curves, all of which implement the same functionality. This approach imposes unnecessary costs - on the network by fragmenting end users according to the particular dApp each user happens to be - using, eliminating valuable network effects around liquidity. 0x is the solution to this problem - by acting as modular, unopinionated building blocks that may be assembled and reconfigured. -
- ), - }, - { - prompt: 'How is 0x different from a centralized exchange like Poloniex or ShapeShift?', - answer: ( -
-
    -
  • 0x is a protocol for exchange, not a user-facing exchange application.
  • -
  • - 0x is decentralized and trustless; there is no central party which can be hacked, run - away with customer funds or be subjected to government regulations. Hacks of Mt. Gox, - Shapeshift and Bitfinex have demonstrated that these types of systemic risks are - palpable. -
  • -
  • - Rather than a proprietary system that exists to extract rent for its owners, 0x is - public infrastructure that is funded by a globally distributed community of - stakeholders. While the protocol is free to use, it enables for-profit user-facing - exchange applications to be built on top of the protocol. -
  • -
-
- ), - }, - { - prompt: 'If 0x protocol is free to use, where do transaction fees come in?', - answer: ( -
- 0x protocol uses off-chain order books to massively reduce friction costs for market makers and - ensure that the blockchain is only used for trade settlement. Hosting and maintaining an - off-chain order book is a service; to incent “Relayers” to provide this service they must be - able to charge transaction fees on trading activity. Relayers are free to set their transaction - fees to any value they desire. We expect Relayers to be highly competitive and transaction fees - to approach an efficient economic equilibrium over time. -
- ), - }, - { - prompt: 'What are the differences between 0x protocol and state channels?', - answer: ( -
-
- Participants in a state channel pass cryptographically signed messages back and forth, - accumulating intermediate state changes without publishing them to the canonical chain until - the channel is closed. State channels are ideal for “bar tab” applications where numerous - intermediate state changes may be accumulated off-chain before being settled by a final - on-chain transaction (i.e. day trading, poker, turn-based games). -
-
    -
  • - While state channels drastically reduce the number of on-chain transactions for specific - use cases, numerous on-chain transactions and a security deposit are required to open - and safely close a state channel making them less efficient than 0x for executing - one-time trades. -
  • -
  • - State channels are isolated from the Ethereum blockchain meaning that they cannot - interact with smart contracts. 0x is designed to be integrated directly into smart - contracts so trades can be executed programmatically in a single line of Solidity code. -
  • -
-
- ), - }, - { - prompt: 'What types of digital assets are supported by 0x?', - answer: ( -
- 0x supports all Ethereum-based assets that adhere to the ERC20 token standard. There are many - ERC20 tokens, worth a combined $2.2B, and more tokens are created each month. We believe that, - by 2020, thousands of assets will be tokenized and moved onto the Ethereum blockchain including - traditional securities such as equities, bonds and derivatives, fiat currencies and scarce - digital goods such as video game items. In the future, cross-blockchain solutions such as{' '} - - Cosmos - {' '} - and{' '} - - Polkadot - {' '} - will allow cryptocurrencies to freely move between blockchains and, naturally, currencies such - as Bitcoin will end up being represented as ERC20 tokens on the Ethereum blockchain. -
- ), - }, - { - prompt: '0x is open source: what prevents someone from forking the protocol?', - answer: ( -
- Ethereum and Bitcoin are both open source protocols. Each protocol has been forked, but the - resulting clone networks have seen little adoption (as measured by transaction count or market - cap). This is because users have little to no incentive to switch over to a clone network if the - original has initial network effects and a talented developer team behind it. An exception is in - the case that a protocol includes a controversial feature such as a method of rent extraction or - a monetary policy that favors one group of users over another (Zcash developer subsidy - for - better or worse - resulted in Zclassic). Perceived inequality can provide a strong enough - incentive that users will fork the original protocol’s codebase and spin up a new network that - eliminates the controversial feature. In the case of 0x, there is no rent extraction and no - users are given special permissions. 0x protocol is upgradable. Cutting-edge technical - capabilities can be integrated into 0x via decentralized governance (see section below), - eliminating incentives to fork off of the original protocol and sacrifice the network effects - surrounding liquidity that result from the shared protocol and settlement layer. -
- ), - }, - ], - }, - { - name: '0x Token (ZRX)', - questions: [ - { - prompt: 'Explain how the 0x protocol token (zrx) works.', - answer: ( -
-
- 0x protocol token (ZRX) is utilized in two ways: 1) to solve the{' '} - - coordination problem - {' '} - and drive network effects around liquidity, creating a feedback loop where early adopters of - the protocol benefit from wider adoption and 2) to be used for decentralized governance over - 0x protocol's update mechanism. In more detail: -
-
    -
  • - ZRX tokens are used by Makers and Takers (market participants that generate and consume - orders, respectively) to pay transaction fees to Relayers (entities that host and - maintain public order books). -
  • -
  • - ZRX tokens are used for decentralized governance over 0x protocol’s update mechanism - which allows its underlying smart contracts to be replaced and improved over time. An - update mechanism is needed because 0x is built upon Ethereum’s rapidly evolving - technology stack, decentralized governance is needed because 0x protocol’s smart - contracts will have access to user funds and numerous dApps will need to plug into 0x - smart contracts. Decentralized governance ensures that this update process is secure and - minimizes disruption to the network. -
  • -
-
- ), - }, - { - prompt: 'Why must transaction fees be denominated in 0x token (ZRX) rather than ETH?', - answer: ( -
- 0x protocol’s decentralized update mechanism is analogous to proof-of-stake. To maximize the - alignment of stakeholder and end user incentives, the staked asset must provide utility within - the protocol. -
- ), - }, - { - prompt: 'How will decentralized governance work?', - answer: ( -
- Decentralized governance is an ongoing focus of research; it will involve token voting with ZRX. - Ultimately the solution will maximize security while also maximizing the protocol’s ability to - absorb new innovations. Until the governance structure is formalized and encoded within 0x DAO, - a multi-sig will be used as a placeholder. -
- ), - }, - ], - }, - { - name: 'ZRX Token Launch and Fund Use', - questions: [ - { - prompt: 'What is the total supply of ZRX tokens?', - answer:
1,000,000,000 ZRX. Fixed supply.
, - }, - { - prompt: 'When is the Token Launch? will there be a pre-sale?', - answer:
The token launch will be on August 15th, 2017. There will not be a pre-sale.
, - }, - { - prompt: 'What will the token launch proceeds be used for?', - answer: ( -
- 100% of the proceeds raised in the token launch will be used to fund the development of free and - open source software, tools and infrastructure that support the protocol and surrounding - ecosystem. Check out our{' '} - - development roadmap - . -
- ), - }, - { - prompt: 'What will be the initial distribution of ZRX tokens?', - answer: ( -
-
- -
-
-
Token Launch (50%)
-
- ZRX is inherently a governance token that plays a critical role in the process of - upgrading 0x protocol. We are fully committed to formulating a functional and - theoretically sound governance model and we plan to dedicate significant resources to - R&D. -
-
-
-
Retained by 0x (15%)
-
- The 0x core development team will be able to sustain itself for approximately five years - using funds raised through the token launch. If 0x protocol proves to be as foundational - a technology as we believe it to be, the retained ZRX tokens will allow the 0x core - development team to sustain operations beyond the first 5 years. -
-
-
-
Developer Fund (15%)
-
- The Developer Fund will be used to make targeted capital injections into high potential - projects and teams that are attempting to grow the 0x ecosystem, strategic partnerships, - hackathon prizes and community development activities. -
-
-
-
Founding Team (10%)
-
- The founding team’s allocation of ZRX will vest over a traditional 4 year vesting - schedule with a one year cliff. We believe this should be standard practice for any team - that is committed to making their project a long term success. -
-
-
-
Early Backers & Advisors (10%)
-
- Our backers and advisors have provided capital, resources and guidance that have allowed - us to fill out our team, setup a robust legal entity and build a fully functional - product before launching a token. As a result, we have a proven track record and can - offer a token that holds genuine utility. -
-
-
- ), - }, - { - prompt: 'Can I mine ZRX tokens?', - answer: ( -
- No, the total supply of ZRX tokens is fixed and there is no continuous issuance model. Users - that facilitate trading over 0x protocol by operating a Relayer earn transaction fees - denominated in ZRX; as more trading activity is generated, more transaction fees are earned. -
- ), - }, - { - prompt: 'Will there be a lockup period for ZRX tokens sold in the token launch?', - answer:
No, ZRX tokens sold in the token launch will immediately be liquid.
, - }, - { - prompt: 'Will there be a lockup period for tokens allocated to the founding team?', - answer: ( -
- Yes. ZRX tokens allocated to founders, advisors and staff members will be released over a 4 year - vesting schedule with a 25% cliff upon completion of the initial token launch and 25% released - each subsequent year in monthly installments. Staff members hired after the token launch will - have a 4 year vesting schedule with a one year cliff. -
- ), - }, - { - prompt: 'Which cryptocurrencies will be accepted in the token launch?', - answer:
ETH.
, - }, - { - prompt: 'When will 0x be live?', - answer: ( -
- An alpha version of 0x has been live on our private test network since January 2017. Version 1.0 - of 0x protocol will be deployed to the canonical Ethereum blockchain after a round of security - audits and prior to the public token launch. 0x will be using the 0x protocol during our token - launch. -
- ), - }, - { - prompt: 'Where can I find a development roadmap?', - answer: ( -
- Check it out{' '} - - here - . -
- ), - }, - ], - }, - { - name: 'Team', - questions: [ - { - prompt: 'Where is 0x based?', - answer:
0x was founded in SF and is driven by a diverse group of contributors.
, - }, - { - prompt: 'How can I get involved?', - answer: ( -
- Join our{' '} - - Rocket.chat - ! As an open source project, 0x will rely on a worldwide community of passionate developers - to contribute proposals, ideas and code. -
- ), - }, - { - prompt: 'Why the name 0x?', - answer: ( -
- 0x is the prefix for hexadecimal numeric constants including Ethereum addresses. In a more - abstract context, as the first open protocol for exchange 0x represents the beginning of the end - for the exchange industry’s rent seeking oligopoly: zero exchange. -
- ), - }, - { - prompt: 'How do you pronounce 0x?', - answer:
We pronounce 0x as “zero-ex,” but you are free to pronounce it however you please.
, - }, - ], - }, + { + name: '0x Protocol', + questions: [ + { + prompt: 'What is 0x?', + answer: ( +
+ At its core, 0x is an open and non-rent seeking protocol that facilitates trustless, low + friction exchange of Ethereum-based assets. Developers can use 0x as a platform to build + exchange applications on top of ( + 0x.js + {' '} + is a Javascript library for interacting with the 0x protocol). For end users, 0x will be the + infrastructure of a wide variety of user-facing applications i.e.{' '} + + 0x Portal + , a decentralized application that facilitates trustless trading of Ethereum-based tokens + between known counterparties. +
+ ), + }, + { + prompt: 'What problem does 0x solve?', + answer: ( +
+ In the two years since the Ethereum blockchain’s genesis block, numerous decentralized + applications (dApps) have created Ethereum smart contracts for peer-to-peer exchange. Rapid + iteration and a lack of best practices have left the blockchain scattered with proprietary and + application-specific implementations. As a result, end users are exposed to numerous smart + contracts of varying quality and security, with unique configuration processes and learning + curves, all of which implement the same functionality. This approach imposes unnecessary costs + on the network by fragmenting end users according to the particular dApp each user happens to be + using, eliminating valuable network effects around liquidity. 0x is the solution to this problem + by acting as modular, unopinionated building blocks that may be assembled and reconfigured. +
+ ), + }, + { + prompt: 'How is 0x different from a centralized exchange like Poloniex or ShapeShift?', + answer: ( +
+
    +
  • 0x is a protocol for exchange, not a user-facing exchange application.
  • +
  • + 0x is decentralized and trustless; there is no central party which can be hacked, run + away with customer funds or be subjected to government regulations. Hacks of Mt. Gox, + Shapeshift and Bitfinex have demonstrated that these types of systemic risks are + palpable. +
  • +
  • + Rather than a proprietary system that exists to extract rent for its owners, 0x is + public infrastructure that is funded by a globally distributed community of + stakeholders. While the protocol is free to use, it enables for-profit user-facing + exchange applications to be built on top of the protocol. +
  • +
+
+ ), + }, + { + prompt: 'If 0x protocol is free to use, where do transaction fees come in?', + answer: ( +
+ 0x protocol uses off-chain order books to massively reduce friction costs for market makers and + ensure that the blockchain is only used for trade settlement. Hosting and maintaining an + off-chain order book is a service; to incent “Relayers” to provide this service they must be + able to charge transaction fees on trading activity. Relayers are free to set their transaction + fees to any value they desire. We expect Relayers to be highly competitive and transaction fees + to approach an efficient economic equilibrium over time. +
+ ), + }, + { + prompt: 'What are the differences between 0x protocol and state channels?', + answer: ( +
+
+ Participants in a state channel pass cryptographically signed messages back and forth, + accumulating intermediate state changes without publishing them to the canonical chain until + the channel is closed. State channels are ideal for “bar tab” applications where numerous + intermediate state changes may be accumulated off-chain before being settled by a final + on-chain transaction (i.e. day trading, poker, turn-based games). +
+
    +
  • + While state channels drastically reduce the number of on-chain transactions for specific + use cases, numerous on-chain transactions and a security deposit are required to open + and safely close a state channel making them less efficient than 0x for executing + one-time trades. +
  • +
  • + State channels are isolated from the Ethereum blockchain meaning that they cannot + interact with smart contracts. 0x is designed to be integrated directly into smart + contracts so trades can be executed programmatically in a single line of Solidity code. +
  • +
+
+ ), + }, + { + prompt: 'What types of digital assets are supported by 0x?', + answer: ( +
+ 0x supports all Ethereum-based assets that adhere to the ERC20 token standard. There are many + ERC20 tokens, worth a combined $2.2B, and more tokens are created each month. We believe that, + by 2020, thousands of assets will be tokenized and moved onto the Ethereum blockchain including + traditional securities such as equities, bonds and derivatives, fiat currencies and scarce + digital goods such as video game items. In the future, cross-blockchain solutions such as{' '} + + Cosmos + {' '} + and{' '} + + Polkadot + {' '} + will allow cryptocurrencies to freely move between blockchains and, naturally, currencies such + as Bitcoin will end up being represented as ERC20 tokens on the Ethereum blockchain. +
+ ), + }, + { + prompt: '0x is open source: what prevents someone from forking the protocol?', + answer: ( +
+ Ethereum and Bitcoin are both open source protocols. Each protocol has been forked, but the + resulting clone networks have seen little adoption (as measured by transaction count or market + cap). This is because users have little to no incentive to switch over to a clone network if the + original has initial network effects and a talented developer team behind it. An exception is in + the case that a protocol includes a controversial feature such as a method of rent extraction or + a monetary policy that favors one group of users over another (Zcash developer subsidy - for + better or worse - resulted in Zclassic). Perceived inequality can provide a strong enough + incentive that users will fork the original protocol’s codebase and spin up a new network that + eliminates the controversial feature. In the case of 0x, there is no rent extraction and no + users are given special permissions. 0x protocol is upgradable. Cutting-edge technical + capabilities can be integrated into 0x via decentralized governance (see section below), + eliminating incentives to fork off of the original protocol and sacrifice the network effects + surrounding liquidity that result from the shared protocol and settlement layer. +
+ ), + }, + ], + }, + { + name: '0x Token (ZRX)', + questions: [ + { + prompt: 'Explain how the 0x protocol token (zrx) works.', + answer: ( +
+
+ 0x protocol token (ZRX) is utilized in two ways: 1) to solve the{' '} + + coordination problem + {' '} + and drive network effects around liquidity, creating a feedback loop where early adopters of + the protocol benefit from wider adoption and 2) to be used for decentralized governance over + 0x protocol's update mechanism. In more detail: +
+
    +
  • + ZRX tokens are used by Makers and Takers (market participants that generate and consume + orders, respectively) to pay transaction fees to Relayers (entities that host and + maintain public order books). +
  • +
  • + ZRX tokens are used for decentralized governance over 0x protocol’s update mechanism + which allows its underlying smart contracts to be replaced and improved over time. An + update mechanism is needed because 0x is built upon Ethereum’s rapidly evolving + technology stack, decentralized governance is needed because 0x protocol’s smart + contracts will have access to user funds and numerous dApps will need to plug into 0x + smart contracts. Decentralized governance ensures that this update process is secure and + minimizes disruption to the network. +
  • +
+
+ ), + }, + { + prompt: 'Why must transaction fees be denominated in 0x token (ZRX) rather than ETH?', + answer: ( +
+ 0x protocol’s decentralized update mechanism is analogous to proof-of-stake. To maximize the + alignment of stakeholder and end user incentives, the staked asset must provide utility within + the protocol. +
+ ), + }, + { + prompt: 'How will decentralized governance work?', + answer: ( +
+ Decentralized governance is an ongoing focus of research; it will involve token voting with ZRX. + Ultimately the solution will maximize security while also maximizing the protocol’s ability to + absorb new innovations. Until the governance structure is formalized and encoded within 0x DAO, + a multi-sig will be used as a placeholder. +
+ ), + }, + ], + }, + { + name: 'ZRX Token Launch and Fund Use', + questions: [ + { + prompt: 'What is the total supply of ZRX tokens?', + answer:
1,000,000,000 ZRX. Fixed supply.
, + }, + { + prompt: 'When is the Token Launch? will there be a pre-sale?', + answer:
The token launch will be on August 15th, 2017. There will not be a pre-sale.
, + }, + { + prompt: 'What will the token launch proceeds be used for?', + answer: ( +
+ 100% of the proceeds raised in the token launch will be used to fund the development of free and + open source software, tools and infrastructure that support the protocol and surrounding + ecosystem. Check out our{' '} + + development roadmap + . +
+ ), + }, + { + prompt: 'What will be the initial distribution of ZRX tokens?', + answer: ( +
+
+ +
+
+
Token Launch (50%)
+
+ ZRX is inherently a governance token that plays a critical role in the process of + upgrading 0x protocol. We are fully committed to formulating a functional and + theoretically sound governance model and we plan to dedicate significant resources to + R&D. +
+
+
+
Retained by 0x (15%)
+
+ The 0x core development team will be able to sustain itself for approximately five years + using funds raised through the token launch. If 0x protocol proves to be as foundational + a technology as we believe it to be, the retained ZRX tokens will allow the 0x core + development team to sustain operations beyond the first 5 years. +
+
+
+
Developer Fund (15%)
+
+ The Developer Fund will be used to make targeted capital injections into high potential + projects and teams that are attempting to grow the 0x ecosystem, strategic partnerships, + hackathon prizes and community development activities. +
+
+
+
Founding Team (10%)
+
+ The founding team’s allocation of ZRX will vest over a traditional 4 year vesting + schedule with a one year cliff. We believe this should be standard practice for any team + that is committed to making their project a long term success. +
+
+
+
Early Backers & Advisors (10%)
+
+ Our backers and advisors have provided capital, resources and guidance that have allowed + us to fill out our team, setup a robust legal entity and build a fully functional + product before launching a token. As a result, we have a proven track record and can + offer a token that holds genuine utility. +
+
+
+ ), + }, + { + prompt: 'Can I mine ZRX tokens?', + answer: ( +
+ No, the total supply of ZRX tokens is fixed and there is no continuous issuance model. Users + that facilitate trading over 0x protocol by operating a Relayer earn transaction fees + denominated in ZRX; as more trading activity is generated, more transaction fees are earned. +
+ ), + }, + { + prompt: 'Will there be a lockup period for ZRX tokens sold in the token launch?', + answer:
No, ZRX tokens sold in the token launch will immediately be liquid.
, + }, + { + prompt: 'Will there be a lockup period for tokens allocated to the founding team?', + answer: ( +
+ Yes. ZRX tokens allocated to founders, advisors and staff members will be released over a 4 year + vesting schedule with a 25% cliff upon completion of the initial token launch and 25% released + each subsequent year in monthly installments. Staff members hired after the token launch will + have a 4 year vesting schedule with a one year cliff. +
+ ), + }, + { + prompt: 'Which cryptocurrencies will be accepted in the token launch?', + answer:
ETH.
, + }, + { + prompt: 'When will 0x be live?', + answer: ( +
+ An alpha version of 0x has been live on our private test network since January 2017. Version 1.0 + of 0x protocol will be deployed to the canonical Ethereum blockchain after a round of security + audits and prior to the public token launch. 0x will be using the 0x protocol during our token + launch. +
+ ), + }, + { + prompt: 'Where can I find a development roadmap?', + answer: ( +
+ Check it out{' '} + + here + . +
+ ), + }, + ], + }, + { + name: 'Team', + questions: [ + { + prompt: 'Where is 0x based?', + answer:
0x was founded in SF and is driven by a diverse group of contributors.
, + }, + { + prompt: 'How can I get involved?', + answer: ( +
+ Join our{' '} + + Rocket.chat + ! As an open source project, 0x will rely on a worldwide community of passionate developers + to contribute proposals, ideas and code. +
+ ), + }, + { + prompt: 'Why the name 0x?', + answer: ( +
+ 0x is the prefix for hexadecimal numeric constants including Ethereum addresses. In a more + abstract context, as the first open protocol for exchange 0x represents the beginning of the end + for the exchange industry’s rent seeking oligopoly: zero exchange. +
+ ), + }, + { + prompt: 'How do you pronounce 0x?', + answer:
We pronounce 0x as “zero-ex,” but you are free to pronounce it however you please.
, + }, + ], + }, ]; export class FAQ extends React.Component { - public componentDidMount() { - window.scrollTo(0, 0); - } - public render() { - return ( -
- - -
-

- 0x FAQ -

-
{this._renderSections()}
-
-
-
- ); - } - private _renderSections() { - const renderedSections = _.map(sections, (section: FAQSection, i: number) => { - const isFirstSection = i === 0; - return ( -
-

{section.name}

- {this._renderQuestions(section.questions, isFirstSection)} -
- ); - }); - return renderedSections; - } - private _renderQuestions(questions: FAQQuestion[], isFirstSection: boolean) { - const renderedQuestions = _.map(questions, (question: FAQQuestion, i: number) => { - const isFirstQuestion = i === 0; - return ( - - ); - }); - return renderedQuestions; - } + public componentDidMount() { + window.scrollTo(0, 0); + } + public render() { + return ( +
+ + +
+

+ 0x FAQ +

+
{this._renderSections()}
+
+
+
+ ); + } + private _renderSections() { + const renderedSections = _.map(sections, (section: FAQSection, i: number) => { + const isFirstSection = i === 0; + return ( +
+

{section.name}

+ {this._renderQuestions(section.questions, isFirstSection)} +
+ ); + }); + return renderedSections; + } + private _renderQuestions(questions: FAQQuestion[], isFirstSection: boolean) { + const renderedQuestions = _.map(questions, (question: FAQQuestion, i: number) => { + const isFirstQuestion = i === 0; + return ( + + ); + }); + return renderedQuestions; + } } diff --git a/packages/website/ts/pages/faq/question.tsx b/packages/website/ts/pages/faq/question.tsx index 58cf674ef..988c04bc9 100644 --- a/packages/website/ts/pages/faq/question.tsx +++ b/packages/website/ts/pages/faq/question.tsx @@ -4,48 +4,48 @@ import * as React from 'react'; import { colors } from 'ts/utils/colors'; export interface QuestionProps { - prompt: string; - answer: React.ReactNode; - shouldDisplayExpanded: boolean; + prompt: string; + answer: React.ReactNode; + shouldDisplayExpanded: boolean; } interface QuestionState { - isExpanded: boolean; + isExpanded: boolean; } export class Question extends React.Component { - constructor(props: QuestionProps) { - super(props); - this.state = { - isExpanded: props.shouldDisplayExpanded, - }; - } - public render() { - return ( -
- - - -
{this.props.answer}
-
-
-
- ); - } - private _onExchangeChange() { - this.setState({ - isExpanded: !this.state.isExpanded, - }); - } + constructor(props: QuestionProps) { + super(props); + this.state = { + isExpanded: props.shouldDisplayExpanded, + }; + } + public render() { + return ( +
+ + + +
{this.props.answer}
+
+
+
+ ); + } + private _onExchangeChange() { + this.setState({ + isExpanded: !this.state.isExpanded, + }); + } } diff --git a/packages/website/ts/pages/landing/landing.tsx b/packages/website/ts/pages/landing/landing.tsx index 742d94a0f..ca76497df 100644 --- a/packages/website/ts/pages/landing/landing.tsx +++ b/packages/website/ts/pages/landing/landing.tsx @@ -11,755 +11,755 @@ import { constants } from 'ts/utils/constants'; import { utils } from 'ts/utils/utils'; interface BoxContent { - title: string; - description: string; - imageUrl: string; - classNames: string; + title: string; + description: string; + imageUrl: string; + classNames: string; } interface AssetType { - title: string; - imageUrl: string; - style?: React.CSSProperties; + title: string; + imageUrl: string; + style?: React.CSSProperties; } interface UseCase { - imageUrl: string; - type: string; - description: string; - classNames: string; - style?: React.CSSProperties; - projectIconUrls: string[]; + imageUrl: string; + type: string; + description: string; + classNames: string; + style?: React.CSSProperties; + projectIconUrls: string[]; } interface Project { - logoFileName: string; - projectUrl: string; + logoFileName: string; + projectUrl: string; } const THROTTLE_TIMEOUT = 100; const boxContents: BoxContent[] = [ - { - title: 'Trustless exchange', - description: - "Built on Ethereum's distributed network with no centralized \ + { + title: 'Trustless exchange', + description: + "Built on Ethereum's distributed network with no centralized \ point of failure and no down time, each trade is settled atomically \ and without counterparty risk.", - imageUrl: '/images/landing/distributed_network.png', - classNames: '', - }, - { - title: 'Shared liquidity', - description: - 'By sharing a standard API, relayers can easily aggregate liquidity pools, \ + imageUrl: '/images/landing/distributed_network.png', + classNames: '', + }, + { + title: 'Shared liquidity', + description: + 'By sharing a standard API, relayers can easily aggregate liquidity pools, \ creating network effects around liquidity that compound as more relayers come online.', - imageUrl: '/images/landing/liquidity.png', - classNames: 'mx-auto', - }, - { - title: 'Open source', - description: - '0x is open source, permissionless and free to use. Trade directly with a known \ + imageUrl: '/images/landing/liquidity.png', + classNames: 'mx-auto', + }, + { + title: 'Open source', + description: + '0x is open source, permissionless and free to use. Trade directly with a known \ counterparty for free or pay a relayer some ZRX tokens to access their liquidity \ pool.', - imageUrl: '/images/landing/open_source.png', - classNames: 'right', - }, + imageUrl: '/images/landing/open_source.png', + classNames: 'right', + }, ]; const projects: Project[] = [ - { - logoFileName: 'ethfinex-top.png', - projectUrl: constants.PROJECT_URL_ETHFINEX, - }, - { - logoFileName: 'radar_relay_top.png', - projectUrl: constants.PROJECT_URL_RADAR_RELAY, - }, - { - logoFileName: 'paradex_top.png', - projectUrl: constants.PROJECT_URL_PARADEX, - }, - { - logoFileName: 'the_ocean.png', - projectUrl: constants.PROJECT_URL_0CEAN, - }, - { - logoFileName: 'dydx.png', - projectUrl: constants.PROJECT_URL_DYDX, - }, - { - logoFileName: 'melonport.png', - projectUrl: constants.PROJECT_URL_MELONPORT, - }, - { - logoFileName: 'maker.png', - projectUrl: constants.PROJECT_URL_MAKER, - }, - { - logoFileName: 'dharma.png', - projectUrl: constants.PROJECT_URL_DHARMA, - }, - { - logoFileName: 'lendroid.png', - projectUrl: constants.PROJECT_URL_LENDROID, - }, - { - logoFileName: 'district0x.png', - projectUrl: constants.PROJECT_URL_DISTRICT_0X, - }, - { - logoFileName: 'aragon.png', - projectUrl: constants.PROJECT_URL_ARAGON, - }, - { - logoFileName: 'blocknet.png', - projectUrl: constants.PROJECT_URL_BLOCKNET, - }, - { - logoFileName: 'status.png', - projectUrl: constants.PROJECT_URL_STATUS, - }, - { - logoFileName: 'augur.png', - projectUrl: constants.PROJECT_URL_AUGUR, - }, - { - logoFileName: 'anx.png', - projectUrl: constants.PROJECT_URL_OPEN_ANX, - }, - { - logoFileName: 'auctus.png', - projectUrl: constants.PROJECT_URL_AUCTUS, - }, + { + logoFileName: 'ethfinex-top.png', + projectUrl: constants.PROJECT_URL_ETHFINEX, + }, + { + logoFileName: 'radar_relay_top.png', + projectUrl: constants.PROJECT_URL_RADAR_RELAY, + }, + { + logoFileName: 'paradex_top.png', + projectUrl: constants.PROJECT_URL_PARADEX, + }, + { + logoFileName: 'the_ocean.png', + projectUrl: constants.PROJECT_URL_0CEAN, + }, + { + logoFileName: 'dydx.png', + projectUrl: constants.PROJECT_URL_DYDX, + }, + { + logoFileName: 'melonport.png', + projectUrl: constants.PROJECT_URL_MELONPORT, + }, + { + logoFileName: 'maker.png', + projectUrl: constants.PROJECT_URL_MAKER, + }, + { + logoFileName: 'dharma.png', + projectUrl: constants.PROJECT_URL_DHARMA, + }, + { + logoFileName: 'lendroid.png', + projectUrl: constants.PROJECT_URL_LENDROID, + }, + { + logoFileName: 'district0x.png', + projectUrl: constants.PROJECT_URL_DISTRICT_0X, + }, + { + logoFileName: 'aragon.png', + projectUrl: constants.PROJECT_URL_ARAGON, + }, + { + logoFileName: 'blocknet.png', + projectUrl: constants.PROJECT_URL_BLOCKNET, + }, + { + logoFileName: 'status.png', + projectUrl: constants.PROJECT_URL_STATUS, + }, + { + logoFileName: 'augur.png', + projectUrl: constants.PROJECT_URL_AUGUR, + }, + { + logoFileName: 'anx.png', + projectUrl: constants.PROJECT_URL_OPEN_ANX, + }, + { + logoFileName: 'auctus.png', + projectUrl: constants.PROJECT_URL_AUCTUS, + }, ]; export interface LandingProps { - location: Location; + location: Location; } interface LandingState { - screenWidth: ScreenWidths; + screenWidth: ScreenWidths; } export class Landing extends React.Component { - private _throttledScreenWidthUpdate: () => void; - constructor(props: LandingProps) { - super(props); - this.state = { - screenWidth: utils.getScreenWidth(), - }; - this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT); - } - public componentDidMount() { - window.addEventListener('resize', this._throttledScreenWidthUpdate); - window.scrollTo(0, 0); - } - public componentWillUnmount() { - window.removeEventListener('resize', this._throttledScreenWidthUpdate); - } - public render() { - return ( -
- - - {this._renderHero()} - {this._renderProjects()} - {this._renderTokenizationSection()} - {this._renderProtocolSection()} - {this._renderInfoBoxes()} - {this._renderBuildingBlocksSection()} - {this._renderUseCases()} - {this._renderCallToAction()} -
-
- ); - } - private _renderHero() { - const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; - const buttonLabelStyle: React.CSSProperties = { - textTransform: 'none', - fontSize: isSmallScreen ? 12 : 14, - fontWeight: 400, - }; - const lightButtonStyle: React.CSSProperties = { - borderRadius: 6, - border: '1px solid #D8D8D8', - lineHeight: '33px', - height: 38, - }; - const left = 'col lg-col-7 md-col-7 col-12 lg-pt4 md-pt4 sm-pt0 mt1 lg-pl4 md-pl4 sm-pl0 sm-px3 sm-center'; - return ( -
-
-
-
- -
-
-
-
- Powering decentralized exchange -
-
- 0x is an open, permissionless protocol allowing for ERC20 tokens to be traded on the - Ethereum blockchain. -
-
-
- - - -
-
- - - -
-
-
-
-
-
-
- ); - } - private _renderProjects() { - const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; - const isMediumScreen = this.state.screenWidth === ScreenWidths.Md; - const projectList = _.map(projects, (project: Project, i: number) => { - const colWidth = isSmallScreen ? 3 : isMediumScreen ? 4 : 2 - i % 2; - return ( -
-
- - - -
-
- ); - }); - const titleStyle: React.CSSProperties = { - fontFamily: 'Roboto Mono', - color: colors.grey, - textTransform: 'uppercase', - fontWeight: 300, - letterSpacing: 3, - }; - return ( -
-
-
- Projects building on 0x -
-
{projectList}
-
- view the{' '} - - full list - -
-
-
- ); - } - private _renderTokenizationSection() { - const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; - return ( -
-
- {isSmallScreen && this._renderTokenCloud()} -
-
-
- The world's value is becoming tokenized -
-
- {isSmallScreen ? ( - - The Ethereum blockchain is an open, borderless financial system that represents - a wide variety of assets as cryptographic tokens. In the future, most digital - assets and goods will be tokenized. - - ) : ( -
-
- The Ethereum blockchain is an open, borderless financial system that - represents -
-
- a wide variety of assets as cryptographic tokens. In the future, most - digital assets and goods will be tokenized. -
-
- )} -
-
{this._renderAssetTypes()}
-
-
- {!isSmallScreen && this._renderTokenCloud()} -
-
- ); - } - private _renderProtocolSection() { - const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; - return ( -
-
-
- -
-
-
-
Off-chain order relay
-
On-chain settlement
-
-
- In 0x protocol, orders are transported off-chain, massively reducing gas costs and - eliminating blockchain bloat. Relayers help broadcast orders and collect a fee each time - they facilitate a trade. Anyone can build a relayer. -
-
-
-
- RELAYERS BUILDING ON 0X -
-
- - view all - -
-
-
-
- -
-
- -
-
- -
-
-
-
-
-
- ); - } - private _renderBuildingBlocksSection() { - const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; - const descriptionStyle: React.CSSProperties = { - fontFamily: 'Roboto Mono', - lineHeight: isSmallScreen ? 1.5 : 2, - fontWeight: 300, - fontSize: 15, - maxWidth: isSmallScreen ? 375 : 'none', - }; - const callToActionStyle: React.CSSProperties = { - fontFamily: 'Roboto Mono', - fontSize: 15, - fontWeight: 300, - maxWidth: isSmallScreen ? 375 : 441, - }; - return ( -
-
- {isSmallScreen && this._renderBlockChipImage()} -
-
- A building block for dApps -
-
- 0x protocol is a pluggable building block for dApps that require exchange functionality. - Join the many developers that are already using 0x in their web applications and smart - contracts. -
-
- Learn how in our{' '} - - 0x.js - {' '} - and{' '} - - smart contract - {' '} - docs -
-
- {!isSmallScreen && this._renderBlockChipImage()} -
-
- ); - } - private _renderBlockChipImage() { - const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; - return ( -
- -
- ); - } - private _renderTokenCloud() { - const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; - return ( -
- -
- ); - } - private _renderAssetTypes() { - const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; - const assetTypes: AssetType[] = [ - { - title: 'Currency', - imageUrl: '/images/landing/currency.png', - }, - { - title: 'Traditional assets', - imageUrl: '/images/landing/stocks.png', - style: { - paddingLeft: isSmallScreen ? 41 : 56, - paddingRight: isSmallScreen ? 41 : 56, - }, - }, - { - title: 'Digital goods', - imageUrl: '/images/landing/digital_goods.png', - }, - ]; - const assets = _.map(assetTypes, (assetType: AssetType) => { - const style = _.isUndefined(assetType.style) ? {} : assetType.style; - return ( -
-
- -
-
- {assetType.title} -
-
- ); - }); - return assets; - } - private _renderInfoBoxes() { - const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; - const boxStyle: React.CSSProperties = { - maxWidth: 252, - height: 386, - backgroundColor: colors.grey50, - borderRadius: 5, - padding: '10px 24px 24px', - }; - const boxes = _.map(boxContents, (boxContent: BoxContent) => { - return ( -
-
-
- -
-
- {boxContent.title} -
-
- {boxContent.description} -
-
-
- ); - }); - return ( -
-
- {boxes} -
-
- ); - } - private _renderUseCases() { - const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; + private _throttledScreenWidthUpdate: () => void; + constructor(props: LandingProps) { + super(props); + this.state = { + screenWidth: utils.getScreenWidth(), + }; + this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT); + } + public componentDidMount() { + window.addEventListener('resize', this._throttledScreenWidthUpdate); + window.scrollTo(0, 0); + } + public componentWillUnmount() { + window.removeEventListener('resize', this._throttledScreenWidthUpdate); + } + public render() { + return ( +
+ + + {this._renderHero()} + {this._renderProjects()} + {this._renderTokenizationSection()} + {this._renderProtocolSection()} + {this._renderInfoBoxes()} + {this._renderBuildingBlocksSection()} + {this._renderUseCases()} + {this._renderCallToAction()} +
+
+ ); + } + private _renderHero() { + const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; + const buttonLabelStyle: React.CSSProperties = { + textTransform: 'none', + fontSize: isSmallScreen ? 12 : 14, + fontWeight: 400, + }; + const lightButtonStyle: React.CSSProperties = { + borderRadius: 6, + border: '1px solid #D8D8D8', + lineHeight: '33px', + height: 38, + }; + const left = 'col lg-col-7 md-col-7 col-12 lg-pt4 md-pt4 sm-pt0 mt1 lg-pl4 md-pl4 sm-pl0 sm-px3 sm-center'; + return ( +
+
+
+
+ +
+
+
+
+ Powering decentralized exchange +
+
+ 0x is an open, permissionless protocol allowing for ERC20 tokens to be traded on the + Ethereum blockchain. +
+
+
+ + + +
+
+ + + +
+
+
+
+
+
+
+ ); + } + private _renderProjects() { + const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; + const isMediumScreen = this.state.screenWidth === ScreenWidths.Md; + const projectList = _.map(projects, (project: Project, i: number) => { + const colWidth = isSmallScreen ? 3 : isMediumScreen ? 4 : 2 - i % 2; + return ( +
+
+ + + +
+
+ ); + }); + const titleStyle: React.CSSProperties = { + fontFamily: 'Roboto Mono', + color: colors.grey, + textTransform: 'uppercase', + fontWeight: 300, + letterSpacing: 3, + }; + return ( +
+
+
+ Projects building on 0x +
+
{projectList}
+
+ view the{' '} + + full list + +
+
+
+ ); + } + private _renderTokenizationSection() { + const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; + return ( +
+
+ {isSmallScreen && this._renderTokenCloud()} +
+
+
+ The world's value is becoming tokenized +
+
+ {isSmallScreen ? ( + + The Ethereum blockchain is an open, borderless financial system that represents + a wide variety of assets as cryptographic tokens. In the future, most digital + assets and goods will be tokenized. + + ) : ( +
+
+ The Ethereum blockchain is an open, borderless financial system that + represents +
+
+ a wide variety of assets as cryptographic tokens. In the future, most + digital assets and goods will be tokenized. +
+
+ )} +
+
{this._renderAssetTypes()}
+
+
+ {!isSmallScreen && this._renderTokenCloud()} +
+
+ ); + } + private _renderProtocolSection() { + const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; + return ( +
+
+
+ +
+
+
+
Off-chain order relay
+
On-chain settlement
+
+
+ In 0x protocol, orders are transported off-chain, massively reducing gas costs and + eliminating blockchain bloat. Relayers help broadcast orders and collect a fee each time + they facilitate a trade. Anyone can build a relayer. +
+
+
+
+ RELAYERS BUILDING ON 0X +
+
+ + view all + +
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ ); + } + private _renderBuildingBlocksSection() { + const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; + const descriptionStyle: React.CSSProperties = { + fontFamily: 'Roboto Mono', + lineHeight: isSmallScreen ? 1.5 : 2, + fontWeight: 300, + fontSize: 15, + maxWidth: isSmallScreen ? 375 : 'none', + }; + const callToActionStyle: React.CSSProperties = { + fontFamily: 'Roboto Mono', + fontSize: 15, + fontWeight: 300, + maxWidth: isSmallScreen ? 375 : 441, + }; + return ( +
+
+ {isSmallScreen && this._renderBlockChipImage()} +
+
+ A building block for dApps +
+
+ 0x protocol is a pluggable building block for dApps that require exchange functionality. + Join the many developers that are already using 0x in their web applications and smart + contracts. +
+
+ Learn how in our{' '} + + 0x.js + {' '} + and{' '} + + smart contract + {' '} + docs +
+
+ {!isSmallScreen && this._renderBlockChipImage()} +
+
+ ); + } + private _renderBlockChipImage() { + const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; + return ( +
+ +
+ ); + } + private _renderTokenCloud() { + const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; + return ( +
+ +
+ ); + } + private _renderAssetTypes() { + const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; + const assetTypes: AssetType[] = [ + { + title: 'Currency', + imageUrl: '/images/landing/currency.png', + }, + { + title: 'Traditional assets', + imageUrl: '/images/landing/stocks.png', + style: { + paddingLeft: isSmallScreen ? 41 : 56, + paddingRight: isSmallScreen ? 41 : 56, + }, + }, + { + title: 'Digital goods', + imageUrl: '/images/landing/digital_goods.png', + }, + ]; + const assets = _.map(assetTypes, (assetType: AssetType) => { + const style = _.isUndefined(assetType.style) ? {} : assetType.style; + return ( +
+
+ +
+
+ {assetType.title} +
+
+ ); + }); + return assets; + } + private _renderInfoBoxes() { + const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; + const boxStyle: React.CSSProperties = { + maxWidth: 252, + height: 386, + backgroundColor: colors.grey50, + borderRadius: 5, + padding: '10px 24px 24px', + }; + const boxes = _.map(boxContents, (boxContent: BoxContent) => { + return ( +
+
+
+ +
+
+ {boxContent.title} +
+
+ {boxContent.description} +
+
+
+ ); + }); + return ( +
+
+ {boxes} +
+
+ ); + } + private _renderUseCases() { + const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; - const useCases: UseCase[] = [ - { - imageUrl: '/images/landing/governance_icon.png', - type: 'Decentralized governance', - description: - 'Decentralized organizations use tokens to represent ownership and \ + const useCases: UseCase[] = [ + { + imageUrl: '/images/landing/governance_icon.png', + type: 'Decentralized governance', + description: + 'Decentralized organizations use tokens to represent ownership and \ guide their governance logic. 0x allows decentralized organizations \ to seamlessly and safely trade ownership for startup capital.', - projectIconUrls: ['/images/landing/aragon.png'], - classNames: 'lg-px2 md-px2', - }, - { - imageUrl: '/images/landing/prediction_market_icon.png', - type: 'Prediction markets', - description: - 'Decentralized prediction market platforms generate sets of tokens that \ + projectIconUrls: ['/images/landing/aragon.png'], + classNames: 'lg-px2 md-px2', + }, + { + imageUrl: '/images/landing/prediction_market_icon.png', + type: 'Prediction markets', + description: + 'Decentralized prediction market platforms generate sets of tokens that \ represent a financial stake in the outcomes of real-world events. 0x allows \ these tokens to be instantly tradable.', - projectIconUrls: ['/images/landing/augur.png'], - classNames: 'lg-px2 md-px2', - }, - { - imageUrl: '/images/landing/stable_tokens_icon.png', - type: 'Stable tokens', - description: - 'Novel economic constructs such as stable coins require efficient, liquid \ + projectIconUrls: ['/images/landing/augur.png'], + classNames: 'lg-px2 md-px2', + }, + { + imageUrl: '/images/landing/stable_tokens_icon.png', + type: 'Stable tokens', + description: + 'Novel economic constructs such as stable coins require efficient, liquid \ markets to succeed. 0x will facilitate the underlying economic mechanisms \ that allow these tokens to remain stable.', - projectIconUrls: ['/images/landing/maker.png'], - classNames: 'lg-px2 md-px2', - }, - { - imageUrl: '/images/landing/loans_icon.png', - type: 'Decentralized loans', - description: - 'Efficient lending requires liquid markets where investors can buy and re-sell loans. \ + projectIconUrls: ['/images/landing/maker.png'], + classNames: 'lg-px2 md-px2', + }, + { + imageUrl: '/images/landing/loans_icon.png', + type: 'Decentralized loans', + description: + 'Efficient lending requires liquid markets where investors can buy and re-sell loans. \ 0x enables an ecosystem of lenders to self-organize and efficiently determine \ market prices for all outstanding loans.', - projectIconUrls: ['/images/landing/dharma.png', '/images/landing/lendroid.png'], - classNames: 'lg-pr2 md-pr2 lg-col-6 md-col-6', - style: { - width: 291, - float: 'right', - marginTop: !isSmallScreen ? 38 : 0, - }, - }, - { - imageUrl: '/images/landing/fund_management_icon.png', - type: 'Fund management', - description: - 'Decentralized fund management limits fund managers to investing in pre-agreed \ + projectIconUrls: ['/images/landing/dharma.png', '/images/landing/lendroid.png'], + classNames: 'lg-pr2 md-pr2 lg-col-6 md-col-6', + style: { + width: 291, + float: 'right', + marginTop: !isSmallScreen ? 38 : 0, + }, + }, + { + imageUrl: '/images/landing/fund_management_icon.png', + type: 'Fund management', + description: + 'Decentralized fund management limits fund managers to investing in pre-agreed \ upon asset classes. Embedding 0x into fund management smart contracts enables \ them to enforce these security constraints.', - projectIconUrls: ['/images/landing/melonport.png'], - classNames: 'lg-pl2 md-pl2 lg-col-6 md-col-6', - style: { width: 291, marginTop: !isSmallScreen ? 38 : 0 }, - }, - ]; + projectIconUrls: ['/images/landing/melonport.png'], + classNames: 'lg-pl2 md-pl2 lg-col-6 md-col-6', + style: { width: 291, marginTop: !isSmallScreen ? 38 : 0 }, + }, + ]; - const cases = _.map(useCases, (useCase: UseCase) => { - const style = _.isUndefined(useCase.style) || isSmallScreen ? {} : useCase.style; - const useCaseBoxStyle = { - color: colors.grey, - border: '1px solid #565656', - borderRadius: 4, - maxWidth: isSmallScreen ? 375 : 'none', - ...style, - }; - const typeStyle: React.CSSProperties = { - color: colors.lightGrey, - fontSize: 13, - textTransform: 'uppercase', - fontFamily: 'Roboto Mono', - fontWeight: 300, - }; - return ( -
-
-
- -
-
- {useCase.type} -
-
- {useCase.description} -
-
-
- ); - }); - return ( -
-
- {cases} -
-
- ); - } - private _renderCallToAction() { - const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; - const buttonLabelStyle: React.CSSProperties = { - textTransform: 'none', - fontSize: 15, - fontWeight: 400, - }; - const lightButtonStyle: React.CSSProperties = { - borderRadius: 6, - border: '1px solid #a0a0a0', - lineHeight: '33px', - height: 49, - }; - const callToActionClassNames = - 'col lg-col-8 md-col-8 col-12 lg-pr3 md-pr3 \ + const cases = _.map(useCases, (useCase: UseCase) => { + const style = _.isUndefined(useCase.style) || isSmallScreen ? {} : useCase.style; + const useCaseBoxStyle = { + color: colors.grey, + border: '1px solid #565656', + borderRadius: 4, + maxWidth: isSmallScreen ? 375 : 'none', + ...style, + }; + const typeStyle: React.CSSProperties = { + color: colors.lightGrey, + fontSize: 13, + textTransform: 'uppercase', + fontFamily: 'Roboto Mono', + fontWeight: 300, + }; + return ( +
+
+
+ +
+
+ {useCase.type} +
+
+ {useCase.description} +
+
+
+ ); + }); + return ( +
+
+ {cases} +
+
+ ); + } + private _renderCallToAction() { + const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; + const buttonLabelStyle: React.CSSProperties = { + textTransform: 'none', + fontSize: 15, + fontWeight: 400, + }; + const lightButtonStyle: React.CSSProperties = { + borderRadius: 6, + border: '1px solid #a0a0a0', + lineHeight: '33px', + height: 49, + }; + const callToActionClassNames = + 'col lg-col-8 md-col-8 col-12 lg-pr3 md-pr3 \ lg-right-align md-right-align sm-center sm-px3 h4'; - return ( -
-
-
- Get started on building the decentralized future -
-
- - - -
-
-
- ); - } - private _updateScreenWidth() { - const newScreenWidth = utils.getScreenWidth(); - if (newScreenWidth !== this.state.screenWidth) { - this.setState({ - screenWidth: newScreenWidth, - }); - } - } + return ( +
+
+
+ Get started on building the decentralized future +
+
+ + + +
+
+
+ ); + } + private _updateScreenWidth() { + const newScreenWidth = utils.getScreenWidth(); + if (newScreenWidth !== this.state.screenWidth) { + this.setState({ + screenWidth: newScreenWidth, + }); + } + } } // tslint:disable:max-file-line-count diff --git a/packages/website/ts/pages/not_found.tsx b/packages/website/ts/pages/not_found.tsx index 9d8d4142d..ff277c377 100644 --- a/packages/website/ts/pages/not_found.tsx +++ b/packages/website/ts/pages/not_found.tsx @@ -5,38 +5,38 @@ import { TopBar } from 'ts/components/top_bar'; import { Styles } from 'ts/types'; export interface NotFoundProps { - location: Location; + location: Location; } interface NotFoundState {} const styles: Styles = { - thin: { - fontWeight: 100, - }, + thin: { + fontWeight: 100, + }, }; export class NotFound extends React.Component { - public render() { - return ( -
- -
-
-
-
-

404 Not Found

-
-
- Hm... looks like we couldn't find what you are looking for. -
-
-
-
-
-
-
-
- ); - } + public render() { + return ( +
+ +
+
+
+
+

404 Not Found

+
+
+ Hm... looks like we couldn't find what you are looking for. +
+
+
+
+
+
+
+
+ ); + } } diff --git a/packages/website/ts/pages/shared/anchor_title.tsx b/packages/website/ts/pages/shared/anchor_title.tsx index 118aa0ea5..db5be1f59 100644 --- a/packages/website/ts/pages/shared/anchor_title.tsx +++ b/packages/website/ts/pages/shared/anchor_title.tsx @@ -5,87 +5,87 @@ import { constants } from 'ts/utils/constants'; import { utils } from 'ts/utils/utils'; const headerSizeToScrollOffset: { [headerSize: string]: number } = { - h2: -20, - h3: 0, + h2: -20, + h3: 0, }; interface AnchorTitleProps { - title: string | React.ReactNode; - id: string; - headerSize: HeaderSizes; - shouldShowAnchor: boolean; + title: string | React.ReactNode; + id: string; + headerSize: HeaderSizes; + shouldShowAnchor: boolean; } interface AnchorTitleState { - isHovering: boolean; + isHovering: boolean; } const styles: Styles = { - anchor: { - fontSize: 20, - transform: 'rotate(45deg)', - cursor: 'pointer', - }, - headers: { - WebkitMarginStart: 0, - WebkitMarginEnd: 0, - fontWeight: 'bold', - display: 'block', - }, - h1: { - fontSize: '1.8em', - WebkitMarginBefore: '0.83em', - WebkitMarginAfter: '0.83em', - }, - h2: { - fontSize: '1.5em', - WebkitMarginBefore: '0.83em', - WebkitMarginAfter: '0.83em', - }, - h3: { - fontSize: '1.17em', - WebkitMarginBefore: '1em', - WebkitMarginAfter: '1em', - }, + anchor: { + fontSize: 20, + transform: 'rotate(45deg)', + cursor: 'pointer', + }, + headers: { + WebkitMarginStart: 0, + WebkitMarginEnd: 0, + fontWeight: 'bold', + display: 'block', + }, + h1: { + fontSize: '1.8em', + WebkitMarginBefore: '0.83em', + WebkitMarginAfter: '0.83em', + }, + h2: { + fontSize: '1.5em', + WebkitMarginBefore: '0.83em', + WebkitMarginAfter: '0.83em', + }, + h3: { + fontSize: '1.17em', + WebkitMarginBefore: '1em', + WebkitMarginAfter: '1em', + }, }; export class AnchorTitle extends React.Component { - constructor(props: AnchorTitleProps) { - super(props); - this.state = { - isHovering: false, - }; - } - public render() { - let opacity = 0; - if (this.props.shouldShowAnchor) { - opacity = this.state.isHovering ? 0.6 : 1; - } - return ( -
-
- {this.props.title} -
- - - -
- ); - } - private _setHoverState(isHovering: boolean) { - this.setState({ - isHovering, - }); - } + constructor(props: AnchorTitleProps) { + super(props); + this.state = { + isHovering: false, + }; + } + public render() { + let opacity = 0; + if (this.props.shouldShowAnchor) { + opacity = this.state.isHovering ? 0.6 : 1; + } + return ( +
+
+ {this.props.title} +
+ + + +
+ ); + } + private _setHoverState(isHovering: boolean) { + this.setState({ + isHovering, + }); + } } diff --git a/packages/website/ts/pages/shared/markdown_code_block.tsx b/packages/website/ts/pages/shared/markdown_code_block.tsx index a9d95979b..be96fda16 100644 --- a/packages/website/ts/pages/shared/markdown_code_block.tsx +++ b/packages/website/ts/pages/shared/markdown_code_block.tsx @@ -3,23 +3,23 @@ import * as React from 'react'; import * as HighLight from 'react-highlight'; interface MarkdownCodeBlockProps { - literal: string; - language: string; + literal: string; + language: string; } interface MarkdownCodeBlockState {} export class MarkdownCodeBlock extends React.Component { - // Re-rendering a codeblock causes any use selection to become de-selected. This is annoying when trying - // to copy-paste code examples. We therefore noop re-renders on this component if it's props haven't changed. - public shouldComponentUpdate(nextProps: MarkdownCodeBlockProps, nextState: MarkdownCodeBlockState) { - return nextProps.literal !== this.props.literal || nextProps.language !== this.props.language; - } - public render() { - return ( - - {this.props.literal} - - ); - } + // Re-rendering a codeblock causes any use selection to become de-selected. This is annoying when trying + // to copy-paste code examples. We therefore noop re-renders on this component if it's props haven't changed. + public shouldComponentUpdate(nextProps: MarkdownCodeBlockProps, nextState: MarkdownCodeBlockState) { + return nextProps.literal !== this.props.literal || nextProps.language !== this.props.language; + } + public render() { + return ( + + {this.props.literal} + + ); + } } diff --git a/packages/website/ts/pages/shared/markdown_section.tsx b/packages/website/ts/pages/shared/markdown_section.tsx index c875ab736..5487dc8cc 100644 --- a/packages/website/ts/pages/shared/markdown_section.tsx +++ b/packages/website/ts/pages/shared/markdown_section.tsx @@ -9,66 +9,66 @@ import { HeaderSizes } from 'ts/types'; import { utils } from 'ts/utils/utils'; interface MarkdownSectionProps { - sectionName: string; - markdownContent: string; - headerSize?: HeaderSizes; - githubLink?: string; + sectionName: string; + markdownContent: string; + headerSize?: HeaderSizes; + githubLink?: string; } interface MarkdownSectionState { - shouldShowAnchor: boolean; + shouldShowAnchor: boolean; } export class MarkdownSection extends React.Component { - public static defaultProps: Partial = { - headerSize: HeaderSizes.H3, - }; - constructor(props: MarkdownSectionProps) { - super(props); - this.state = { - shouldShowAnchor: false, - }; - } - public render() { - const sectionName = this.props.sectionName; - const id = utils.getIdFromName(sectionName); - return ( -
- -
-
- - - -
-
- {!_.isUndefined(this.props.githubLink) && ( - } - /> - )} -
-
- -
-
- ); - } - private _setAnchorVisibility(shouldShowAnchor: boolean) { - this.setState({ - shouldShowAnchor, - }); - } + public static defaultProps: Partial = { + headerSize: HeaderSizes.H3, + }; + constructor(props: MarkdownSectionProps) { + super(props); + this.state = { + shouldShowAnchor: false, + }; + } + public render() { + const sectionName = this.props.sectionName; + const id = utils.getIdFromName(sectionName); + return ( +
+ +
+
+ + + +
+
+ {!_.isUndefined(this.props.githubLink) && ( + } + /> + )} +
+
+ +
+
+ ); + } + private _setAnchorVisibility(shouldShowAnchor: boolean) { + this.setState({ + shouldShowAnchor, + }); + } } diff --git a/packages/website/ts/pages/shared/nested_sidebar_menu.tsx b/packages/website/ts/pages/shared/nested_sidebar_menu.tsx index cd7ea68e6..849c33504 100644 --- a/packages/website/ts/pages/shared/nested_sidebar_menu.tsx +++ b/packages/website/ts/pages/shared/nested_sidebar_menu.tsx @@ -9,146 +9,146 @@ import { constants } from 'ts/utils/constants'; import { utils } from 'ts/utils/utils'; interface NestedSidebarMenuProps { - topLevelMenu: { [topLevel: string]: string[] }; - menuSubsectionsBySection: MenuSubsectionsBySection; - shouldDisplaySectionHeaders?: boolean; - onMenuItemClick?: () => void; - selectedVersion?: string; - versions?: string[]; - docPath?: string; - isSectionHeaderClickable?: boolean; + topLevelMenu: { [topLevel: string]: string[] }; + menuSubsectionsBySection: MenuSubsectionsBySection; + shouldDisplaySectionHeaders?: boolean; + onMenuItemClick?: () => void; + selectedVersion?: string; + versions?: string[]; + docPath?: string; + isSectionHeaderClickable?: boolean; } interface NestedSidebarMenuState {} const styles: Styles = { - menuItemWithHeaders: { - minHeight: 0, - }, - menuItemWithoutHeaders: { - minHeight: 48, - }, - menuItemInnerDivWithHeaders: { - lineHeight: 2, - }, + menuItemWithHeaders: { + minHeight: 0, + }, + menuItemWithoutHeaders: { + minHeight: 48, + }, + menuItemInnerDivWithHeaders: { + lineHeight: 2, + }, }; export class NestedSidebarMenu extends React.Component { - public static defaultProps: Partial = { - shouldDisplaySectionHeaders: true, - onMenuItemClick: _.noop, - }; - public render() { - const navigation = _.map(this.props.topLevelMenu, (menuItems: string[], sectionName: string) => { - const finalSectionName = sectionName.replace(/-/g, ' '); - if (this.props.shouldDisplaySectionHeaders) { - const id = utils.getIdFromName(sectionName); - return ( -
- -
- {finalSectionName.toUpperCase()} -
-
- {this._renderMenuItems(menuItems)} -
- ); - } else { - return
{this._renderMenuItems(menuItems)}
; - } - }); - return ( -
- {!_.isUndefined(this.props.versions) && - !_.isUndefined(this.props.selectedVersion) && - !_.isUndefined(this.props.docPath) && ( - - )} - {navigation} -
- ); - } - private _renderMenuItems(menuItemNames: string[]): React.ReactNode[] { - const menuItemStyles = this.props.shouldDisplaySectionHeaders - ? styles.menuItemWithHeaders - : styles.menuItemWithoutHeaders; - const menuItemInnerDivStyles = this.props.shouldDisplaySectionHeaders ? styles.menuItemInnerDivWithHeaders : {}; - const menuItems = _.map(menuItemNames, menuItemName => { - const id = utils.getIdFromName(menuItemName); - return ( -
- - - {menuItemName} - - - {this._renderMenuItemSubsections(menuItemName)} -
- ); - }); - return menuItems; - } - private _renderMenuItemSubsections(menuItemName: string): React.ReactNode { - if (_.isUndefined(this.props.menuSubsectionsBySection[menuItemName])) { - return null; - } - return this._renderMenuSubsectionsBySection(menuItemName, this.props.menuSubsectionsBySection[menuItemName]); - } - private _renderMenuSubsectionsBySection(menuItemName: string, entityNames: string[]): React.ReactNode { - return ( -
    - {_.map(entityNames, entityName => { - const name = `${menuItemName}-${entityName}`; - const id = utils.getIdFromName(name); - return ( -
  • - - - {entityName} - - -
  • - ); - })} -
- ); - } - private _onMenuItemClick(name: string): void { - const id = utils.getIdFromName(name); - utils.setUrlHash(id); - this.props.onMenuItemClick(); - } + public static defaultProps: Partial = { + shouldDisplaySectionHeaders: true, + onMenuItemClick: _.noop, + }; + public render() { + const navigation = _.map(this.props.topLevelMenu, (menuItems: string[], sectionName: string) => { + const finalSectionName = sectionName.replace(/-/g, ' '); + if (this.props.shouldDisplaySectionHeaders) { + const id = utils.getIdFromName(sectionName); + return ( +
+ +
+ {finalSectionName.toUpperCase()} +
+
+ {this._renderMenuItems(menuItems)} +
+ ); + } else { + return
{this._renderMenuItems(menuItems)}
; + } + }); + return ( +
+ {!_.isUndefined(this.props.versions) && + !_.isUndefined(this.props.selectedVersion) && + !_.isUndefined(this.props.docPath) && ( + + )} + {navigation} +
+ ); + } + private _renderMenuItems(menuItemNames: string[]): React.ReactNode[] { + const menuItemStyles = this.props.shouldDisplaySectionHeaders + ? styles.menuItemWithHeaders + : styles.menuItemWithoutHeaders; + const menuItemInnerDivStyles = this.props.shouldDisplaySectionHeaders ? styles.menuItemInnerDivWithHeaders : {}; + const menuItems = _.map(menuItemNames, menuItemName => { + const id = utils.getIdFromName(menuItemName); + return ( +
+ + + {menuItemName} + + + {this._renderMenuItemSubsections(menuItemName)} +
+ ); + }); + return menuItems; + } + private _renderMenuItemSubsections(menuItemName: string): React.ReactNode { + if (_.isUndefined(this.props.menuSubsectionsBySection[menuItemName])) { + return null; + } + return this._renderMenuSubsectionsBySection(menuItemName, this.props.menuSubsectionsBySection[menuItemName]); + } + private _renderMenuSubsectionsBySection(menuItemName: string, entityNames: string[]): React.ReactNode { + return ( +
    + {_.map(entityNames, entityName => { + const name = `${menuItemName}-${entityName}`; + const id = utils.getIdFromName(name); + return ( +
  • + + + {entityName} + + +
  • + ); + })} +
+ ); + } + private _onMenuItemClick(name: string): void { + const id = utils.getIdFromName(name); + utils.setUrlHash(id); + this.props.onMenuItemClick(); + } } diff --git a/packages/website/ts/pages/shared/section_header.tsx b/packages/website/ts/pages/shared/section_header.tsx index f9aa1a5e6..a5f5f52cf 100644 --- a/packages/website/ts/pages/shared/section_header.tsx +++ b/packages/website/ts/pages/shared/section_header.tsx @@ -5,46 +5,46 @@ import { HeaderSizes } from 'ts/types'; import { utils } from 'ts/utils/utils'; interface SectionHeaderProps { - sectionName: string; - headerSize?: HeaderSizes; + sectionName: string; + headerSize?: HeaderSizes; } interface SectionHeaderState { - shouldShowAnchor: boolean; + shouldShowAnchor: boolean; } export class SectionHeader extends React.Component { - public static defaultProps: Partial = { - headerSize: HeaderSizes.H2, - }; - constructor(props: SectionHeaderProps) { - super(props); - this.state = { - shouldShowAnchor: false, - }; - } - public render() { - const sectionName = this.props.sectionName.replace(/-/g, ' '); - const id = utils.getIdFromName(sectionName); - return ( -
- - {sectionName}} - id={id} - shouldShowAnchor={this.state.shouldShowAnchor} - /> - -
- ); - } - private _setAnchorVisibility(shouldShowAnchor: boolean) { - this.setState({ - shouldShowAnchor, - }); - } + public static defaultProps: Partial = { + headerSize: HeaderSizes.H2, + }; + constructor(props: SectionHeaderProps) { + super(props); + this.state = { + shouldShowAnchor: false, + }; + } + public render() { + const sectionName = this.props.sectionName.replace(/-/g, ' '); + const id = utils.getIdFromName(sectionName); + return ( +
+ + {sectionName}} + id={id} + shouldShowAnchor={this.state.shouldShowAnchor} + /> + +
+ ); + } + private _setAnchorVisibility(shouldShowAnchor: boolean) { + this.setState({ + shouldShowAnchor, + }); + } } diff --git a/packages/website/ts/pages/shared/version_drop_down.tsx b/packages/website/ts/pages/shared/version_drop_down.tsx index a647252ba..b922e1048 100644 --- a/packages/website/ts/pages/shared/version_drop_down.tsx +++ b/packages/website/ts/pages/shared/version_drop_down.tsx @@ -4,34 +4,34 @@ import MenuItem from 'material-ui/MenuItem'; import * as React from 'react'; interface VersionDropDownProps { - selectedVersion: string; - versions: string[]; - docPath: string; + selectedVersion: string; + versions: string[]; + docPath: string; } interface VersionDropDownState {} export class VersionDropDown extends React.Component { - public render() { - return ( -
- - {this._renderDropDownItems()} - -
- ); - } - private _renderDropDownItems() { - const items = _.map(this.props.versions, version => { - return ; - }); - return items; - } - private _updateSelectedVersion(e: any, index: number, value: string) { - window.location.href = `${this.props.docPath}/${value}${window.location.hash}`; - } + public render() { + return ( +
+ + {this._renderDropDownItems()} + +
+ ); + } + private _renderDropDownItems() { + const items = _.map(this.props.versions, version => { + return ; + }); + return items; + } + private _updateSelectedVersion(e: any, index: number, value: string) { + window.location.href = `${this.props.docPath}/${value}${window.location.hash}`; + } } diff --git a/packages/website/ts/pages/wiki/wiki.tsx b/packages/website/ts/pages/wiki/wiki.tsx index dba5ed6a0..d065614ba 100644 --- a/packages/website/ts/pages/wiki/wiki.tsx +++ b/packages/website/ts/pages/wiki/wiki.tsx @@ -16,186 +16,186 @@ import { utils } from 'ts/utils/utils'; const WIKI_NOT_READY_BACKOUT_TIMEOUT_MS = 5000; export interface WikiProps { - source: string; - location: Location; + source: string; + location: Location; } interface WikiState { - articlesBySection: ArticlesBySection; + articlesBySection: ArticlesBySection; } const styles: Styles = { - mainContainers: { - position: 'absolute', - top: 1, - left: 0, - bottom: 0, - right: 0, - overflowZ: 'hidden', - overflowY: 'scroll', - minHeight: 'calc(100vh - 1px)', - WebkitOverflowScrolling: 'touch', - }, - menuContainer: { - borderColor: colors.grey300, - maxWidth: 330, - marginLeft: 20, - }, + mainContainers: { + position: 'absolute', + top: 1, + left: 0, + bottom: 0, + right: 0, + overflowZ: 'hidden', + overflowY: 'scroll', + minHeight: 'calc(100vh - 1px)', + WebkitOverflowScrolling: 'touch', + }, + menuContainer: { + borderColor: colors.grey300, + maxWidth: 330, + marginLeft: 20, + }, }; export class Wiki extends React.Component { - private _wikiBackoffTimeoutId: number; - constructor(props: WikiProps) { - super(props); - this.state = { - articlesBySection: undefined, - }; - } - public componentWillMount() { - // tslint:disable-next-line:no-floating-promises - this._fetchArticlesBySectionAsync(); - } - public componentWillUnmount() { - clearTimeout(this._wikiBackoffTimeoutId); - } - public render() { - const menuSubsectionsBySection = _.isUndefined(this.state.articlesBySection) - ? {} - : this._getMenuSubsectionsBySection(this.state.articlesBySection); - return ( -
- - - {_.isUndefined(this.state.articlesBySection) ? ( -
-
-
- -
-
- Loading wiki... -
-
-
- ) : ( -
-
-
- -
-
-
-
-
-

- - 0x Protocol Wiki - -

-
{this._renderWikiArticles()}
-
-
-
- )} -
- ); - } - private _renderWikiArticles(): React.ReactNode { - const sectionNames = _.keys(this.state.articlesBySection); - const sections = _.map(sectionNames, sectionName => this._renderSection(sectionName)); - return sections; - } - private _renderSection(sectionName: string) { - const articles = this.state.articlesBySection[sectionName]; - const renderedArticles = _.map(articles, (article: Article) => { - const githubLink = `${constants.URL_GITHUB_WIKI}/edit/master/${sectionName}/${article.fileName}`; - return ( -
- -
- See a way to make this article better?{' '} - - Edit here → - -
-
- ); - }); - return ( -
- - {renderedArticles} -
- ); - } - private _scrollToHash(): void { - const hashWithPrefix = this.props.location.hash; - let hash = hashWithPrefix.slice(1); - if (_.isEmpty(hash)) { - hash = '0xProtocolWiki'; // scroll to the top - } + private _wikiBackoffTimeoutId: number; + constructor(props: WikiProps) { + super(props); + this.state = { + articlesBySection: undefined, + }; + } + public componentWillMount() { + // tslint:disable-next-line:no-floating-promises + this._fetchArticlesBySectionAsync(); + } + public componentWillUnmount() { + clearTimeout(this._wikiBackoffTimeoutId); + } + public render() { + const menuSubsectionsBySection = _.isUndefined(this.state.articlesBySection) + ? {} + : this._getMenuSubsectionsBySection(this.state.articlesBySection); + return ( +
+ + + {_.isUndefined(this.state.articlesBySection) ? ( +
+
+
+ +
+
+ Loading wiki... +
+
+
+ ) : ( +
+
+
+ +
+
+
+
+
+

+ + 0x Protocol Wiki + +

+
{this._renderWikiArticles()}
+
+
+
+ )} +
+ ); + } + private _renderWikiArticles(): React.ReactNode { + const sectionNames = _.keys(this.state.articlesBySection); + const sections = _.map(sectionNames, sectionName => this._renderSection(sectionName)); + return sections; + } + private _renderSection(sectionName: string) { + const articles = this.state.articlesBySection[sectionName]; + const renderedArticles = _.map(articles, (article: Article) => { + const githubLink = `${constants.URL_GITHUB_WIKI}/edit/master/${sectionName}/${article.fileName}`; + return ( +
+ +
+ See a way to make this article better?{' '} + + Edit here → + +
+
+ ); + }); + return ( +
+ + {renderedArticles} +
+ ); + } + private _scrollToHash(): void { + const hashWithPrefix = this.props.location.hash; + let hash = hashWithPrefix.slice(1); + if (_.isEmpty(hash)) { + hash = '0xProtocolWiki'; // scroll to the top + } - scroller.scrollTo(hash, { - duration: 0, - offset: 0, - containerId: 'documentation', - }); - } - private async _fetchArticlesBySectionAsync(): Promise { - const endpoint = `${configs.BACKEND_BASE_URL}${WebsitePaths.Wiki}`; - const response = await fetch(endpoint); - if (response.status === constants.HTTP_NO_CONTENT_STATUS_CODE) { - // We need to backoff and try fetching again later - this._wikiBackoffTimeoutId = window.setTimeout(() => { - // tslint:disable-next-line:no-floating-promises - this._fetchArticlesBySectionAsync(); - }, WIKI_NOT_READY_BACKOUT_TIMEOUT_MS); - return; - } - if (response.status !== 200) { - // TODO: Show the user an error message when the wiki fail to load - const errMsg = await response.text(); - utils.consoleLog(`Failed to load wiki: ${response.status} ${errMsg}`); - return; - } - const articlesBySection = await response.json(); - this.setState( - { - articlesBySection, - }, - () => { - this._scrollToHash(); - }, - ); - } - private _getMenuSubsectionsBySection(articlesBySection: ArticlesBySection) { - const sectionNames = _.keys(articlesBySection); - const menuSubsectionsBySection: { [section: string]: string[] } = {}; - for (const sectionName of sectionNames) { - const articles = articlesBySection[sectionName]; - const articleNames = _.map(articles, article => article.title); - menuSubsectionsBySection[sectionName] = articleNames; - } - return menuSubsectionsBySection; - } + scroller.scrollTo(hash, { + duration: 0, + offset: 0, + containerId: 'documentation', + }); + } + private async _fetchArticlesBySectionAsync(): Promise { + const endpoint = `${configs.BACKEND_BASE_URL}${WebsitePaths.Wiki}`; + const response = await fetch(endpoint); + if (response.status === constants.HTTP_NO_CONTENT_STATUS_CODE) { + // We need to backoff and try fetching again later + this._wikiBackoffTimeoutId = window.setTimeout(() => { + // tslint:disable-next-line:no-floating-promises + this._fetchArticlesBySectionAsync(); + }, WIKI_NOT_READY_BACKOUT_TIMEOUT_MS); + return; + } + if (response.status !== 200) { + // TODO: Show the user an error message when the wiki fail to load + const errMsg = await response.text(); + utils.consoleLog(`Failed to load wiki: ${response.status} ${errMsg}`); + return; + } + const articlesBySection = await response.json(); + this.setState( + { + articlesBySection, + }, + () => { + this._scrollToHash(); + }, + ); + } + private _getMenuSubsectionsBySection(articlesBySection: ArticlesBySection) { + const sectionNames = _.keys(articlesBySection); + const menuSubsectionsBySection: { [section: string]: string[] } = {}; + for (const sectionName of sectionNames) { + const articles = articlesBySection[sectionName]; + const articleNames = _.map(articles, article => article.title); + menuSubsectionsBySection[sectionName] = articleNames; + } + return menuSubsectionsBySection; + } } -- cgit v1.2.3