💫 Update website (#3285)
<!--- Provide a general summary of your changes in the title. -->
## Description
The new website is implemented using [Gatsby](https://www.gatsbyjs.org) with [Remark](https://github.com/remarkjs/remark) and [MDX](https://mdxjs.com/). This allows authoring content in **straightforward Markdown** without the usual limitations. Standard elements can be overwritten with powerful [React](http://reactjs.org/) components and wherever Markdown syntax isn't enough, JSX components can be used. Hopefully, this update will also make it much easier to contribute to the docs. Once this PR is merged, I'll implement auto-deployment via [Netlify](https://netlify.com) on a specific branch (to avoid building the website on every PR). There's a bunch of other cool stuff that the new setup will allow us to do – including writing front-end tests, service workers, offline support, implementing a search and so on.
This PR also includes various new docs pages and content.
Resolves #3270. Resolves #3222. Resolves #2947. Resolves #2837.
### Types of change
enhancement
## Checklist
<!--- Before you submit the PR, go over this checklist and make sure you can
tick off all the boxes. [] -> [x] -->
- [x] I have submitted the spaCy Contributor Agreement.
- [x] I ran the tests, and all new and existing tests passed.
- [x] My changes don't require a change to the documentation, or if they do, I've added all required information.
2019-02-17 21:31:19 +03:00
|
|
|
|
import React, { Fragment } from 'react'
|
|
|
|
|
import { Parser as HtmlToReactParser } from 'html-to-react'
|
|
|
|
|
import remark from 'remark'
|
|
|
|
|
import remark2react from 'remark-react'
|
|
|
|
|
import siteMetadata from '../../meta/site.json'
|
|
|
|
|
|
|
|
|
|
const htmlToReactParser = new HtmlToReactParser()
|
|
|
|
|
|
|
|
|
|
export const repo = siteMetadata.repo
|
|
|
|
|
export const modelsRepo = siteMetadata.modelsRepo
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This is used to provide selectors for headings so they can be crawled by
|
|
|
|
|
* Algolia's DocSearch
|
|
|
|
|
*/
|
|
|
|
|
export const headingTextClassName = 'heading-text'
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Create a link to the spaCy repository on GitHub
|
|
|
|
|
* @param {string} filepath - The file path relative to the root of the repo.
|
|
|
|
|
* @param {string} [branch] - Optional branch. Defaults to master.
|
|
|
|
|
* @returns {string} - URL to the file on GitHub.
|
|
|
|
|
*/
|
|
|
|
|
export function github(filepath, branch = 'master') {
|
|
|
|
|
const path = filepath ? '/tree/' + (branch || 'master') + '/' + filepath : ''
|
|
|
|
|
return `https://github.com/${repo}${path}`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the source of a file in the documentation based on its slug
|
|
|
|
|
* @param {string} slug - The slug, e.g. /api/doc.
|
|
|
|
|
* @param {boolean} [isIndex] - Whether the page is an index, e.g. /api/index.md
|
|
|
|
|
* @param {string} [branch] - Optional branch on GitHub. Defaults to master.
|
|
|
|
|
*/
|
|
|
|
|
export function getCurrentSource(slug, isIndex = false, branch = 'master') {
|
|
|
|
|
const ext = isIndex ? '/index.md' : '.md'
|
|
|
|
|
return github(`website/docs${slug}${ext}`, branch)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param obj – The object to check.
|
|
|
|
|
* @returns {boolean} - Whether the object is a string.
|
|
|
|
|
*/
|
|
|
|
|
export function isString(obj) {
|
|
|
|
|
return typeof obj === 'string' || obj instanceof String
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-08 16:52:59 +03:00
|
|
|
|
/**
|
|
|
|
|
* @param obj - The object to check.
|
|
|
|
|
* @returns {boolean} - Whether the object is empty.
|
|
|
|
|
*/
|
|
|
|
|
export function isEmptyObj(obj) {
|
|
|
|
|
return Object.entries(obj).length === 0 && obj.constructor === Object
|
|
|
|
|
}
|
|
|
|
|
|
💫 Update website (#3285)
<!--- Provide a general summary of your changes in the title. -->
## Description
The new website is implemented using [Gatsby](https://www.gatsbyjs.org) with [Remark](https://github.com/remarkjs/remark) and [MDX](https://mdxjs.com/). This allows authoring content in **straightforward Markdown** without the usual limitations. Standard elements can be overwritten with powerful [React](http://reactjs.org/) components and wherever Markdown syntax isn't enough, JSX components can be used. Hopefully, this update will also make it much easier to contribute to the docs. Once this PR is merged, I'll implement auto-deployment via [Netlify](https://netlify.com) on a specific branch (to avoid building the website on every PR). There's a bunch of other cool stuff that the new setup will allow us to do – including writing front-end tests, service workers, offline support, implementing a search and so on.
This PR also includes various new docs pages and content.
Resolves #3270. Resolves #3222. Resolves #2947. Resolves #2837.
### Types of change
enhancement
## Checklist
<!--- Before you submit the PR, go over this checklist and make sure you can
tick off all the boxes. [] -> [x] -->
- [x] I have submitted the spaCy Contributor Agreement.
- [x] I ran the tests, and all new and existing tests passed.
- [x] My changes don't require a change to the documentation, or if they do, I've added all required information.
2019-02-17 21:31:19 +03:00
|
|
|
|
/**
|
|
|
|
|
* Convert raw HTML to React elements
|
|
|
|
|
* @param {string} html - The HTML markup to convert.
|
|
|
|
|
* @returns {Node} - The converted React elements.
|
|
|
|
|
*/
|
|
|
|
|
export function htmlToReact(html) {
|
|
|
|
|
return htmlToReactParser.parse(html)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Convert raw Markdown to React
|
|
|
|
|
* @param {String} markdown - The Markdown markup to convert.
|
|
|
|
|
* @param {Object} [remarkReactComponents] - Optional React components to use
|
|
|
|
|
* for HTML elements.
|
|
|
|
|
* @returns {Node} - The converted React elements.
|
|
|
|
|
*/
|
|
|
|
|
export function markdownToReact(markdown, remarkReactComponents = {}) {
|
|
|
|
|
return remark()
|
|
|
|
|
.use(remark2react, { remarkReactComponents })
|
|
|
|
|
.processSync(markdown).contents
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Join an array of nodes with a given string delimiter, like Array.join for React
|
|
|
|
|
* @param {Array} arr - The elements to join.
|
|
|
|
|
* @param {string} delimiter - String placed between elements.
|
|
|
|
|
* @returns {Node} - The joined array.
|
|
|
|
|
*/
|
|
|
|
|
export function join(arr, delimiter = ', ') {
|
|
|
|
|
return arr.map((obj, i) => (
|
|
|
|
|
<Fragment key={i}>
|
|
|
|
|
{obj}
|
|
|
|
|
{i < arr.length - 1 && delimiter}
|
|
|
|
|
</Fragment>
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Convert an array of objects to an object, using a key with a unique value (ID).
|
|
|
|
|
* e.g. [{id: 'foo', bar: 'baz'}] => {foo: { id: 'foo', bar: 'baz'}}
|
|
|
|
|
* @param {Array} arr - The array to convert.
|
|
|
|
|
* @param {string} key - The key value to use to key the dictionary by.
|
|
|
|
|
* @return {Object} - The converted object.
|
|
|
|
|
*/
|
|
|
|
|
export function arrayToObj(arr, key) {
|
|
|
|
|
return Object.assign({}, ...arr.map(item => ({ [item[key]]: item })))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Abbreviate a number, e.g. 14249930 --> 14.25m.
|
|
|
|
|
* @param {number|string} num - The number to convert.
|
|
|
|
|
* @param {number} fixed - Number of decimals.
|
|
|
|
|
* @returns {string} - The abbreviated number.
|
|
|
|
|
*/
|
|
|
|
|
export function abbrNum(num = 0, fixed = 1) {
|
|
|
|
|
const suffixes = ['', 'k', 'm', 'b', 't']
|
|
|
|
|
if (num === null || num === 0) return 0
|
|
|
|
|
const b = num.toPrecision(2).split('e')
|
|
|
|
|
const k = b.length === 1 ? 0 : Math.floor(Math.min(b[1].slice(1), 14) / 3)
|
|
|
|
|
const n = k < 1 ? num : num / Math.pow(10, k * 3)
|
|
|
|
|
const c = k >= 1 && n >= 100 ? Math.round(n) : n.toFixed(fixed)
|
|
|
|
|
return (c < 0 ? c : Math.abs(c)) + suffixes[k]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Divide an array into chunks
|
|
|
|
|
* @param {Array} arr - The array to divide.
|
|
|
|
|
* @param {number} chunkSize - Size of the individual chunks.
|
|
|
|
|
* @returns {Array} - The divided array.
|
|
|
|
|
*/
|
|
|
|
|
export function chunkArray(arr, chunkSize) {
|
|
|
|
|
const base = [...arr]
|
|
|
|
|
const result = []
|
|
|
|
|
while (base.length) {
|
|
|
|
|
result.push(base.splice(0, chunkSize))
|
|
|
|
|
}
|
|
|
|
|
return result
|
|
|
|
|
}
|