1
0
mirror of https://github.com/oceanprotocol/docs.git synced 2024-11-26 19:49:26 +01:00

Merge branch 'master' into feature/get-consume-flow

This commit is contained in:
Matthias Kretschmann 2019-01-30 11:13:00 +01:00 committed by GitHub
commit f07ded1e1f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 1375 additions and 448 deletions

1
.gitignore vendored
View File

@ -7,3 +7,4 @@ yarn-error.log
.DS_Store
.env
.env.*
data/squid-js.json

3
.gitmodules vendored
View File

@ -2,3 +2,6 @@
path = external/dev-ocean
url = https://github.com/oceanprotocol/dev-ocean
branch = master
[submodule "external/squid-js"]
path = external/squid-js
url = https://github.com/oceanprotocol/squid-js.git

View File

@ -82,37 +82,37 @@ All Markdown files should use
1. The file must begin with a section called YAML frontmatter that looks like this:
```md
---
title: This is the Title in Title Case
description: A short description of the page.
---
```md
---
title: This is the Title in Title Case
description: A short description of the page.
---
Markdown content begins here.
```
Markdown content begins here.
```
For external documents in other repos, defining the `slug` and `section` is required:
For external documents in other repos, defining the `slug` and `section` is required:
```md
---
title: This is the Title in Title Case
description: A short description of the page.
slug: /concepts/architecture/
section: concepts
---
```md
---
title: This is the Title in Title Case
description: A short description of the page.
slug: /concepts/architecture/
section: concepts
---
Markdown content begins here.
```
Markdown content begins here.
```
Note: The `description` value will be rendered on-page below the title, and it will also be used for description tags in the HTML head.
Note: The `description` value will be rendered on-page below the title, and it will also be used for description tags in the HTML head.
2. Don't include the page title or description in the Markdown section. That is, don't begin the Markdown content with `# This is the Title in Title Case`. Just write as if that were already there.
3. start your heading levels with `h2`, so `## My heading`
4. Internal links to other docs pages should be:
1. Don't include the page title or description in the Markdown section. That is, don't begin the Markdown content with `# This is the Title in Title Case`. Just write as if that were already there.
2. start your heading levels with `h2`, so `## My heading`
3. Internal links to other docs pages should be:
- to a absolute URL without the host, that looks like `/concepts/terminology/` with slashes on the beginning and end, and with no `.md` or `.html` at the end (before the last slash).
- when linking from external repos, to the _full absolute URL_, such as `https://docs.oceanprotocol.com/hello/you-are-awesome/`
5. no TOC please, this will be generated automatically from all headings
6. for images and media, you can keep them in the original repo. Images will be automatically grabbed by the docs site on querying. When doing that, docs site will generate all sorts of image sizes to handle proper responsive images, so no need to keep an eye on image dimensions or file sizes
4. no TOC please, this will be generated automatically from all headings
5. for images and media, you can keep them in the original repo. Images will be automatically grabbed by the docs site on querying. When doing that, docs site will generate all sorts of image sizes to handle proper responsive images, so no need to keep an eye on image dimensions or file sizes
**Have a look at [docs.oceanprotocol.com/test/](https://docs.oceanprotocol.com/test/) to see what content elements can be used in all Markdown files included in docs site.**
@ -207,9 +207,11 @@ For more information about stylistic issues, take a look at the section in the t
#### TypeDoc specs
Reference pages based on generated `json` file from TypeDoc.
Reference pages based on generated `json` file from TypeDoc. TypeScript-based projects are included as git submodules under `./external`.
_Coming soon... see [#45](https://github.com/oceanprotocol/docs/issues/45)_
On site build, TypeDoc will automatically generate the required `json` spec file into `./data/squid-js.json` and create pages from it. The data from these json files is then used by the TypeDoc template.
To update the specs to the most recent version, the `./external/squid-js` submodule needs to be manuall updated. That's it, on next site build a new spec will be used.
## Development

View File

@ -12,7 +12,7 @@ The following components expose a consumable REST API which are documented on th
Those are sourced from their respective Swagger specs. On this site you can't execute the documented API calls yet. If you need this, you can run a component's local Swagger UI as outlined in the repository instructions on GitHub.
References of all the functions and methods used in our libraries are not yet integrated here. For now, have a look at the respective repos for more infos:
References of all the functions and methods used in our libraries:
<repo name="squid-js"></repo>
<repo name="squid-py"></repo>

View File

@ -1,6 +1,5 @@
---
title: API Reference
description:
title: Squid-py API Reference
---
ReadTheDocs hosts the [squid-py API Reference Docs](https://squid-py.readthedocs.io/en/latest/).

View File

@ -20,7 +20,13 @@
- group: Libraries
items:
- name: squid-js
links:
- name: API reference
url: /references/squid-js/
- name: squid-py
links:
- name: API reference
url: /references/squid-py/
- name: squid-java
- group: OceanDB

View File

@ -3,16 +3,6 @@
- title: API References
link: /references/introduction/
# - group: squid-js
# items:
# - title: API Reference
# link: /references/squid-js/
- group: squid-py
items:
- title: API Reference
link: /references/squid-py/
- group: aquarius
items:
- title: API Reference
@ -22,3 +12,13 @@
items:
- title: API Reference
link: /references/brizo/
- group: squid-js
items:
- title: API Reference
link: /references/squid-js/
- group: squid-py
items:
- title: API Reference
link: /references/squid-py/

2
external/dev-ocean vendored

@ -1 +1 @@
Subproject commit 79786228757f8e39092d9dd5adf387097f0b02f6
Subproject commit bb4bd802b318f68b2f4a9568bbb0d25bde7e24a9

1
external/squid-js vendored Submodule

@ -0,0 +1 @@
Subproject commit 89cd8fd744ad5c61273b5da595e33f3b80c29c4f

View File

@ -153,7 +153,7 @@ exports.createPages = ({ graphql, actions }) => {
// Create pages from swagger json files
//
const apiSwaggerTemplate = path.resolve(
'./src/templates/ApiSwagger.jsx'
'./src/templates/Swagger/index.jsx'
)
const petStoreSlug = '/references/petstore/'
@ -197,6 +197,58 @@ exports.createPages = ({ graphql, actions }) => {
}
})
//
// Create pages from TypeDoc json files
//
const typeDocSpecs = ['./data/squid-js.json']
const typedocTemplate = path.resolve(
'./src/templates/Typedoc/index.jsx'
)
typeDocSpecs.forEach(spec => {
const typedoc = require(spec) // eslint-disable-line
const name = path
.basename(spec)
.split('.json')
.join('')
const slug = `/references/${name}/`
createPage({
path: slug,
component: typedocTemplate,
context: {
slug,
typedoc,
// TODO: defining these classes for inclusion
// needs to be handled somewhere else to keep
// it generic for all TypeDoc specs
classes: [
'ocean/Ocean',
'ocean/OceanAccounts',
'ocean/OceanAssets',
'ocean/OceanAgreements',
'ocean/Account',
'ocean/DID',
'ocean/ServiceAgreements/ServiceAgreement',
'ddo/DDO',
'ddo/Service',
'aquarius/AquariusProvider',
'aquarius/Aquarius',
'aquarius/query/SearchQuery',
'brizo/BrizoProvider',
'brizo/Brizo',
'keeper/Keeper',
'keeper/Web3Provider',
'secretstore/SecretStoreProvider',
'models/Config',
'models/Balance'
]
}
})
})
//
// create redirects
//

View File

@ -5,8 +5,8 @@
"author": "Ocean Protocol <devops@oceanprotocol.com>",
"license": "Apache-2.0",
"scripts": {
"build": "gatsby build",
"start": "gatsby develop",
"build": "npm run typedoc && gatsby build",
"start": "npm run typedoc && gatsby develop",
"ssr": "npm run build && serve -s public/",
"format:js": "prettier --write '**/*.{js,jsx}'",
"format:css": "prettier-stylelint --write --quiet 'src/**/*.{css,scss}'",
@ -19,7 +19,8 @@
"lint:yml": "prettier '**/*.{yml,yaml}' --list-different",
"lint": "run-p --continue-on-error lint:js lint:css lint:md lint:yml",
"test": "npm run lint",
"deploy": "./scripts/deploy.sh"
"deploy": "./scripts/deploy.sh",
"typedoc": "node ./scripts/typedoc.js"
},
"dependencies": {
"@oceanprotocol/art": "^2.1.0",
@ -33,7 +34,7 @@
"gatsby-plugin-offline": "^2.0.19",
"gatsby-plugin-react-helmet": "^3.0.4",
"gatsby-plugin-sass": "^2.0.7",
"gatsby-plugin-sharp": "^2.0.15",
"gatsby-plugin-sharp": "^2.0.17",
"gatsby-plugin-sitemap": "^2.0.3",
"gatsby-plugin-svgr": "^2.0.1",
"gatsby-remark-autolink-headers": "^2.0.12",
@ -57,10 +58,12 @@
"react": "^16.6.3",
"react-dom": "^16.6.3",
"react-helmet": "^5.2.0",
"react-scrollspy": "^3.3.5",
"rehype-react": "^3.1.0",
"remark": "^10.0.1",
"remark-react": "^5.0.0",
"slugify": "^1.3.4",
"smoothscroll-polyfill": "^0.4.3",
"swagger-client": "^3.8.22"
},
"devDependencies": {
@ -72,12 +75,14 @@
"eslint-plugin-prettier": "^3.0.0",
"markdownlint-cli": "^0.13.0",
"npm-run-all": "^4.1.5",
"ora": "^3.0.0",
"prettier": "^1.15.3",
"prettier-stylelint": "^0.4.2",
"stylelint": "^9.9.0",
"stylelint-config-bigchaindb": "^1.2.1",
"stylelint-config-css-modules": "^1.3.0",
"stylelint-config-standard": "^18.2.0"
"stylelint-config-standard": "^18.2.0",
"typedoc": "^0.14.2"
},
"repository": {
"type": "git",

66
scripts/typedoc.js Normal file
View File

@ -0,0 +1,66 @@
#!/usr/bin/env node
/* eslint-disable no-console, security/detect-child-process, security/detect-non-literal-fs-filename */
const fs = require('fs')
const typedoc = require('typedoc')
const typescript = require('typescript')
const ora = require('ora')
const squidJsPackage = require('../external/squid-js/package.json')
const { exec } = require('child_process')
const { description, version } = squidJsPackage
// Setup our paths, relative to project root
const outPath = './data/squid-js.json'
const files = ['./external/squid-js/src/squid.ts']
// specifically point to tsconfig, otherwise TypeDoc fails
const config = typescript.findConfigFile(
'./external/squid-js',
typescript.sys.fileExists
)
// npm install for squid-js
const spinnerNpm = ora('Installing submodule dependencies...').start()
const install = exec(
'cd ./external/squid-js && npm i && git checkout package-lock.json'
)
install.on('exit', () => {
spinnerNpm.succeed('Installed submodule dependencies.')
generateJson()
})
const generateJson = () => {
const spinnerTypedoc = ora('Generating TypeDoc json...').start()
// Setup our TypeDoc app
const app = new typedoc.Application({
tsconfig: config
})
const src = app.expandInputFiles(files)
const project = app.convert(src)
// Generate the JSON file
app.generateJson(project, outPath)
// Parse and modify json output
const jsonOrig = JSON.parse(fs.readFileSync(outPath, 'utf8'))
const jsonFinal = {
info: {
title: 'Squid-js',
description,
version,
sourceUrl:
'https://github.com/oceanprotocol/squid-js/tree/develop/src/'
},
...jsonOrig
}
fs.writeFileSync(outPath, JSON.stringify(jsonFinal, null, 4))
spinnerTypedoc.succeed('Generated TypeDoc json.')
}

85
src/components/Scroll.jsx Normal file
View File

@ -0,0 +1,85 @@
import smoothscroll from 'smoothscroll-polyfill'
import React from 'react'
import PropTypes from 'prop-types'
export default class TocScroll extends React.Component {
static propTypes = {
type: PropTypes.string,
element: PropTypes.string,
offset: PropTypes.number,
timeout: PropTypes.number,
children: PropTypes.node.isRequired
}
componentDidMount() {
smoothscroll.polyfill()
}
handleClick = e => {
e.preventDefault()
let elem = 0
let scroll = true
const { type, element, offset, timeout } = this.props
if (type && element) {
switch (type) {
case 'class':
// eslint-disable-next-line prefer-destructuring
elem = document.getElementsByClassName(element)[0]
scroll = !!elem
break
case 'id':
elem = document.getElementById(element)
scroll = !!elem
break
default:
}
}
if (scroll) {
this.scrollTo(elem, offset, timeout)
// update browser url
if (typeof window !== 'undefined') {
window.history.pushState({}, null, `#${element}`)
}
} else {
console.log(`Element not found: ${element}`) // eslint-disable-line
}
}
scrollTo(element, offSet = 0, timeout = null) {
const elemPos = element
? element.getBoundingClientRect().top + window.pageYOffset
: 0
if (timeout) {
setTimeout(() => {
window.scroll({
top: elemPos + offSet,
left: 0,
behavior: 'smooth'
})
}, timeout)
} else {
window.scroll({
top: elemPos + offSet,
left: 0,
behavior: 'smooth'
})
}
}
render() {
return (
<a
onClick={this.handleClick}
href={`#${this.props.element}`}
{...this.props}
>
{this.props.children}
</a>
)
}
}

View File

@ -34,13 +34,10 @@ SidebarLink.propTypes = {
linkClasses: PropTypes.string
}
const SidebarList = ({ items, location, toc, tableOfContents }) => (
const SidebarList = ({ items, location, toc, tocComponent }) => (
<div className={styles.list}>
{toc ? (
<div
className={styles.toc}
dangerouslySetInnerHTML={{ __html: tableOfContents }}
/>
<div className={styles.toc}>{tocComponent}</div>
) : (
<ul>
{items.map((item, j) => (
@ -65,7 +62,7 @@ SidebarList.propTypes = {
items: PropTypes.array.isRequired,
location: PropTypes.object.isRequired,
toc: PropTypes.bool,
tableOfContents: PropTypes.string
tocComponent: PropTypes.object
}
const SidebarGroupTitle = ({ group }) => (
@ -104,19 +101,13 @@ export default class Sidebar extends Component {
location: PropTypes.object.isRequired,
collapsed: PropTypes.bool,
toc: PropTypes.bool,
tableOfContents: PropTypes.string
tocComponent: PropTypes.element
}
static defaultProps = { location: { pathname: '/' } }
render() {
const {
sidebar,
location,
collapsed,
toc,
tableOfContents
} = this.props
const { sidebar, location, collapsed, toc, tocComponent } = this.props
if (sidebar) {
try {
@ -143,7 +134,7 @@ export default class Sidebar extends Component {
group={group}
location={location}
toc={toc}
tableOfContents={tableOfContents}
tocComponent={tocComponent}
/>
) : (
<SidebarGroupTitle group={group} />

View File

@ -16,8 +16,8 @@
}
&::-webkit-scrollbar {
width: 6px;
height: 6px;
width: 8px;
height: 8px;
}
&::-webkit-scrollbar-thumb {
@ -79,22 +79,50 @@
&:focus {
transform: none;
color: $brand-purple;
:global(.setup) & {
color: $brand-blue;
}
:global(.tutorials) & {
color: $orange;
}
:global(.references) & {
color: $green;
}
}
}
.toc {
ul {
padding-left: 0;
margin: 0;
ul {
padding-left: $spacer / 2;
margin: 0;
border-left: 1px solid $brand-grey-lighter;
margin-left: $spacer;
font-size: $font-size-small;
}
}
li {
margin: 0;
}
a {
padding-top: $spacer / 12;
padding-bottom: $spacer / 12;
}
code {
background: none;
color: inherit;
}
[data-deprecated='true'] code {
opacity: .5;
}
}
.active {
@ -111,4 +139,16 @@
color: $orange;
border-left-color: $orange;
}
:global(.references) & {
color: $green;
border-left-color: $green;
}
}
.scrollspyActive {
> a {
color: $green;
border-left-color: $green;
}
}

View File

@ -283,11 +283,11 @@ samp {
}
:not(pre) > code {
background: darken($brand-white, 5%) !important;
color: $brand-grey-dark !important;
background: darken($brand-white, 5%);
color: $brand-grey-dark;
display: inline-block;
padding-left: .3rem !important;
padding-right: .3rem !important;
padding-left: .3rem;
padding-right: .3rem;
}
pre {

View File

@ -1,321 +0,0 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { graphql } from 'gatsby'
import Helmet from 'react-helmet'
import slugify from 'slugify'
import Layout from '../components/Layout'
import Content from '../components/Content'
import HeaderSection from '../components/HeaderSection'
import Sidebar from '../components/Sidebar'
import DocHeader from '../components/DocHeader'
import DocFooter from '../components/DocFooter'
import SEO from '../components/Seo'
import stylesDoc from './Doc.module.scss'
import styles from './ApiSwagger.module.scss'
const cleanKey = key => {
let keyCleaned = key
if (key.includes('aquarius')) {
keyCleaned = key.replace(/\/api\/v1\/aquarius/gi, '')
}
if (key.includes('brizo')) {
keyCleaned = key.replace(/\/api\/v1\/brizo/gi, '')
}
return keyCleaned
}
const toc = api => {
const items = Object.keys(api.paths).map(
key => `<li key=${key}>
<a href="#${slugify(cleanKey(key))}"><code>${cleanKey(
key
)}</code></a>
</li>`
)
return `<ul>${items}</ul>`
}
const SwaggerMeta = ({ contact, license }) => (
<ul className={styles.swaggerMeta}>
{contact && (
<li>
<a href={`mailto:${contact.email}`}>{contact.email}</a>
</li>
)}
{license && (
<li>
<a href={license.url}>{license.name}</a>
</li>
)}
</ul>
)
SwaggerMeta.propTypes = {
contact: PropTypes.object,
license: PropTypes.object
}
const ParameterExample = ({ properties }) => (
//
// HEADS UP!
//
// Constructing the example request body here based on the defined properties
// where `key` is the name of the property, and `properties[key].example` is
// the value for it.
//
// Making prism.js pick up on the strings only output didn't work out so well
// so the spans and classes this plugin would add are added manually here. Since we
// include the prism css file globally this is picked up by that.
//
// But this can only work if all keys and values are manually constructed here, which
// is almost impossible to do for deep nested objects or arrays as example value. Running
// that code through `JSON.stringify` won't syntax highlight that part of the code.
//
<pre className="language-json">
<code className="language-json">
{'{'}
{properties &&
Object.keys(properties).map(key => (
<div key={key}>
<span className="token property">{` "${key}"`}</span>
<span className="token operator">{`: `}</span>
{properties[key].type === 'string' && (
<span className="token string">{`"${
properties[key].example
}"`}</span>
)}
{(properties[key].type === 'integer' ||
properties[key].type === 'number') && (
<span className="token number">
{`${properties[key].example}`}
</span>
)}
{(properties[key].type === 'array' ||
properties[key].type === 'object') &&
JSON.stringify(properties[key].example, null, 2)}
,
</div>
))}
{'}'}
</code>
</pre>
)
ParameterExample.propTypes = {
properties: PropTypes.object
}
const Parameters = ({ parameters }) => (
<>
<h4 className={styles.subHeading}>Parameters</h4>
{parameters.map(parameter => {
const { name, type, required, description, schema } = parameter
return (
<div className={styles.parameters} key={parameter.name}>
<h5>
<code>{name}</code>
{required && (
<span
className={styles.parameterRequired}
title="required parameter"
>
*
</span>
)}
<span className={styles.parameterType}>{type}</span>
</h5>
<p>{description}</p>
{schema && (
<ParameterExample properties={schema.properties} />
)}
</div>
)
})}
</>
)
const Responses = ({ responses }) => (
<>
<h4 className={styles.subHeading}>Responses</h4>
{Object.keys(responses).map(key => (
<div key={key} className={styles.response}>
<code>{key}</code> {responses[key].description}
</div>
))}
</>
)
const Method = ({ keyName, value }) => {
const { summary, description, parameters, responses } = value
return (
<div className={styles.method}>
<h3 className={styles.pathMethod} data-type={keyName}>
{keyName}
</h3>
<p>{summary}</p>
{description && <p>{description}</p>}
{/*
{consumes &&
consumes.map((item, i) => (
<div key={i}>
<code>{item}</code>
</div>
))}
*/}
{parameters && parameters.length && (
<Parameters parameters={parameters} />
)}
{responses && Object.keys(responses).length !== 0 && (
<Responses responses={responses} />
)}
</div>
)
}
Method.propTypes = {
keyName: PropTypes.string,
value: PropTypes.object
}
const Paths = ({ paths }) =>
Object.entries(paths).map(([key, value]) => (
<div key={key}>
<h2 id={slugify(cleanKey(key))} className={styles.pathName}>
<code>{cleanKey(key)}</code>
</h2>
{Object.entries(value).map(([key, value]) => (
<Method key={key} keyName={key} value={value} />
))}
</div>
))
const BasePath = ({ host, basePath }) => (
<div className={styles.basePath}>
<h2>Base Path</h2>
<code>
<span>{host}</span>
{basePath}
</code>
</div>
)
BasePath.propTypes = {
host: PropTypes.string,
basePath: PropTypes.string
}
export default class ApiSwaggerTemplate extends Component {
static propTypes = {
data: PropTypes.object.isRequired,
location: PropTypes.object.isRequired,
pageContext: PropTypes.object.isRequired
}
render() {
const { location, data, pageContext } = this.props
const sections = data.allSectionsYaml.edges
const { api } = pageContext
const { host, basePath, info, paths } = api
const { title, description, version, license, contact } = info
// output section title as defined in sections.yml
const sectionTitle = sections.map(({ node }) => {
// compare section against section title from sections.yml
if (node.title.toLowerCase().includes('references')) {
return node.title
}
})
return (
<>
<Helmet>
<body className={'references'} />
</Helmet>
<SEO
title={title}
description={description}
slug={pageContext.slug}
article
/>
<Layout location={location}>
<HeaderSection title={sectionTitle} />
<Content>
<main className={stylesDoc.wrapper}>
<aside className={stylesDoc.sidebar}>
<Sidebar
location={location}
sidebar={'references'}
collapsed
toc
tableOfContents={toc(api)
.split(',')
.join('')}
/>
</aside>
<article className={stylesDoc.main}>
<DocHeader
title={title}
description={description}
prepend={
<span className={styles.version}>
{version}
</span>
}
/>
{(contact || license) && (
<SwaggerMeta
contact={contact}
license={license}
/>
)}
{(host || basePath) && (
<BasePath host={host} basePath={basePath} />
)}
<Paths paths={paths} />
<DocFooter
url={`https://github.com/oceanprotocol/${title.toLowerCase()}`}
externalName={`${title} Swagger spec`}
/>
</article>
</main>
</Content>
</Layout>
</>
)
}
}
export const apiSwaggerQuery = graphql`
query {
allSectionsYaml {
edges {
node {
title
description
link
}
}
}
}
`

View File

@ -26,8 +26,8 @@ const DocMain = ({ title, description, tableOfContents, post, single }) => (
DocMain.propTypes = {
title: PropTypes.string.isRequired,
description: PropTypes.string.isRequired,
tableOfContents: PropTypes.string,
description: PropTypes.string,
tableOfContents: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
post: PropTypes.object.isRequired,
single: PropTypes.bool
}
@ -38,22 +38,25 @@ export default class DocTemplate extends Component {
location: PropTypes.object.isRequired
}
// output section title as defined in sections.yml
sectionTitle = this.props.data.allSectionsYaml.edges.map(({ node }) => {
// compare section against section title from sections.yml
if (
node.title
.toLowerCase()
.includes(this.props.data.markdownRemark.fields.section)
) {
return node.title
}
})
render() {
const { location } = this.props
const post = this.props.data.markdownRemark
const sections = this.props.data.allSectionsYaml.edges
const { section, slug } = post.fields
const { title, description } = post.frontmatter
const { tableOfContents } = post
// output section title as defined in sections.yml
const sectionTitle = sections.map(({ node }) => {
// compare section against section title from sections.yml
if (node.title.toLowerCase().includes(section)) {
return node.title
}
})
const isApiSection = location.pathname.includes('/references/')
return (
@ -70,7 +73,9 @@ export default class DocTemplate extends Component {
/>
<Layout location={location}>
<HeaderSection title={section ? sectionTitle : title} />
<HeaderSection
title={section ? this.sectionTitle : title}
/>
<Content>
{section ? (

View File

@ -14,6 +14,7 @@
@media (min-width: $break-point--medium) {
width: 27%;
margin-bottom: 0;
margin-top: 0;
order: 1;
+ .main {
@ -47,3 +48,9 @@
max-width: 73%;
margin: auto;
}
.version {
font-size: $font-size-base;
font-family: $font-family-monospace;
color: $brand-grey-light;
}

View File

@ -0,0 +1,151 @@
import React from 'react'
import PropTypes from 'prop-types'
import slugify from 'slugify'
import { cleanPathKey } from './utils'
import styles from './Paths.module.scss'
const ParameterExample = ({ properties }) => (
//
// HEADS UP!
//
// Constructing the example request body here based on the defined properties
// where `key` is the name of the property, and `properties[key].example` is
// the value for it.
//
// Making prism.js pick up on the strings only output didn't work out so well
// so the spans and classes this plugin would add are added manually here. Since we
// include the prism css file globally this is picked up by that.
//
// But this can only work if all keys and values are manually constructed here, which
// is almost impossible to do for deep nested objects or arrays as example value. Running
// that code through `JSON.stringify` won't syntax highlight that part of the code.
//
<pre className="language-json">
<code className="language-json">
{'{'}
{properties &&
Object.keys(properties).map(key => (
<div key={key}>
<span className="token property">{` "${key}"`}</span>
<span className="token operator">{`: `}</span>
{properties[key].type === 'string' && (
<span className="token string">{`"${
properties[key].example
}"`}</span>
)}
{(properties[key].type === 'integer' ||
properties[key].type === 'number') && (
<span className="token number">
{`${properties[key].example}`}
</span>
)}
{(properties[key].type === 'array' ||
properties[key].type === 'object') &&
JSON.stringify(properties[key].example, null, 2)}
,
</div>
))}
{'}'}
</code>
</pre>
)
ParameterExample.propTypes = {
properties: PropTypes.object
}
const Parameters = ({ parameters }) => (
<>
<h4 className={styles.subHeading}>Parameters</h4>
{parameters.map(parameter => {
const { name, type, required, description, schema } = parameter
return (
<div className={styles.parameters} key={parameter.name}>
<h5>
<code>{name}</code>
{required && (
<span
className={styles.parameterRequired}
title="required parameter"
>
*
</span>
)}
<span className={styles.parameterType}>{type}</span>
</h5>
<p>{description}</p>
{schema && (
<ParameterExample properties={schema.properties} />
)}
</div>
)
})}
</>
)
const Responses = ({ responses }) => (
<>
<h4 className={styles.subHeading}>Responses</h4>
{Object.keys(responses).map(key => (
<div key={key} className={styles.response}>
<code>{key}</code> {responses[key].description}
</div>
))}
</>
)
const Method = ({ keyName, value }) => {
const { summary, description, parameters, responses } = value
return (
<div className={styles.method}>
<h3 className={styles.pathMethod} data-type={keyName}>
{keyName}
</h3>
<p>{summary}</p>
{description && <p>{description}</p>}
{/*
{consumes &&
consumes.map((item, i) => (
<div key={i}>
<code>{item}</code>
</div>
))}
*/}
{parameters && parameters.length && (
<Parameters parameters={parameters} />
)}
{responses && Object.keys(responses).length !== 0 && (
<Responses responses={responses} />
)}
</div>
)
}
Method.propTypes = {
keyName: PropTypes.string,
value: PropTypes.object
}
const Paths = ({ paths }) =>
Object.entries(paths).map(([key, value]) => (
<div key={key} id={slugify(cleanPathKey(key))}>
<h2 className={styles.pathName}>
<code>{cleanPathKey(key)}</code>
</h2>
{Object.entries(value).map(([key, value]) => (
<Method key={key} keyName={key} value={value} />
))}
</div>
))
export default Paths

View File

@ -1,52 +1,5 @@
@import 'variables';
.version {
font-size: $font-size-base;
font-family: $font-family-monospace;
color: $brand-grey-light;
}
.swaggerMeta {
margin-top: -($spacer);
padding: 0;
font-size: $font-size-small;
li {
display: inline-block;
margin-left: $spacer;
&:first-child {
margin-left: 0;
}
&:before {
display: none;
}
}
}
.basePath {
margin-top: $spacer;
h2 {
font-size: $font-size-h3;
border-bottom: 1px solid $brand-grey-lighter;
padding-bottom: $spacer / 2;
margin-top: $spacer * 2;
margin-bottom: $spacer;
}
span {
color: $brand-grey-light;
}
code {
// stylelint-disable-next-line
font-size: $font-size-large !important;
font-weight: $font-weight-bold;
}
}
.pathName {
font-size: $font-size-h3;
border-bottom: 1px solid $brand-grey-lighter;

View File

@ -0,0 +1,43 @@
import React from 'react'
import PropTypes from 'prop-types'
import slugify from 'slugify'
import Scrollspy from 'react-scrollspy'
import Scroll from '../../components/Scroll'
import { cleanPathKey } from './utils'
import stylesSidebar from '../../components/Sidebar.module.scss'
const Toc = ({ data }) => {
let Ids = []
const items = Object.keys(data.paths).map(key => {
Ids.push(slugify(cleanPathKey(key)))
return (
<li key={key}>
<Scroll
type="id"
element={`${slugify(cleanPathKey(key))}`}
offset={-20}
>
<code>{cleanPathKey(key)}</code>
</Scroll>
</li>
)
})
return (
<Scrollspy
items={Ids}
currentClassName={stylesSidebar.scrollspyActive}
offset={-100}
>
{items}
</Scrollspy>
)
}
Toc.propTypes = {
data: PropTypes.oneOfType([PropTypes.array, PropTypes.object])
}
export default Toc

View File

@ -0,0 +1,152 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { graphql } from 'gatsby'
import Helmet from 'react-helmet'
import Layout from '../../components/Layout'
import Content from '../../components/Content'
import HeaderSection from '../../components/HeaderSection'
import Sidebar from '../../components/Sidebar'
import DocHeader from '../../components/DocHeader'
import DocFooter from '../../components/DocFooter'
import SEO from '../../components/Seo'
import Toc from './Toc'
import Paths from './Paths'
import stylesDoc from '../Doc.module.scss'
import styles from './index.module.scss'
const SwaggerMeta = ({ contact, license }) => (
<ul className={styles.swaggerMeta}>
{contact && (
<li>
<a href={`mailto:${contact.email}`}>{contact.email}</a>
</li>
)}
{license && (
<li>
<a href={license.url}>{license.name}</a>
</li>
)}
</ul>
)
SwaggerMeta.propTypes = {
contact: PropTypes.object,
license: PropTypes.object
}
const BasePath = ({ host, basePath }) => (
<div className={styles.basePath}>
<h2>Base Path</h2>
<code>
<span>{host}</span>
{basePath}
</code>
</div>
)
BasePath.propTypes = {
host: PropTypes.string,
basePath: PropTypes.string
}
export default class ApiSwaggerTemplate extends Component {
static propTypes = {
data: PropTypes.object.isRequired,
location: PropTypes.object.isRequired,
pageContext: PropTypes.object.isRequired
}
// output section title as defined in sections.yml
sectionTitle = this.props.data.allSectionsYaml.edges.map(({ node }) => {
// compare section against section title from sections.yml
if (node.title.toLowerCase().includes('references')) {
return node.title
}
})
render() {
const { location, pageContext } = this.props
const { api } = pageContext
const { host, basePath, info, paths } = api
const { title, description, version, license, contact } = info
return (
<>
<Helmet>
<body className={'references'} />
</Helmet>
<SEO
title={title}
description={description}
slug={pageContext.slug}
article
/>
<Layout location={location}>
<HeaderSection title={this.sectionTitle} />
<Content>
<main className={stylesDoc.wrapper}>
<aside className={stylesDoc.sidebar}>
<Sidebar
location={location}
sidebar={'references'}
collapsed
toc
tocComponent={<Toc data={api} />}
/>
</aside>
<article className={stylesDoc.main}>
<DocHeader
title={title}
description={description}
prepend={
<span className={stylesDoc.version}>
{version}
</span>
}
/>
{(contact || license) && (
<SwaggerMeta
contact={contact}
license={license}
/>
)}
{(host || basePath) && (
<BasePath host={host} basePath={basePath} />
)}
<Paths paths={paths} />
<DocFooter
url={`https://github.com/oceanprotocol/${title.toLowerCase()}`}
externalName={`${title} Swagger spec`}
/>
</article>
</main>
</Content>
</Layout>
</>
)
}
}
export const apiSwaggerQuery = graphql`
query {
allSectionsYaml {
edges {
node {
title
description
link
}
}
}
}
`

View File

@ -0,0 +1,42 @@
@import 'variables';
.swaggerMeta {
margin-top: -($spacer);
padding: 0;
font-size: $font-size-small;
li {
display: inline-block;
margin-left: $spacer;
&:first-child {
margin-left: 0;
}
&:before {
display: none;
}
}
}
.basePath {
margin-top: $spacer;
h2 {
font-size: $font-size-h3;
border-bottom: 1px solid $brand-grey-lighter;
padding-bottom: $spacer / 2;
margin-top: $spacer * 2;
margin-bottom: $spacer;
}
span {
color: $brand-grey-light;
}
code {
// stylelint-disable-next-line
font-size: $font-size-large !important;
font-weight: $font-weight-bold;
}
}

View File

@ -0,0 +1,13 @@
export const cleanPathKey = key => {
let keyCleaned = key
if (key.includes('aquarius')) {
keyCleaned = key.replace(/\/api\/v1\/aquarius/gi, '')
}
if (key.includes('brizo')) {
keyCleaned = key.replace(/\/api\/v1\/brizo/gi, '')
}
return keyCleaned
}

View File

@ -0,0 +1,252 @@
import React from 'react'
import PropTypes from 'prop-types'
import slugify from 'slugify'
import Scroll from '../../components/Scroll'
import styles from './Entities.module.scss'
import { filterByKindOfProperty } from './utils'
const Type = ({ type }) => {
let isArray = false
if (type.type === 'array') {
isArray = true
type = type.elementType
}
const { name, type: typeOfType, typeArguments, id } = type
const isInternal = typeOfType === 'reference' && id
return (
<div className={styles.type}>
<span>
{isInternal && (
<Scroll type="id" element={`${slugify(name)}`} offset={-20}>
{type.name}
</Scroll>
)}
{!isInternal && <span>{type.name}</span>}
</span>
{typeArguments && (
<span>
<span className={styles.typeSymbol}>&lt;</span>
<span>
{typeArguments.map((typeArgument, i) => (
<span key={i}>
{i !== 0 && (
<span className={styles.typeSymbol}>
,{' '}
</span>
)}
<Type type={typeArgument} key={i} />
</span>
))}
</span>
<span className={styles.typeSymbol}>&gt;</span>
</span>
)}
{isArray && <span className={styles.typeSymbol}>[]</span>}
</div>
)
}
Type.propTypes = {
type: PropTypes.object.isRequired
}
const PropertyDetails = ({ property }) => {
const { type } = property
return (
<div>
<Type type={type} />
</div>
)
}
PropertyDetails.propTypes = {
property: PropTypes.object
}
const MethodDetails = ({ property }) => {
const signature = property.signatures[0]
const { parameters, type } = signature
return (
<>
{parameters && parameters.length && (
<div>
<h4 className={styles.subHeading}>Parameters</h4>
{parameters.map(parameter => {
const { name, type, flags, comment } = parameter
const { isOptional } = flags
const description =
comment && (comment.text || comment.shortText)
return (
<div
className={styles.parameters}
key={parameter.name}
>
<h5>
<code>{name}</code>
{isOptional && (
<span
className={styles.parameterOptional}
title="optional parameter"
>
?
</span>
)}
</h5>
<Type type={type} />
<p>{description}</p>
</div>
)
})}
</div>
)}
{type && (
<div>
<h4 className={styles.subHeading}>Returns</h4>
<Type type={type} />
</div>
)}
</>
)
}
MethodDetails.propTypes = {
property: PropTypes.object
}
const PropertyWrapper = ({ property, sourceUrl, parentAnchor }) => {
const {
name,
kindString,
flags,
signatures,
sources,
decorators
} = property
const { isPublic, isStatic } = flags
const signature = signatures && signatures[0]
const comment = (signature && signature.comment) || property.comment
const { fileName, line } = sources[0]
const deprecation = (decorators || []).filter(
({ name }) => name === 'deprecated'
)[0] // Assuming deprecated annotation
let deprecatedUse, deprecatedSlug
if (deprecation) {
deprecatedUse = deprecation.arguments.alternative.replace(/('|")/g, '')
deprecatedSlug = slugify(deprecatedUse.replace('.', '-'))
}
const sourceLink = `${sourceUrl}${fileName}#L${line}`
return (
<div
className={styles.property}
data-private={!isPublic}
data-deprecated={!!deprecation}
id={`${parentAnchor}-${slugify(name)}`}
>
<h3 className={styles.propertyName}>{name}</h3>
<div
className={styles.propertyType}
data-type={kindString.toLowerCase()}
>
{kindString}
</div>
{isStatic && <div className={styles.propertyModifier}>static</div>}
{!isPublic && (
<div className={styles.propertyModifier} data-secondary>
private
</div>
)}
{comment && !deprecation && (
<div className={styles.propertyDescription}>
{comment.text || comment.shortText}
</div>
)}
{deprecation && (
<div className={styles.deprecation}>
<strong>Deprecated</strong>: use{' '}
<code>
<Scroll
type="id"
element={`${deprecatedSlug}`}
offset={-20}
>
{deprecatedUse}
</Scroll>
</code>{' '}
instead
</div>
)}
{!deprecation &&
(() => {
switch (kindString) {
case 'Method':
return <MethodDetails property={property} />
case 'Property':
return <PropertyDetails property={property} />
}
})()}
{fileName && (
<a
className={styles.sourceLink}
href={sourceLink}
target="_blank"
rel="noopener noreferrer"
>
{`${fileName}#L${line}`}
</a>
)}
</div>
)
}
PropertyWrapper.propTypes = {
property: PropTypes.object,
sourceUrl: PropTypes.string,
parentAnchor: PropTypes.string
}
const Entities = ({ entities, sourceUrl }) =>
entities.map(({ name, comment, children }) => (
<div key={name} id={slugify(name)}>
<h2 className={styles.entityName}>
<code>{name}</code>
</h2>
{comment && (
<div className={styles.entityDescription}>
{comment.text || comment.shortText}
</div>
)}
{children.filter(filterByKindOfProperty).map(property => (
<PropertyWrapper
key={`${name}/${property.id}`}
property={property}
sourceUrl={sourceUrl}
parentAnchor={slugify(name)}
/>
))}
</div>
))
Entities.propTypes = {
entities: PropTypes.array.isRequired,
sourceUrl: PropTypes.string
}
export default Entities

View File

@ -0,0 +1,173 @@
@import 'variables';
.entityName {
font-size: $font-size-h2;
border-bottom: 1px solid $brand-grey-lighter;
padding-bottom: $spacer / 2;
margin-top: $spacer * 2;
margin-bottom: $spacer;
code {
// stylelint-disable declaration-no-important
background: none !important;
padding: 0 !important;
// stylelint-enable declaration-no-important
}
}
.entityDescription {
padding-bottom: $spacer;
white-space: pre-line;
}
.property {
padding: $spacer / 2;
border: 1px solid $brand-grey-lighter;
margin-bottom: $spacer;
border-radius: $border-radius;
position: relative;
&[data-deprecated='true'] {
> *:not(.deprecation) {
opacity: .5;
}
code {
opacity: 1;
background: none;
padding: 0;
}
.sourceLink {
display: none;
}
}
}
.propertyName,
.propertyType,
.propertyModifier {
font-size: $font-size-base;
font-family: $font-family-monospace;
margin-bottom: $spacer / 4;
margin-top: 0;
display: inline-block;
padding: 0 $spacer / 4;
border-radius: $border-radius;
vertical-align: middle;
}
.propertyName {
font-size: $font-size-large;
padding: 0;
margin-right: $spacer / 3;
}
.propertyType,
.propertyModifier {
font-size: $font-size-small;
color: $brand-grey;
margin-right: $spacer / 4;
}
.propertyType {
&[data-type='method'] {
background: rgba($green, .3);
}
&[data-type='property'] {
background: rgba($yellow, .3);
}
}
.propertyModifier {
background: rgba($red, .2);
&[data-secondary] {
background: rgba($brand-blue, .2);
}
}
.propertyDescription {
margin-bottom: $spacer;
}
.sourceLink {
display: block;
font-size: $font-size-mini;
color: $brand-grey-light;
margin-top: $spacer / 2;
&:hover,
&:focus {
transform: none;
}
@media (min-width: $break-point--large) {
margin-top: 0;
position: absolute;
bottom: $spacer / 2;
right: $spacer / 2;
}
}
.deprecation {
font-size: $font-size-small;
margin-top: $spacer / 4;
strong {
color: $brand-grey-light;
}
}
.type {
display: inline-block;
color: $brand-grey;
font-family: $font-family-monospace;
font-size: $font-size-small;
a {
&:hover {
opacity: .6;
}
}
}
.typeSymbol {
opacity: .6;
}
.subHeading {
font-size: $font-size-base;
border-bottom: 1px solid $brand-grey-lighter;
padding-bottom: $spacer / 4;
margin-bottom: $spacer / 4;
color: $brand-grey;
}
.parameters {
margin-top: $spacer / 1.5;
h5,
p {
margin: 0;
}
h5 {
font-size: $font-size-small;
margin-bottom: $spacer / 4;
margin-right: $spacer / 4;
margin-left: -(.2rem);
display: inline-block;
}
code {
padding: .2rem;
}
}
.parameterOptional {
font-size: $font-size-small;
vertical-align: top;
color: $brand-purple;
}

View File

@ -0,0 +1,63 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import slugify from 'slugify'
import Scrollspy from 'react-scrollspy'
import Scroll from '../../components/Scroll'
import { filterByKindOfProperty } from './utils'
import stylesSidebar from '../../components/Sidebar.module.scss'
export default class Toc extends PureComponent {
static propTypes = {
data: PropTypes.array
}
subItems = (children, parentName) =>
children.filter(filterByKindOfProperty).map(({ name, decorators }) => {
const deprecation = (decorators || []).filter(
({ name }) => name === 'deprecated'
)[0] // Assuming deprecated annotation
return (
<li key={name}>
<Scroll
type="id"
element={`${parentName}-${slugify(name)}`}
data-deprecated={!!deprecation}
offset={-20}
>
<code>{name}</code>
</Scroll>
</li>
)
})
items = this.props.data.map(({ name, children }) => {
let subIds = []
const parentName = name
subIds.push(
children.filter(filterByKindOfProperty).map(({ name }) => {
return `${parentName}-${slugify(name)}`
})
)
return (
<li key={name}>
<Scroll type="id" element={`${slugify(name)}`} offset={-20}>
<code>{name}</code>
</Scroll>
<Scrollspy
items={subIds[0]}
currentClassName={stylesSidebar.scrollspyActive}
offset={-30}
>
{this.subItems(children, name)}
</Scrollspy>
</li>
)
})
render() {
return <ul>{this.items}</ul>
}
}

View File

@ -0,0 +1,109 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { graphql } from 'gatsby'
import Helmet from 'react-helmet'
import Layout from '../../components/Layout'
import Content from '../../components/Content'
import HeaderSection from '../../components/HeaderSection'
import Sidebar from '../../components/Sidebar'
import DocHeader from '../../components/DocHeader'
import SEO from '../../components/Seo'
import { cleanTypedocData } from './utils'
import Entities from './Entities'
import Toc from './Toc'
import stylesDoc from '../Doc.module.scss'
export default class TypedocTemplate extends Component {
static propTypes = {
data: PropTypes.object.isRequired,
location: PropTypes.object.isRequired,
pageContext: PropTypes.object.isRequired
}
typedocCleaned = cleanTypedocData(
this.props.pageContext.typedoc,
this.props.pageContext.classes
)
// output section title as defined in sections.yml
sectionTitle = this.props.data.allSectionsYaml.edges.map(({ node }) => {
// compare section against section title from sections.yml
if (node.title.toLowerCase().includes('references')) {
return node.title
}
})
render() {
const { location, pageContext } = this.props
const { typedoc } = pageContext
const { info } = typedoc
const { title, description, version, sourceUrl } = info
return (
<>
<Helmet>
<body className={'references'} />
</Helmet>
<SEO
title={title}
description={description}
slug={pageContext.slug}
article
/>
<Layout location={location}>
<HeaderSection title={this.sectionTitle} />
<Content>
<main className={stylesDoc.wrapper}>
<aside className={stylesDoc.sidebar}>
<Sidebar
location={location}
sidebar={'references'}
collapsed
toc
tocComponent={
<Toc data={this.typedocCleaned} />
}
/>
</aside>
<article className={stylesDoc.main}>
<DocHeader
title={title}
description={description}
prepend={
<span className={stylesDoc.version}>
{version}
</span>
}
/>
<Entities
entities={this.typedocCleaned}
sourceUrl={sourceUrl}
/>
</article>
</main>
</Content>
</Layout>
</>
)
}
}
export const TypedocQuery = graphql`
query {
allSectionsYaml {
edges {
node {
title
description
link
}
}
}
}
`

View File

@ -0,0 +1,34 @@
export const cleanTypedocData = (data, useClasses) => {
const nodes = data.children
const cleanData = nodes
.map(node => ({
...node,
name: node.name.replace(/"/g, ''),
child: node.children && node.children[0]
}))
.filter(({ name }) => (useClasses || []).includes(name))
.sort((a, b) => useClasses.indexOf(a.name) - useClasses.indexOf(b.name))
.map(({ child }) => child)
.map(node => ({
...node,
children: node.children.sort((a, b) => a.id - b.id)
}))
return cleanData
}
// more kinds: 'Property', 'Class'
const showKindOfProperty = {
Method: { onlyPublic: true },
Property: { onlyPublic: true }
}
export const filterByKindOfProperty = ({ kindString, flags }) => {
const config = showKindOfProperty[kindString]
if (!config) return
if (config.onlyPublic && !flags.isPublic) return
return true
}