mirror of
https://github.com/explosion/spaCy.git
synced 2025-01-12 10:16:27 +03:00
Merge branch 'develop' of https://github.com/explosion/spaCy into develop
This commit is contained in:
commit
29fb7b4a16
|
@ -22,6 +22,10 @@
|
||||||
"id": "83b0498b1e7fa3c91ce68c3f1",
|
"id": "83b0498b1e7fa3c91ce68c3f1",
|
||||||
"list": "89ad33e698"
|
"list": "89ad33e698"
|
||||||
},
|
},
|
||||||
|
"docSearch": {
|
||||||
|
"apiKey": "371e26ed49d29a27bd36273dfdaf89af",
|
||||||
|
"indexName": "spacy"
|
||||||
|
},
|
||||||
"spacyVersion": "2.1",
|
"spacyVersion": "2.1",
|
||||||
"binderUrl": "ines/spacy-io-binder",
|
"binderUrl": "ines/spacy-io-binder",
|
||||||
"binderBranch": "nightly",
|
"binderBranch": "nightly",
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { ReactComponent as YesIcon } from '../images/icons/yes.svg'
|
||||||
import { ReactComponent as NoIcon } from '../images/icons/no.svg'
|
import { ReactComponent as NoIcon } from '../images/icons/no.svg'
|
||||||
import { ReactComponent as NeutralIcon } from '../images/icons/neutral.svg'
|
import { ReactComponent as NeutralIcon } from '../images/icons/neutral.svg'
|
||||||
import { ReactComponent as OfflineIcon } from '../images/icons/offline.svg'
|
import { ReactComponent as OfflineIcon } from '../images/icons/offline.svg'
|
||||||
|
import { ReactComponent as SearchIcon } from '../images/icons/search.svg'
|
||||||
|
|
||||||
import classes from '../styles/icon.module.sass'
|
import classes from '../styles/icon.module.sass'
|
||||||
|
|
||||||
|
@ -39,6 +40,7 @@ const icons = {
|
||||||
no: NoIcon,
|
no: NoIcon,
|
||||||
neutral: NeutralIcon,
|
neutral: NeutralIcon,
|
||||||
offline: OfflineIcon,
|
offline: OfflineIcon,
|
||||||
|
search: SearchIcon,
|
||||||
}
|
}
|
||||||
|
|
||||||
const Icon = ({ name, width, height, inline, variant, className }) => {
|
const Icon = ({ name, width, height, inline, variant, className }) => {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
|
import { navigate } from 'gatsby'
|
||||||
|
|
||||||
import Link from './link'
|
import Link from './link'
|
||||||
import Icon from './icon'
|
import Icon from './icon'
|
||||||
|
@ -8,36 +9,64 @@ import { github } from './util'
|
||||||
import { ReactComponent as Logo } from '../images/logo.svg'
|
import { ReactComponent as Logo } from '../images/logo.svg'
|
||||||
import classes from '../styles/navigation.module.sass'
|
import classes from '../styles/navigation.module.sass'
|
||||||
|
|
||||||
const Navigation = ({ title, items, section, children }) => (
|
const Dropdown = ({ items, section }) => {
|
||||||
<nav className={classes.root}>
|
const active = items.find(({ text }) => text.toLowerCase() === section)
|
||||||
<Link to="/" aria-label={title} hidden>
|
const defaultValue = active ? active.url : 'title'
|
||||||
<h1 className={classes.title}>{title}</h1>
|
return (
|
||||||
<Logo className={classes.logo} width={300} height={96} />
|
<select
|
||||||
</Link>
|
defaultValue={defaultValue}
|
||||||
|
className={classes.dropdown}
|
||||||
|
onChange={({ target }) => navigate(target.value)}
|
||||||
|
>
|
||||||
|
<option value="title" disabled>
|
||||||
|
Menu
|
||||||
|
</option>
|
||||||
|
{items.map(({ text, url }, i) => (
|
||||||
|
<option key={i} value={url}>
|
||||||
|
{text}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
<ul className={classes.menu}>
|
const Navigation = ({ title, items, section, search, children }) => {
|
||||||
{items.map(({ text, url }, i) => {
|
return (
|
||||||
const isActive = section && text.toLowerCase() === section
|
<nav className={classes.root}>
|
||||||
const itemClassNames = classNames(classes.item, {
|
<Link to="/" aria-label={title} hidden>
|
||||||
[classes.isActive]: isActive,
|
<h1 className={classes.title}>{title}</h1>
|
||||||
})
|
<Logo className={classes.logo} width={300} height={96} />
|
||||||
return (
|
</Link>
|
||||||
<li key={i} className={itemClassNames}>
|
|
||||||
<Link to={url} tabIndex={isActive ? '-1' : null} hidden>
|
<div className={classes.menu}>
|
||||||
{text}
|
<Dropdown items={items} section={section} />
|
||||||
|
|
||||||
|
<ul className={classes.list}>
|
||||||
|
{items.map(({ text, url }, i) => {
|
||||||
|
const isActive = section && text.toLowerCase() === section
|
||||||
|
const itemClassNames = classNames(classes.item, {
|
||||||
|
[classes.isActive]: isActive,
|
||||||
|
})
|
||||||
|
return (
|
||||||
|
<li key={i} className={itemClassNames}>
|
||||||
|
<Link to={url} tabIndex={isActive ? '-1' : null} hidden>
|
||||||
|
{text}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
<li className={classes.item}>
|
||||||
|
<Link to={github()} aria-label="GitHub" hidden>
|
||||||
|
<Icon name="github" />
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
)
|
</ul>
|
||||||
})}
|
{search && <div className={classes.search}>{search}</div>}
|
||||||
<li className={classes.item}>
|
</div>
|
||||||
<Link to={github()} aria-label="GitHub" hidden>
|
{children}
|
||||||
<Icon name="github" />
|
</nav>
|
||||||
</Link>
|
)
|
||||||
</li>
|
}
|
||||||
</ul>
|
|
||||||
{children}
|
|
||||||
</nav>
|
|
||||||
)
|
|
||||||
|
|
||||||
Navigation.defaultProps = {
|
Navigation.defaultProps = {
|
||||||
items: [],
|
items: [],
|
||||||
|
@ -52,6 +81,7 @@ Navigation.propTypes = {
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
section: PropTypes.string,
|
section: PropTypes.string,
|
||||||
|
search: PropTypes.node,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Navigation
|
export default Navigation
|
||||||
|
|
53
website/src/components/search.js
Normal file
53
website/src/components/search.js
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import { window } from 'browser-monads'
|
||||||
|
|
||||||
|
import Icon from './icon'
|
||||||
|
import classes from '../styles/search.module.sass'
|
||||||
|
|
||||||
|
const Search = ({ id, placeholder, settings }) => {
|
||||||
|
const { apiKey, indexName } = settings
|
||||||
|
const [isInitialized, setIsInitialized] = useState(false)
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isInitialized) {
|
||||||
|
setIsInitialized(true)
|
||||||
|
window.docsearch({
|
||||||
|
apiKey,
|
||||||
|
indexName,
|
||||||
|
inputSelector: `#${id}`,
|
||||||
|
debug: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, window.docsearch)
|
||||||
|
return (
|
||||||
|
<form className={classes.root}>
|
||||||
|
<label htmlFor={id} className={classes.icon}>
|
||||||
|
<Icon name="search" width={24} />
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id={id}
|
||||||
|
className={classes.input}
|
||||||
|
type="search"
|
||||||
|
placeholder={placeholder}
|
||||||
|
aria-label={placeholder}
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Search.defaultProps = {
|
||||||
|
id: 'docsearch',
|
||||||
|
placeholder: 'Search docs',
|
||||||
|
settings: {},
|
||||||
|
}
|
||||||
|
|
||||||
|
Search.propTypes = {
|
||||||
|
settings: PropTypes.shape({
|
||||||
|
apiKey: PropTypes.string.isRequired,
|
||||||
|
indexName: PropTypes.string.isRequired,
|
||||||
|
}).isRequired,
|
||||||
|
id: PropTypes.string.isRequired,
|
||||||
|
placeholder: PropTypes.string.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Search
|
|
@ -26,10 +26,10 @@ const Sidebar = ({ items, pageMenu, slug }) => {
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<menu className={classes.root}>
|
<menu className={classNames('sidebar', classes.root)}>
|
||||||
{items.map((section, i) => (
|
{items.map((section, i) => (
|
||||||
<ul className={classes.section} key={i}>
|
<ul className={classes.section} key={i}>
|
||||||
<li className={classes.label}>{section.label}</li>
|
<li className={classNames('h0', classes.label)}>{section.label}</li>
|
||||||
{section.items.map(({ text, url, onClick, menu, isActive }, j) => {
|
{section.items.map(({ text, url, onClick, menu, isActive }, j) => {
|
||||||
const currentMenu = menu || pageMenu || []
|
const currentMenu = menu || pageMenu || []
|
||||||
const active = isActive || slug === url
|
const active = isActive || slug === url
|
||||||
|
@ -43,7 +43,7 @@ const Sidebar = ({ items, pageMenu, slug }) => {
|
||||||
to={url}
|
to={url}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
className={itemClassNames}
|
className={itemClassNames}
|
||||||
activeClassName={classes.isActive}
|
activeClassName={classNames('is-active', classes.isActive)}
|
||||||
hideIcon
|
hideIcon
|
||||||
>
|
>
|
||||||
{text}
|
{text}
|
||||||
|
|
|
@ -46,8 +46,10 @@ export const Table = props => <table className={classes.root} {...props} />
|
||||||
export const Th = props => <th className={classes.th} {...props} />
|
export const Th = props => <th className={classes.th} {...props} />
|
||||||
|
|
||||||
export const Tr = ({ children, ...props }) => {
|
export const Tr = ({ children, ...props }) => {
|
||||||
|
const foot = isFootRow(children)
|
||||||
const trClasssNames = classNames(classes.tr, {
|
const trClasssNames = classNames(classes.tr, {
|
||||||
[classes.footer]: isFootRow(children),
|
[classes.footer]: foot,
|
||||||
|
'table-footer': foot,
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
import classNames from 'classnames'
|
||||||
|
|
||||||
import Button from './button'
|
import Button from './button'
|
||||||
import Tag from './tag'
|
import Tag from './tag'
|
||||||
|
@ -34,7 +35,7 @@ const Title = ({ title, tag, version, teaser, source, image, children, ...props
|
||||||
</Tag>
|
</Tag>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{teaser && <div className={classes.teaser}>{teaser}</div>}
|
{teaser && <div className={classNames('heading-teaser', classes.teaser)}>{teaser}</div>}
|
||||||
|
|
||||||
{children}
|
{children}
|
||||||
</header>
|
</header>
|
||||||
|
|
43
website/src/html.js
Normal file
43
website/src/html.js
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import React from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
|
export default function HTML(props) {
|
||||||
|
return (
|
||||||
|
<html {...props.htmlAttributes}>
|
||||||
|
<head>
|
||||||
|
<meta charSet="utf-8" />
|
||||||
|
<meta httpEquiv="x-ua-compatible" content="ie=edge" />
|
||||||
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
||||||
|
/>
|
||||||
|
{props.headComponents}
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.css"
|
||||||
|
/>
|
||||||
|
</head>
|
||||||
|
<body {...props.bodyAttributes}>
|
||||||
|
{props.preBodyComponents}
|
||||||
|
<noscript key="noscript" id="gatsby-noscript">
|
||||||
|
This app works best with JavaScript enabled.
|
||||||
|
</noscript>
|
||||||
|
<div key={`body`} id="___gatsby" dangerouslySetInnerHTML={{ __html: props.body }} />
|
||||||
|
{props.postBodyComponents}
|
||||||
|
</body>
|
||||||
|
<script
|
||||||
|
type="text/javascript"
|
||||||
|
src="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.js"
|
||||||
|
/>
|
||||||
|
</html>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
HTML.propTypes = {
|
||||||
|
htmlAttributes: PropTypes.object,
|
||||||
|
headComponents: PropTypes.array,
|
||||||
|
bodyAttributes: PropTypes.object,
|
||||||
|
preBodyComponents: PropTypes.array,
|
||||||
|
body: PropTypes.string,
|
||||||
|
postBodyComponents: PropTypes.array,
|
||||||
|
}
|
3
website/src/images/icons/search.svg
Normal file
3
website/src/images/icons/search.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path d="M9.516 14.016c2.484 0 4.5-2.016 4.5-4.5s-2.016-4.5-4.5-4.5-4.5 2.016-4.5 4.5 2.016 4.5 4.5 4.5zM15.516 14.016l4.969 4.969-1.5 1.5-4.969-4.969v-0.797l-0.281-0.281c-1.125 0.984-2.625 1.547-4.219 1.547-3.609 0-6.516-2.859-6.516-6.469s2.906-6.516 6.516-6.516 6.469 2.906 6.469 6.516c0 1.594-0.563 3.094-1.547 4.219l0.281 0.281h0.797z"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 440 B |
|
@ -18,6 +18,7 @@
|
||||||
box-shadow: var(--box-shadow)
|
box-shadow: var(--box-shadow)
|
||||||
|
|
||||||
.logo
|
.logo
|
||||||
|
min-width: 95px
|
||||||
width: 95px
|
width: 95px
|
||||||
height: 30px
|
height: 30px
|
||||||
color: var(--color-theme) !important
|
color: var(--color-theme) !important
|
||||||
|
@ -26,23 +27,12 @@
|
||||||
.title
|
.title
|
||||||
display: none
|
display: none
|
||||||
|
|
||||||
.menu
|
.list
|
||||||
display: flex
|
display: flex
|
||||||
height: 100%
|
|
||||||
flex-flow: row nowrap
|
flex-flow: row nowrap
|
||||||
border-color: inherit
|
border-color: inherit
|
||||||
overflow-x: auto
|
justify-content: flex-end
|
||||||
overflow-y: hidden
|
margin-bottom: 0.25rem
|
||||||
-webkit-overflow-scrolling: touch
|
|
||||||
|
|
||||||
@include breakpoint(max, sm)
|
|
||||||
.menu
|
|
||||||
@include scroll-shadow-base(var(--color-shadow))
|
|
||||||
margin-left: 1rem
|
|
||||||
|
|
||||||
@include breakpoint(min, md)
|
|
||||||
.menu
|
|
||||||
justify-content: flex-end
|
|
||||||
|
|
||||||
.item
|
.item
|
||||||
display: inline-flex
|
display: inline-flex
|
||||||
|
@ -58,13 +48,40 @@
|
||||||
margin-left: 2em
|
margin-left: 2em
|
||||||
|
|
||||||
&:last-child
|
&:last-child
|
||||||
@include scroll-shadow-cover(right, var(--color-back))
|
|
||||||
padding-right: 2rem
|
padding-right: 2rem
|
||||||
|
|
||||||
&:first-child
|
&:first-child
|
||||||
@include scroll-shadow-cover(left, var(--color-back))
|
|
||||||
padding-left: 2rem
|
padding-left: 2rem
|
||||||
|
|
||||||
|
.menu
|
||||||
|
display: flex
|
||||||
|
flex-flow: row nowrap
|
||||||
|
margin-left: 0.5rem
|
||||||
|
|
||||||
|
.dropdown
|
||||||
|
font-family: var(--font-secondary)
|
||||||
|
font-size: 1.6rem
|
||||||
|
font-weight: bold
|
||||||
|
color: var(--color-theme)
|
||||||
|
text-transform: uppercase
|
||||||
|
background: transparent
|
||||||
|
border: 0
|
||||||
|
margin-right: 0.5rem
|
||||||
|
|
||||||
.is-active
|
.is-active
|
||||||
color: var(--color-dark)
|
color: var(--color-dark)
|
||||||
pointer-events: none
|
pointer-events: none
|
||||||
|
|
||||||
|
.search
|
||||||
|
display: inline-flex
|
||||||
|
align-items: center
|
||||||
|
height: 100%
|
||||||
|
padding-right: 2rem
|
||||||
|
|
||||||
|
@include breakpoint(max, xs)
|
||||||
|
.list
|
||||||
|
display: none
|
||||||
|
|
||||||
|
@include breakpoint(min, sm)
|
||||||
|
.dropdown
|
||||||
|
display: none
|
||||||
|
|
57
website/src/styles/search.module.sass
Normal file
57
website/src/styles/search.module.sass
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
@import base
|
||||||
|
|
||||||
|
.root
|
||||||
|
font: var(--font-size-sm)/var(--line-height-md) var(--font-primary)
|
||||||
|
border: 1px solid var(--color-subtle)
|
||||||
|
border-radius: 2em
|
||||||
|
max-width: 100%
|
||||||
|
display: flex
|
||||||
|
flex-flow: row nowrap
|
||||||
|
|
||||||
|
&:focus-within
|
||||||
|
border-color: var(--color-theme)
|
||||||
|
box-shadow: 0 0 0 1px var(--color-theme)
|
||||||
|
|
||||||
|
.input
|
||||||
|
width: 100%
|
||||||
|
max-width: 100%
|
||||||
|
font: inherit
|
||||||
|
padding: 0.5rem 1rem 0.5rem 0.5rem
|
||||||
|
|
||||||
|
.icon
|
||||||
|
display: inline-block
|
||||||
|
color: var(--color-subtle-dark)
|
||||||
|
padding-left: 0.5rem
|
||||||
|
position: relative
|
||||||
|
top: 0.25rem
|
||||||
|
cursor: pointer
|
||||||
|
|
||||||
|
/* Algolia DocSearch */
|
||||||
|
|
||||||
|
@include breakpoint(max, xs)
|
||||||
|
\:global(.algolia-autocomplete .ds-dropdown-menu)
|
||||||
|
max-width: 90vw
|
||||||
|
min-width: 90vw
|
||||||
|
|
||||||
|
\:global(.algolia-autocomplete .algolia-docsearch-suggestion--category-header)
|
||||||
|
display: block
|
||||||
|
font: bold var(--font-size-lg)/var(--line-height-md) var(--font-secondary)
|
||||||
|
text-transform: uppercase
|
||||||
|
color: var(--color-theme)
|
||||||
|
|
||||||
|
\:global(.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column)
|
||||||
|
color: var(--color-dark)
|
||||||
|
|
||||||
|
\:global(.algolia-autocomplete .algolia-docsearch-suggestion--title)
|
||||||
|
font-size: var(--font-size-sm)
|
||||||
|
|
||||||
|
\:global(.algolia-autocomplete .ds-dropdown-menu .ds-suggestion.ds-cursor .algolia-docsearch-suggestion--content)
|
||||||
|
background: var(--color-subtle-opaque) !important
|
||||||
|
|
||||||
|
\:global(.algolia-autocomplete .algolia-docsearch-suggestion--text)
|
||||||
|
font-size: var(--font-size-sm)
|
||||||
|
|
||||||
|
\:global(.algolia-autocomplete .algolia-docsearch-suggestion--highlight)
|
||||||
|
box-shadow: none !important
|
||||||
|
background: var(--color-theme-opaque) !important
|
||||||
|
color: var(--color-theme-dark) !important
|
|
@ -30,6 +30,7 @@ import Tag from '../components/tag'
|
||||||
import Grid from '../components/grid'
|
import Grid from '../components/grid'
|
||||||
import { YouTube, SoundCloud, Iframe, Image } from '../components/embed'
|
import { YouTube, SoundCloud, Iframe, Image } from '../components/embed'
|
||||||
import Alert from '../components/alert'
|
import Alert from '../components/alert'
|
||||||
|
import Search from '../components/search'
|
||||||
|
|
||||||
const mdxComponents = {
|
const mdxComponents = {
|
||||||
a: Link,
|
a: Link,
|
||||||
|
@ -119,7 +120,12 @@ class Layout extends React.Component {
|
||||||
bodyClass={bodyClass}
|
bodyClass={bodyClass}
|
||||||
/>
|
/>
|
||||||
<AlertSpace />
|
<AlertSpace />
|
||||||
<Navigation title={meta.title} items={meta.navigation} section={section}>
|
<Navigation
|
||||||
|
title={meta.title}
|
||||||
|
items={meta.navigation}
|
||||||
|
section={section}
|
||||||
|
search={<Search settings={meta.docSearch} />}
|
||||||
|
>
|
||||||
<Progress key={location.href} />
|
<Progress key={location.href} />
|
||||||
</Navigation>
|
</Navigation>
|
||||||
{isDocs ? (
|
{isDocs ? (
|
||||||
|
@ -184,6 +190,10 @@ export const pageQuery = graphql`
|
||||||
text
|
text
|
||||||
url
|
url
|
||||||
}
|
}
|
||||||
|
docSearch {
|
||||||
|
apiKey
|
||||||
|
indexName
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file(fields: { slug: { eq: $slug } }) {
|
file(fields: { slug: { eq: $slug } }) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user