diff --git a/README.rst b/README.rst
index 60e1b9e8c..139453344 100644
--- a/README.rst
+++ b/README.rst
@@ -49,7 +49,7 @@ integration. It's commercial open-source software, released under the MIT licens
`New in v2.0`_ New features, backwards incompatibilities and migration guide.
`API Reference`_ The detailed reference for spaCy's API.
`Models`_ Download statistical language models for spaCy.
-`Resources`_ Libraries, extensions, demos, books and courses.
+`Universe`_ Libraries, extensions, demos, books and courses.
`Changelog`_ Changes and version history.
`Contribute`_ How to contribute to the spaCy project and code base.
=================== ===
@@ -59,7 +59,7 @@ integration. It's commercial open-source software, released under the MIT licens
.. _Usage Guides: https://spacy.io/usage/
.. _API Reference: https://spacy.io/api/
.. _Models: https://spacy.io/models
-.. _Resources: https://spacy.io/usage/resources
+.. _Universe: https://spacy.io/universe
.. _Changelog: https://spacy.io/usage/#changelog
.. _Contribute: https://github.com/explosion/spaCy/blob/master/CONTRIBUTING.md
diff --git a/examples/training/train_textcat.py b/examples/training/train_textcat.py
index 34de9f836..61cd7e51e 100644
--- a/examples/training/train_textcat.py
+++ b/examples/training/train_textcat.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# coding: utf8
-"""Train a multi-label convolutional neural network text classifier on the
+"""Train a convolutional neural network text classifier on the
IMDB dataset, using the TextCategorizer component. The dataset will be loaded
automatically via Thinc's built-in dataset loader. The model is added to
spacy.pipeline, and predictions are available via `doc.cats`. For more details,
diff --git a/website/_harp.json b/website/_harp.json
index 7da11afa4..a7e12da4b 100644
--- a/website/_harp.json
+++ b/website/_harp.json
@@ -1,7 +1,7 @@
{
"globals": {
"title": "spaCy",
- "description": "spaCy is a free open-source library featuring state-of-the-art speed and accuracy and a powerful Python API.",
+ "description": "spaCy is a free open-source library for Natural Language Processing in Python. It features NER, POS tagging, dependency parsing, word vectors and more.",
"SITENAME": "spaCy",
"SLOGAN": "Industrial-strength Natural Language Processing in Python",
@@ -10,10 +10,13 @@
"COMPANY": "Explosion AI",
"COMPANY_URL": "https://explosion.ai",
- "DEMOS_URL": "https://demos.explosion.ai",
+ "DEMOS_URL": "https://explosion.ai/demos",
"MODELS_REPO": "explosion/spacy-models",
+ "KERNEL_BINDER": "ines/spacy-binder",
+ "KERNEL_PYTHON": "python3",
"SPACY_VERSION": "2.0",
+ "BINDER_VERSION": "2.0.11",
"SOCIAL": {
"twitter": "spacy_io",
@@ -26,7 +29,8 @@
"NAVIGATION": {
"Usage": "/usage",
"Models": "/models",
- "API": "/api"
+ "API": "/api",
+ "Universe": "/universe"
},
"FOOTER": {
@@ -34,7 +38,7 @@
"Usage": "/usage",
"Models": "/models",
"API Reference": "/api",
- "Resources": "/usage/resources"
+ "Universe": "/universe"
},
"Support": {
"Issue Tracker": "https://github.com/explosion/spaCy/issues",
@@ -82,8 +86,8 @@
}
],
- "V_CSS": "2.0.1",
- "V_JS": "2.0.1",
+ "V_CSS": "2.1.1",
+ "V_JS": "2.1.0",
"DEFAULT_SYNTAX": "python",
"ANALYTICS": "UA-58931649-1",
"MAILCHIMP": {
diff --git a/website/_includes/_functions.jade b/website/_includes/_functions.jade
index 39139cc58..c93469db1 100644
--- a/website/_includes/_functions.jade
+++ b/website/_includes/_functions.jade
@@ -15,12 +15,39 @@
- MODEL_META = public.models._data.MODEL_META
- MODEL_LICENSES = public.models._data.MODEL_LICENSES
- MODEL_BENCHMARKS = public.models._data.MODEL_BENCHMARKS
+- EXAMPLE_SENT_LANGS = public.models._data.EXAMPLE_SENT_LANGS
- EXAMPLE_SENTENCES = public.models._data.EXAMPLE_SENTENCES
- IS_PAGE = (SECTION != "index") && !landing
- IS_MODELS = (SECTION == "models" && LANGUAGES[current.source])
- HAS_MODELS = IS_MODELS && CURRENT_MODELS.length
+//- Get page URL
+
+- function getPageUrl() {
+- var path = current.path;
+- if(path[path.length - 1] == 'index') path = path.slice(0, path.length - 1);
+- return `${SITE_URL}/${path.join('/')}`;
+- }
+
+//- Get pretty page title depending on section
+
+- function getPageTitle() {
+- var sections = ['api', 'usage', 'models'];
+- if (sections.includes(SECTION)) {
+- var titleSection = (SECTION == "api") ? 'API' : SECTION.charAt(0).toUpperCase() + SECTION.slice(1);
+- return `${title} · ${SITENAME} ${titleSection} Documentation`;
+- }
+- else if (SECTION != 'index') return `${title} · ${SITENAME}`;
+- return `${SITENAME} · ${SLOGAN}`;
+- }
+
+//- Get social image based on section and settings
+
+- function getPageImage() {
+- var img = (SECTION == 'api') ? 'api' : 'default';
+- return `${SITE_URL}/assets/img/social/preview_${preview || img}.jpg`;
+- }
//- Add prefixes to items of an array (for modifier CSS classes)
array - [array] list of class names or options, e.g. ["foot"]
diff --git a/website/_includes/_mixins.jade b/website/_includes/_mixins.jade
index 158668de5..105d04b8a 100644
--- a/website/_includes/_mixins.jade
+++ b/website/_includes/_mixins.jade
@@ -7,7 +7,7 @@ include _functions
id - [string] anchor assigned to section (used for breadcrumb navigation)
mixin section(id)
- section.o-section(id="section-" + id data-section=id)
+ section.o-section(id=id ? "section-" + id : null data-section=id)&attributes(attributes)
block
@@ -143,7 +143,7 @@ mixin aside-wrapper(label, emoji)
mixin aside(label, emoji)
+aside-wrapper(label, emoji)
- .c-aside__text.u-text-small
+ .c-aside__text.u-text-small&attributes(attributes)
block
@@ -154,7 +154,7 @@ mixin aside(label, emoji)
prompt - [string] prompt displayed before first line, e.g. "$"
mixin aside-code(label, language, prompt)
- +aside-wrapper(label)
+ +aside-wrapper(label)&attributes(attributes)
+code(false, language, prompt).o-no-block
block
@@ -165,7 +165,7 @@ mixin aside-code(label, language, prompt)
argument to be able to wrap it for spacing
mixin infobox(label, emoji)
- aside.o-box.o-block.u-text-small
+ aside.o-box.o-block.u-text-small&attributes(attributes)
if label
h3.u-heading.u-text-label.u-color-theme
if emoji
@@ -242,7 +242,9 @@ mixin button(url, trusted, ...style)
wrap - [boolean] wrap text and disable horizontal scrolling
mixin code(label, language, prompt, height, icon, wrap)
- pre.c-code-block.o-block(class="lang-#{(language || DEFAULT_SYNTAX)}" class=icon ? "c-code-block--has-icon" : null style=height ? "height: #{height}px" : null)&attributes(attributes)
+ - var lang = (language != "none") ? (language || DEFAULT_SYNTAX) : null
+ - var lang_class = (language != "none") ? "lang-" + (language || DEFAULT_SYNTAX) : null
+ pre.c-code-block.o-block(data-language=lang class=lang_class class=icon ? "c-code-block--has-icon" : null style=height ? "height: #{height}px" : null)&attributes(attributes)
if label
h4.u-text-label.u-text-label--dark=label
if icon
@@ -253,6 +255,15 @@ mixin code(label, language, prompt, height, icon, wrap)
code.c-code-block__content(class=wrap ? "u-wrap" : null data-prompt=prompt)
block
+//- Executable code
+
+mixin code-exec(label, large)
+ - label = (label || "Editable code example") + " (experimental)"
+ +terminal-wrapper(label, !large)
+ figure.thebelab-wrapper
+ span.thebelab-wrapper__text.u-text-tiny v#{BINDER_VERSION} · Python 3 · via #[+a("https://mybinder.org/").u-hide-link Binder]
+ +code(data-executable="true")&attributes(attributes)
+ block
//- Wrapper for code blocks to display old/new versions
@@ -658,12 +669,16 @@ mixin qs(data, style)
//- Terminal-style code window
label - [string] title displayed in top bar of terminal window
-mixin terminal(label, button_text, button_url)
- .x-terminal
- .x-terminal__icons: span
- .u-padding-small.u-text-label.u-text-center=label
+mixin terminal-wrapper(label, small)
+ .x-terminal(class=small ? "x-terminal--small" : null)
+ .x-terminal__icons(class=small ? "x-terminal__icons--small" : null): span
+ .u-padding-small.u-text-center(class=small ? "u-text-tiny" : "u-text")
+ strong=label
+ block
- +code.x-terminal__code
+mixin terminal(label, button_text, button_url, exec)
+ +terminal-wrapper(label)
+ +code.x-terminal__code(data-executable=exec ? "" : null)
block
if button_text && button_url
diff --git a/website/_includes/_navigation.jade b/website/_includes/_navigation.jade
index 8ce5e394b..71868987a 100644
--- a/website/_includes/_navigation.jade
+++ b/website/_includes/_navigation.jade
@@ -10,10 +10,7 @@ nav.c-nav.u-text.js-nav(class=landing ? "c-nav--theme" : null)
li.c-nav__menu__item(class=is_active ? "is-active" : null)
+a(url)(tabindex=is_active ? "-1" : null)=item
- li.c-nav__menu__item.u-hidden-xs
- +a("https://survey.spacy.io", true) User Survey 2018
-
- li.c-nav__menu__item.u-hidden-xs
+ li.c-nav__menu__item
+a(gh("spaCy"))(aria-label="GitHub") #[+icon("github", 20)]
progress.c-progress.js-progress(value="0" max="1")
diff --git a/website/_includes/_page_models.jade b/website/_includes/_page_models.jade
index d0fe05a6c..16d68fd8a 100644
--- a/website/_includes/_page_models.jade
+++ b/website/_includes/_page_models.jade
@@ -1,77 +1,110 @@
//- 💫 INCLUDES > MODELS PAGE TEMPLATE
for id in CURRENT_MODELS
+ - var comps = getModelComponents(id)
+section(id)
- +grid("vcenter").o-no-block(id=id)
- +grid-col("two-thirds")
- +h(2)
- +a("#" + id).u-permalink=id
+ section(data-vue=id data-model=id)
+ +grid("vcenter").o-no-block(id=id)
+ +grid-col("two-thirds")
+ +h(2)
+ +a("#" + id).u-permalink=id
- +grid-col("third").u-text-right
- .u-color-subtle.u-text-tiny
- +button(gh("spacy-models") + "/releases", true, "secondary", "small")(data-tpl=id data-tpl-key="download")
- | Release details
- .u-padding-small Latest: #[code(data-tpl=id data-tpl-key="version") n/a]
+ +grid-col("third").u-text-right
+ .u-color-subtle.u-text-tiny
+ +button(gh("spacy-models") + "/releases", true, "secondary", "small")(v-bind:href="releaseUrl")
+ | Release details
+ .u-padding-small Latest: #[code(v-text="version") n/a]
- +aside-code("Installation", "bash", "$").
- python -m spacy download #{id}
+ +aside-code("Installation", "bash", "$").
+ python -m spacy download #{id}
- - var comps = getModelComponents(id)
+ p(v-if="description" v-text="description")
- p(data-tpl=id data-tpl-key="description")
-
- div(data-tpl=id data-tpl-key="error")
- +infobox
+ +infobox(v-if="error")
| Unable to load model details from GitHub. To find out more
| about this model, see the overview of the
| #[+a(gh("spacy-models") + "/releases") latest model releases].
- +table.o-block-small(data-tpl=id data-tpl-key="table")
- +row
- +cell #[+label Language]
- +cell #[+tag=comps.lang] #{LANGUAGES[comps.lang]}
- for comp, label in {"Type": comps.type, "Genre": comps.genre}
+ +table.o-block-small(v-bind:data-loading="loading")
+row
- +cell #[+label=label]
- +cell #[+tag=comp] #{MODEL_META[comp]}
- +row
- +cell #[+label Size]
- +cell #[+tag=comps.size] #[span(data-tpl=id data-tpl-key="size") #[em n/a]]
+ +cell #[+label Language]
+ +cell #[+tag=comps.lang] #{LANGUAGES[comps.lang]}
+ for comp, label in {"Type": comps.type, "Genre": comps.genre}
+ +row
+ +cell #[+label=label]
+ +cell #[+tag=comp] #{MODEL_META[comp]}
+ +row
+ +cell #[+label Size]
+ +cell #[+tag=comps.size] #[span(v-text="sizeFull" v-if="sizeFull")] #[em(v-else="") n/a]
- each label in ["Pipeline", "Vectors", "Sources", "Author", "License"]
- - var field = label.toLowerCase()
- if field == "vectors"
- - field = "vecs"
- +row
- +cell.u-nowrap
- +label=label
- if MODEL_META[field]
- | #[+help(MODEL_META[field]).u-color-subtle]
+ +row(v-if="pipeline && pipeline.length" v-cloak="")
+cell
- span(data-tpl=id data-tpl-key=field) #[em n/a]
+ +label Pipeline #[+help(MODEL_META.pipeline).u-color-subtle]
+ +cell
+ span(v-for="(pipe, index) in pipeline" v-if="pipeline")
+ code(v-text="pipe")
+ span(v-if="index != pipeline.length - 1") ,
- +row(data-tpl=id data-tpl-key="compat-wrapper" hidden="")
- +cell
- +label Compat #[+help("Latest compatible model version for your spaCy installation").u-color-subtle]
- +cell
- .o-field.u-float-left
- select.o-field__select.u-text-small(data-tpl=id data-tpl-key="compat")
- div(data-tpl=id data-tpl-key="compat-versions")
+ +row(v-if="vectors" v-cloak="")
+ +cell
+ +label Vectors #[+help(MODEL_META.vectors).u-color-subtle]
+ +cell(v-text="vectors")
- section(data-tpl=id data-tpl-key="benchmarks" hidden="")
- +grid.o-block-small
+ +row(v-if="sources && sources.length" v-cloak="")
+ +cell
+ +label Sources #[+help(MODEL_META.sources).u-color-subtle]
+ +cell
+ span(v-for="(source, index) in sources") {{ source }}
+ span(v-if="index != sources.length - 1") ,
+
+ +row(v-if="author" v-cloak="")
+ +cell #[+label Author]
+ +cell
+ +a("")(v-bind:href="url" v-if="url" v-text="author")
+ span(v-else="" v-text="author") {{ model.author }}
+
+ +row(v-if="license" v-cloak="")
+ +cell #[+label License]
+ +cell
+ +a("")(v-bind:href="modelLicenses[license]" v-if="modelLicenses[license]") {{ license }}
+ span(v-else="") {{ license }}
+
+ +row(v-cloak="")
+ +cell #[+label Compat #[+help(MODEL_META.compat).u-color-subtle]]
+ +cell
+ .o-field.u-float-left
+ select.o-field__select.u-text-small(v-model="spacyVersion")
+ option(v-for="version in orderedCompat" v-bind:value="version") spaCy v{{ version }}
+ code(v-if="compatVersion" v-text="compatVersion")
+ em(v-else="") not compatible
+
+ +grid.o-block-small(v-cloak="" v-if="hasAccuracy")
for keys, label in MODEL_BENCHMARKS
- .u-flex-full.u-padding-small(data-tpl=id data-tpl-key=label.toLowerCase() hidden="")
+ .u-flex-full.u-padding-small
+table.o-block-small
+row("head")
+head-cell(colspan="2")=(MODEL_META["benchmark_" + label] || label)
for label, field in keys
- +row(hidden="")
+ +row
+cell.u-nowrap
+label=label
if MODEL_META[field]
| #[+help(MODEL_META[field]).u-color-subtle]
- +cell("num")(data-tpl=id data-tpl-key=field)
- | n/a
+ +cell("num")
+ span(v-if="#{field}" v-text="#{field}")
+ em(v-if="!#{field}") n/a
+
+ p.u-text-small.u-color-dark(v-if="notes" v-text="notes" v-cloak="")
+
+ if comps.size == "sm" && EXAMPLE_SENT_LANGS.includes(comps.lang)
+ section
+ +code-exec("Test the model live").
+ import spacy
+ from spacy.lang.#{comps.lang}.examples import sentences
+
+ nlp = spacy.load('#{id}')
+ doc = nlp(sentences[0])
+ print(doc.text)
+ for token in doc:
+ print(token.text, token.pos_, token.dep_)
- p.u-text-small.u-color-dark(data-tpl=id data-tpl-key="notes")
diff --git a/website/_includes/_scripts.jade b/website/_includes/_scripts.jade
index a70f880a0..b93b8cd00 100644
--- a/website/_includes/_scripts.jade
+++ b/website/_includes/_scripts.jade
@@ -1,86 +1,33 @@
//- 💫 INCLUDES > SCRIPTS
-if quickstart
- script(src="/assets/js/vendor/quickstart.min.js")
+if IS_PAGE || SECTION == "index"
+ script(type="text/x-thebe-config")
+ | { bootstrap: true, binderOptions: { repo: "#{KERNEL_BINDER}"},
+ | kernelOptions: { name: "#{KERNEL_PYTHON}" }}
-if IS_PAGE
- script(src="/assets/js/vendor/in-view.min.js")
+- scripts = ["vendor/prism.min", "vendor/vue.min"]
+- if (SECTION == "universe") scripts.push("vendor/vue-markdown.min")
+- if (quickstart) scripts.push("vendor/quickstart.min")
+- if (IS_PAGE) scripts.push("vendor/in-view.min")
+- if (IS_PAGE || SECTION == "index") scripts.push("vendor/thebelab.custom.min")
+
+for script in scripts
+ script(src="/assets/js/" + script + ".js")
+script(src="/assets/js/main.js?v#{V_JS}" type=(environment == "deploy") ? null : "module")
if environment == "deploy"
- script(async src="https://www.google-analytics.com/analytics.js")
-
-script(src="/assets/js/vendor/prism.min.js")
-
-if compare_models
- script(src="/assets/js/vendor/chart.min.js")
-
-script
- if quickstart
- | new Quickstart("#qs");
-
- if environment == "deploy"
+ script(src="https://www.google-analytics.com/analytics.js", async)
+ script
| window.ga=window.ga||function(){
| (ga.q=ga.q||[]).push(arguments)}; ga.l=+new Date;
| ga('create', '#{ANALYTICS}', 'auto'); ga('send', 'pageview');
- if IS_PAGE
+if IS_PAGE
+ script(src="https://sidecar.gitter.im/dist/sidecar.v1.js" async defer)
+ script
| ((window.gitter = {}).chat = {}).options = {
| useStyles: false,
| activationElement: '.js-gitter-button',
| targetElement: '.js-gitter',
| room: '!{SOCIAL.gitter}'
| };
-
-if IS_PAGE
- script(src="https://sidecar.gitter.im/dist/sidecar.v1.js" async defer)
-
-
-//- JS modules – slightly hacky, but necessary to dynamically instantiate the
- classes with data from the Harp JSON files, while still being able to
- support older browsers that can't handle JS modules. More details:
- https://medium.com/dev-channel/es6-modules-in-chrome-canary-m60-ba588dfb8ab7
-
-- ProgressBar = "new ProgressBar('.js-progress');"
-- Accordion = "new Accordion('.js-accordion');"
-- Changelog = "new Changelog('" + SOCIAL.github + "', 'spacy');"
-- NavHighlighter = "new NavHighlighter('data-section', 'data-nav');"
-- GitHubEmbed = "new GitHubEmbed('" + SOCIAL.github + "', 'data-gh-embed');"
-- ModelLoader = "new ModelLoader('" + MODELS_REPO + "'," + JSON.stringify(CURRENT_MODELS) + "," + JSON.stringify(MODEL_LICENSES) + "," + JSON.stringify(MODEL_BENCHMARKS) + ");"
-- ModelComparer = "new ModelComparer('" + MODELS_REPO + "'," + JSON.stringify(MODEL_LICENSES) + "," + JSON.stringify(MODEL_BENCHMARKS) + "," + JSON.stringify(LANGUAGES) + "," + JSON.stringify(MODEL_META) + "," + JSON.stringify(default_models || false) + ");"
-
-if environment == "deploy"
- //- DEPLOY: use compiled rollup.js and instantiate classes directly
- script(src="/assets/js/rollup.js?v#{V_JS}")
- script
- !=ProgressBar
- if changelog
- !=Changelog
- if IS_PAGE
- !=NavHighlighter
- !=GitHubEmbed
- !=Accordion
- if HAS_MODELS
- !=ModelLoader
- if compare_models
- !=ModelComparer
-else
- //- DEVELOPMENT: Use ES6 modules
- script(type="module")
- | import ProgressBar from '/assets/js/progress.js';
- !=ProgressBar
- if changelog
- | import Changelog from '/assets/js/changelog.js';
- !=Changelog
- if IS_PAGE
- | import NavHighlighter from '/assets/js/nav-highlighter.js';
- !=NavHighlighter
- | import GitHubEmbed from '/assets/js/github-embed.js';
- !=GitHubEmbed
- | import Accordion from '/assets/js/accordion.js';
- !=Accordion
- if HAS_MODELS
- | import { ModelLoader } from '/assets/js/models.js';
- !=ModelLoader
- if compare_models
- | import { ModelComparer } from '/assets/js/models.js';
- !=ModelComparer
diff --git a/website/_includes/_svg.jade b/website/_includes/_svg.jade
index 77f5fa543..b7b988db9 100644
--- a/website/_includes/_svg.jade
+++ b/website/_includes/_svg.jade
@@ -7,6 +7,12 @@ svg(style="position: absolute; visibility: hidden; width: 0; height: 0;" width="
symbol#svg_github(viewBox="0 0 27 32")
path(d="M13.714 2.286q3.732 0 6.884 1.839t4.991 4.991 1.839 6.884q0 4.482-2.616 8.063t-6.759 4.955q-0.482 0.089-0.714-0.125t-0.232-0.536q0-0.054 0.009-1.366t0.009-2.402q0-1.732-0.929-2.536 1.018-0.107 1.83-0.321t1.679-0.696 1.446-1.188 0.946-1.875 0.366-2.688q0-2.125-1.411-3.679 0.661-1.625-0.143-3.643-0.5-0.161-1.446 0.196t-1.643 0.786l-0.679 0.429q-1.661-0.464-3.429-0.464t-3.429 0.464q-0.286-0.196-0.759-0.482t-1.491-0.688-1.518-0.241q-0.804 2.018-0.143 3.643-1.411 1.554-1.411 3.679 0 1.518 0.366 2.679t0.938 1.875 1.438 1.196 1.679 0.696 1.83 0.321q-0.696 0.643-0.875 1.839-0.375 0.179-0.804 0.268t-1.018 0.089-1.17-0.384-0.991-1.116q-0.339-0.571-0.866-0.929t-0.884-0.429l-0.357-0.054q-0.375 0-0.518 0.080t-0.089 0.205 0.161 0.25 0.232 0.214l0.125 0.089q0.393 0.179 0.777 0.679t0.563 0.911l0.179 0.411q0.232 0.679 0.786 1.098t1.196 0.536 1.241 0.125 0.991-0.063l0.411-0.071q0 0.679 0.009 1.58t0.009 0.973q0 0.321-0.232 0.536t-0.714 0.125q-4.143-1.375-6.759-4.955t-2.616-8.063q0-3.732 1.839-6.884t4.991-4.991 6.884-1.839zM5.196 21.982q0.054-0.125-0.125-0.214-0.179-0.054-0.232 0.036-0.054 0.125 0.125 0.214 0.161 0.107 0.232-0.036zM5.75 22.589q0.125-0.089-0.036-0.286-0.179-0.161-0.286-0.054-0.125 0.089 0.036 0.286 0.179 0.179 0.286 0.054zM6.286 23.393q0.161-0.125 0-0.339-0.143-0.232-0.304-0.107-0.161 0.089 0 0.321t0.304 0.125zM7.036 24.143q0.143-0.143-0.071-0.339-0.214-0.214-0.357-0.054-0.161 0.143 0.071 0.339 0.214 0.214 0.357 0.054zM8.054 24.589q0.054-0.196-0.232-0.286-0.268-0.071-0.339 0.125t0.232 0.268q0.268 0.107 0.339-0.107zM9.179 24.679q0-0.232-0.304-0.196-0.286 0-0.286 0.196 0 0.232 0.304 0.196 0.286 0 0.286-0.196zM10.214 24.5q-0.036-0.196-0.321-0.161-0.286 0.054-0.25 0.268t0.321 0.143 0.25-0.25z")
+ symbol#svg_twitter(viewBox="0 0 30 32")
+ path(d="M28.929 7.286q-1.196 1.75-2.893 2.982 0.018 0.25 0.018 0.75 0 2.321-0.679 4.634t-2.063 4.437-3.295 3.759-4.607 2.607-5.768 0.973q-4.839 0-8.857-2.589 0.625 0.071 1.393 0.071 4.018 0 7.161-2.464-1.875-0.036-3.357-1.152t-2.036-2.848q0.589 0.089 1.089 0.089 0.768 0 1.518-0.196-2-0.411-3.313-1.991t-1.313-3.67v-0.071q1.214 0.679 2.607 0.732-1.179-0.786-1.875-2.054t-0.696-2.75q0-1.571 0.786-2.911 2.161 2.661 5.259 4.259t6.634 1.777q-0.143-0.679-0.143-1.321 0-2.393 1.688-4.080t4.080-1.688q2.5 0 4.214 1.821 1.946-0.375 3.661-1.393-0.661 2.054-2.536 3.179 1.661-0.179 3.321-0.893z")
+
+ symbol#svg_website(viewBox="0 0 32 32")
+ path(d="M22.658 10.988h5.172c0.693 1.541 1.107 3.229 1.178 5.012h-5.934c-0.025-1.884-0.181-3.544-0.416-5.012zM20.398 3.896c2.967 1.153 5.402 3.335 6.928 6.090h-4.836c-0.549-2.805-1.383-4.799-2.092-6.090zM16.068 9.986v-6.996c1.066 0.047 2.102 0.216 3.092 0.493 0.75 1.263 1.719 3.372 2.33 6.503h-5.422zM9.489 22.014c-0.234-1.469-0.396-3.119-0.421-5.012h5.998v5.012h-5.577zM9.479 10.988h5.587v5.012h-6.004c0.025-1.886 0.183-3.543 0.417-5.012zM11.988 3.461c0.987-0.266 2.015-0.435 3.078-0.469v6.994h-5.422c0.615-3.148 1.591-5.265 2.344-6.525zM3.661 9.986c1.551-2.8 4.062-4.993 7.096-6.131-0.715 1.29-1.559 3.295-2.114 6.131h-4.982zM8.060 16h-6.060c0.066-1.781 0.467-3.474 1.158-5.012h5.316c-0.233 1.469-0.39 3.128-0.414 5.012zM8.487 22.014h-5.29c-0.694-1.543-1.139-3.224-1.204-5.012h6.071c0.024 1.893 0.188 3.541 0.423 5.012zM8.651 23.016c0.559 2.864 1.416 4.867 2.134 6.142-3.045-1.133-5.557-3.335-7.11-6.142h4.976zM15.066 23.016v6.994c-1.052-0.033-2.067-0.199-3.045-0.46-0.755-1.236-1.736-3.363-2.356-6.534h5.401zM21.471 23.016c-0.617 3.152-1.592 5.271-2.344 6.512-0.979 0.271-2.006 0.418-3.059 0.465v-6.977h5.403zM16.068 17.002h5.998c-0.023 1.893-0.188 3.542-0.422 5.012h-5.576v-5.012zM22.072 16h-6.004v-5.012h5.586c0.235 1.469 0.393 3.126 0.418 5.012zM23.070 17.002h5.926c-0.066 1.787-0.506 3.468-1.197 5.012h-5.152c0.234-1.471 0.398-3.119 0.423-5.012zM27.318 23.016c-1.521 2.766-3.967 4.949-6.947 6.1 0.715-1.276 1.561-3.266 2.113-6.1h4.834z")
+
symbol#svg_code(viewBox="0 0 20 20")
path(d="M5.719 14.75c-0.236 0-0.474-0.083-0.664-0.252l-5.060-4.498 5.341-4.748c0.412-0.365 1.044-0.33 1.411 0.083s0.33 1.045-0.083 1.412l-3.659 3.253 3.378 3.002c0.413 0.367 0.45 0.999 0.083 1.412-0.197 0.223-0.472 0.336-0.747 0.336zM14.664 14.748l5.341-4.748-5.060-4.498c-0.413-0.367-1.045-0.33-1.411 0.083s-0.33 1.045 0.083 1.412l3.378 3.003-3.659 3.252c-0.413 0.367-0.45 0.999-0.083 1.412 0.197 0.223 0.472 0.336 0.747 0.336 0.236 0 0.474-0.083 0.664-0.252zM9.986 16.165l2-12c0.091-0.545-0.277-1.060-0.822-1.151-0.547-0.092-1.061 0.277-1.15 0.822l-2 12c-0.091 0.545 0.277 1.060 0.822 1.151 0.056 0.009 0.11 0.013 0.165 0.013 0.48 0 0.904-0.347 0.985-0.835z")
diff --git a/website/_layout.jade b/website/_layout.jade
index 5ee65da77..b0a1342e5 100644
--- a/website/_layout.jade
+++ b/website/_layout.jade
@@ -3,23 +3,15 @@
include _includes/_mixins
- title = IS_MODELS ? LANGUAGES[current.source] || title : title
-- social_title = (SECTION == "index") ? SITENAME + " - " + SLOGAN : title + " - " + SITENAME
-- social_img = SITE_URL + "/assets/img/social/preview_" + (preview || ALPHA ? "alpha" : "default") + ".jpg"
+
+- PAGE_URL = getPageUrl()
+- PAGE_TITLE = getPageTitle()
+- PAGE_IMAGE = getPageImage()
doctype html
html(lang="en")
head
- title
- if SECTION == "api" || SECTION == "usage" || SECTION == "models"
- - var title_section = (SECTION == "api") ? "API" : SECTION.charAt(0).toUpperCase() + SECTION.slice(1)
- | #{title} | #{SITENAME} #{title_section} Documentation
-
- else if SECTION != "index"
- | #{title} | #{SITENAME}
-
- else
- | #{SITENAME} - #{SLOGAN}
-
+ title=PAGE_TITLE
meta(charset="utf-8")
meta(name="viewport" content="width=device-width, initial-scale=1.0")
meta(name="referrer" content="always")
@@ -27,23 +19,24 @@ html(lang="en")
meta(property="og:type" content="website")
meta(property="og:site_name" content=sitename)
- meta(property="og:url" content="#{SITE_URL}/#{current.path.join('/')}")
- meta(property="og:title" content=social_title)
+ meta(property="og:url" content=PAGE_URL)
+ meta(property="og:title" content=PAGE_TITLE)
meta(property="og:description" content=description)
- meta(property="og:image" content=social_img)
+ meta(property="og:image" content=PAGE_IMAGE)
meta(name="twitter:card" content="summary_large_image")
meta(name="twitter:site" content="@" + SOCIAL.twitter)
- meta(name="twitter:title" content=social_title)
+ meta(name="twitter:title" content=PAGE_TITLE)
meta(name="twitter:description" content=description)
- meta(name="twitter:image" content=social_img)
+ meta(name="twitter:image" content=PAGE_IMAGE)
link(rel="shortcut icon" href="/assets/img/favicon.ico")
link(rel="icon" type="image/x-icon" href="/assets/img/favicon.ico")
if SECTION == "api"
link(href="/assets/css/style_green.css?v#{V_CSS}" rel="stylesheet")
-
+ else if SECTION == "universe"
+ link(href="/assets/css/style_purple.css?v#{V_CSS}" rel="stylesheet")
else
link(href="/assets/css/style.css?v#{V_CSS}" rel="stylesheet")
@@ -54,6 +47,9 @@ html(lang="en")
if !landing
include _includes/_page-docs
+ else if SECTION == "universe"
+ !=yield
+
else
main!=yield
include _includes/_footer
diff --git a/website/api/_architecture/_nn-model.jade b/website/api/_architecture/_nn-model.jade
index 8080af2ec..b7c32eae6 100644
--- a/website/api/_architecture/_nn-model.jade
+++ b/website/api/_architecture/_nn-model.jade
@@ -1,5 +1,13 @@
//- 💫 DOCS > API > ARCHITECTURE > NN MODEL ARCHITECTURE
+p
+ | spaCy's statistical models have been custom-designed to give a
+ | high-performance mix of speed and accuracy. The current architecture
+ | hasn't been published yet, but in the meantime we prepared a video that
+ | explains how the models work, with particular focus on NER.
+
++youtube("sqDHBH9IjRU")
+
p
| The parsing model is a blend of recent results. The two recent
| inspirations have been the work of Eli Klipperwasser and Yoav Goldberg at
@@ -44,7 +52,7 @@ p
+cell First two words of the buffer.
+row
- +cell.u-nowrap
+ +cell
| #[code S0L1], #[code S1L1], #[code S2L1], #[code B0L1],
| #[code B1L1]#[br]
| #[code S0L2], #[code S1L2], #[code S2L2], #[code B0L2],
@@ -54,7 +62,7 @@ p
| #[code S2], #[code B0] and #[code B1].
+row
- +cell.u-nowrap
+ +cell
| #[code S0R1], #[code S1R1], #[code S2R1], #[code B0R1],
| #[code B1R1]#[br]
| #[code S0R2], #[code S1R2], #[code S2R2], #[code B0R2],
diff --git a/website/assets/css/_base/_objects.sass b/website/assets/css/_base/_objects.sass
index b8a20f5dd..f54667c3f 100644
--- a/website/assets/css/_base/_objects.sass
+++ b/website/assets/css/_base/_objects.sass
@@ -60,6 +60,13 @@
padding-bottom: 4rem
border-bottom: 1px dotted $color-subtle
+ &.o-section--small
+ overflow: auto
+
+ &:not(:last-child)
+ margin-bottom: 3.5rem
+ padding-bottom: 2rem
+
.o-block
margin-bottom: 4rem
@@ -142,6 +149,14 @@
.o-badge
border-radius: 1em
+.o-thumb
+ @include size(100px)
+ overflow: hidden
+ border-radius: 50%
+
+ &.o-thumb--small
+ @include size(35px)
+
//- SVG
diff --git a/website/assets/css/_base/_utilities.sass b/website/assets/css/_base/_utilities.sass
index 9b1c0cedc..10fe843a4 100644
--- a/website/assets/css/_base/_utilities.sass
+++ b/website/assets/css/_base/_utilities.sass
@@ -103,6 +103,9 @@
&:hover
color: $color-theme-dark
+.u-hand
+ cursor: pointer
+
.u-hide-link.u-hide-link
border: none
color: inherit
@@ -224,6 +227,7 @@
$spinner-size: 75px
$spinner-bar: 8px
+ min-height: $spinner-size * 2
position: relative
& > *
@@ -245,10 +249,19 @@
//- Hidden elements
-.u-hidden
- display: none
+.u-hidden,
+[v-cloak]
+ display: none !important
@each $breakpoint in (xs, sm, md)
.u-hidden-#{$breakpoint}.u-hidden-#{$breakpoint}
@include breakpoint(max, $breakpoint)
display: none
+
+//- Transitions
+
+.u-fade-enter-active
+ transition: opacity 0.5s
+
+.u-fade-enter
+ opacity: 0
diff --git a/website/assets/css/_components/_code.sass b/website/assets/css/_components/_code.sass
index 0fec230c0..0d0161ca6 100644
--- a/website/assets/css/_components/_code.sass
+++ b/website/assets/css/_components/_code.sass
@@ -2,7 +2,8 @@
//- Code block
-.c-code-block
+.c-code-block,
+.thebelab-cell
background: $color-front
color: darken($color-back, 20)
padding: 0.75em 0
@@ -13,11 +14,11 @@
white-space: pre
direction: ltr
- &.c-code-block--has-icon
- padding: 0
- display: flex
- border-top-left-radius: 0
- border-bottom-left-radius: 0
+.c-code-block--has-icon
+ padding: 0
+ display: flex
+ border-top-left-radius: 0
+ border-bottom-left-radius: 0
.c-code-block__icon
padding: 0 0 0 1rem
@@ -28,26 +29,66 @@
&.c-code-block__icon--border
border-left: 6px solid
-
-
//- Code block content
-.c-code-block__content
+.c-code-block__content,
+.thebelab-input,
+.jp-OutputArea
display: block
font: normal normal 1.1rem/#{1.9} $font-code
padding: 1em 2em
- &[data-prompt]:before,
- content: attr(data-prompt)
- margin-right: 0.65em
- display: inline-block
- vertical-align: middle
- opacity: 0.5
+.c-code-block__content[data-prompt]:before,
+ content: attr(data-prompt)
+ margin-right: 0.65em
+ display: inline-block
+ vertical-align: middle
+ opacity: 0.5
+//- Thebelab
+
+[data-executable]
+ margin-bottom: 0
+
+.thebelab-input.thebelab-input
+ padding: 3em 2em 1em
+
+.jp-OutputArea
+ &:not(:empty)
+ padding: 2rem 2rem 1rem
+ border-top: 1px solid $color-dark
+ margin-top: 2rem
+
+ .entities, svg
+ white-space: initial
+ font-family: inherit
+
+ .entities
+ font-size: 1.35rem
+
+.jp-OutputArea pre
+ font: inherit
+
+.jp-OutputPrompt.jp-OutputArea-prompt
+ padding-top: 0.5em
+ margin-right: 1rem
+ font-family: inherit
+ font-weight: bold
+
+.thebelab-run-button
+ @extend .u-text-label, .u-text-label--dark
+
+.thebelab-wrapper
+ position: relative
+
+.thebelab-wrapper__text
+ @include position(absolute, top, right, 1.25rem, 1.25rem)
+ color: $color-subtle-dark
+ z-index: 10
//- Code
-code
+code, .CodeMirror, .jp-RenderedText, .jp-OutputArea
-webkit-font-smoothing: subpixel-antialiased
-moz-osx-font-smoothing: auto
@@ -73,7 +114,7 @@ code
text-shadow: none
-//- Syntax Highlighting
+//- Syntax Highlighting (Prism)
[class*="language-"] .token
&.comment, &.prolog, &.doctype, &.cdata, &.punctuation
@@ -103,3 +144,50 @@ code
&.italic
font-style: italic
+
+//- Syntax Highlighting (CodeMirror)
+
+.CodeMirror.cm-s-default
+ background: $color-front
+ color: darken($color-back, 20)
+
+ .CodeMirror-selected
+ background: $color-theme
+ color: $color-back
+
+ .CodeMirror-cursor
+ border-left-color: currentColor
+
+ .cm-variable-2
+ color: inherit
+ font-style: italic
+
+ .cm-comment
+ color: map-get($syntax-highlighting, comment)
+
+ .cm-keyword, .cm-builtin
+ color: map-get($syntax-highlighting, keyword)
+
+ .cm-operator
+ color: map-get($syntax-highlighting, operator)
+
+ .cm-string
+ color: map-get($syntax-highlighting, selector)
+
+ .cm-number
+ color: map-get($syntax-highlighting, number)
+
+ .cm-def
+ color: map-get($syntax-highlighting, function)
+
+//- Syntax highlighting (Jupyter)
+
+.jp-RenderedText pre
+ .ansi-cyan-fg
+ color: map-get($syntax-highlighting, function)
+
+ .ansi-green-fg
+ color: $color-green
+
+ .ansi-red-fg
+ color: map-get($syntax-highlighting, operator)
diff --git a/website/assets/css/_components/_misc.sass b/website/assets/css/_components/_misc.sass
index c09fdf79a..0abbb6ae9 100644
--- a/website/assets/css/_components/_misc.sass
+++ b/website/assets/css/_components/_misc.sass
@@ -8,6 +8,12 @@
width: 100%
position: relative
+ &.x-terminal--small
+ background: $color-dark
+ color: $color-subtle
+ border-radius: 4px
+ margin-bottom: 4rem
+
.x-terminal__icons
position: absolute
padding: 10px
@@ -32,6 +38,13 @@
content: ""
background: $color-yellow
+ &.x-terminal__icons--small
+ &:before,
+ &:after,
+ span
+ @include size(10px)
+
+
.x-terminal__code
margin: 0
border: none
diff --git a/website/assets/css/_components/_navigation.sass b/website/assets/css/_components/_navigation.sass
index 2f1cfb6e3..eaeb33957 100644
--- a/website/assets/css/_components/_navigation.sass
+++ b/website/assets/css/_components/_navigation.sass
@@ -9,7 +9,7 @@
display: flex
justify-content: space-between
flex-flow: row nowrap
- padding: 0 2rem 0 1rem
+ padding: 0 0 0 1rem
z-index: 30
width: 100%
box-shadow: $box-shadow
@@ -21,11 +21,20 @@
.c-nav__menu
@include size(100%)
display: flex
- justify-content: flex-end
flex-flow: row nowrap
border-color: inherit
flex: 1
+
+ @include breakpoint(max, sm)
+ @include scroll-shadow-base($color-front)
+ overflow-x: auto
+ overflow-y: hidden
+ -webkit-overflow-scrolling: touch
+
+ @include breakpoint(min, md)
+ justify-content: flex-end
+
.c-nav__menu__item
display: flex
align-items: center
@@ -39,6 +48,14 @@
&:not(:first-child)
margin-left: 2em
+ &:last-child
+ @include scroll-shadow-cover(right, $color-back)
+ padding-right: 2rem
+
+ &:first-child
+ @include scroll-shadow-cover(left, $color-back)
+ padding-left: 2rem
+
&.is-active
color: $color-dark
pointer-events: none
diff --git a/website/assets/css/_variables.sass b/website/assets/css/_variables.sass
index fbceb5a6f..bac6c4f69 100644
--- a/website/assets/css/_variables.sass
+++ b/website/assets/css/_variables.sass
@@ -26,7 +26,7 @@ $font-code: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace
// Colors
-$colors: ( blue: #09a3d5, green: #05b083 )
+$colors: ( blue: #09a3d5, green: #05b083, purple: #6542d1 )
$color-back: #fff !default
$color-front: #1a1e23 !default
diff --git a/website/assets/css/style_purple.sass b/website/assets/css/style_purple.sass
new file mode 100644
index 000000000..f00573cc7
--- /dev/null
+++ b/website/assets/css/style_purple.sass
@@ -0,0 +1,4 @@
+//- 💫 STYLESHEET (PURPLE)
+
+$theme: purple
+@import style
diff --git a/website/assets/img/pattern_purple.jpg b/website/assets/img/pattern_purple.jpg
new file mode 100644
index 000000000..1bc5686de
Binary files /dev/null and b/website/assets/img/pattern_purple.jpg differ
diff --git a/website/assets/img/social/preview_api.jpg b/website/assets/img/social/preview_api.jpg
new file mode 100644
index 000000000..d707abd1b
Binary files /dev/null and b/website/assets/img/social/preview_api.jpg differ
diff --git a/website/assets/img/social/preview_universe.jpg b/website/assets/img/social/preview_universe.jpg
new file mode 100644
index 000000000..960b8b29a
Binary files /dev/null and b/website/assets/img/social/preview_universe.jpg differ
diff --git a/website/assets/js/accordion.js b/website/assets/js/accordion.js
deleted file mode 100644
index 7293f95b8..000000000
--- a/website/assets/js/accordion.js
+++ /dev/null
@@ -1,25 +0,0 @@
-'use strict';
-
-import { $$ } from './util.js';
-
-export default class Accordion {
- /**
- * Simple, collapsible accordion sections.
- * Inspired by: https://inclusive-components.design/collapsible-sections/
- * @param {string} selector - Query selector of button element.
- */
- constructor(selector) {
- [...$$(selector)].forEach(btn =>
- btn.addEventListener('click', this.onClick.bind(this)))
- }
-
- /**
- * Toggle aria-expanded attribute on button and visibility of section.
- * @param {node} Event.target - The accordion button.
- */
- onClick({ target }) {
- const exp = target.getAttribute('aria-expanded') === 'true' || false;
- target.setAttribute('aria-expanded', !exp);
- target.parentElement.nextElementSibling.hidden = exp;
- }
-}
diff --git a/website/assets/js/changelog.js b/website/assets/js/changelog.js
deleted file mode 100644
index 94f2149ad..000000000
--- a/website/assets/js/changelog.js
+++ /dev/null
@@ -1,72 +0,0 @@
-'use strict';
-
-import { Templater, handleResponse } from './util.js';
-
-export default class Changelog {
- /**
- * Fetch and render changelog from GitHub. Clones a template node (table row)
- * to avoid doubling templating markup in JavaScript.
- * @param {string} user - GitHub username.
- * @param {string} repo - Repository to fetch releases from.
- */
- constructor(user, repo) {
- this.url = `https://api.github.com/repos/${user}/${repo}/releases`;
- this.template = new Templater('changelog');
- this.fetchChangelog()
- .then(json => this.render(json))
- .catch(this.showError.bind(this));
- // make sure scroll positions for progress bar etc. are recalculated
- window.dispatchEvent(new Event('resize'));
- }
-
- fetchChangelog() {
- return new Promise((resolve, reject) =>
- fetch(this.url)
- .then(res => handleResponse(res))
- .then(json => json.ok ? resolve(json) : reject()))
- }
-
- showError() {
- this.template.get('error').style.display = 'block';
- }
-
- /**
- * Get template section from template row. Hacky, but does make sense.
- * @param {node} item - Parent element.
- * @param {string} id - ID of child element, set via data-changelog.
- */
- getField(item, id) {
- return item.querySelector(`[data-changelog="${id}"]`);
- }
-
- render(json) {
- this.template.get('table').style.display = 'block';
- this.row = this.template.get('item');
- this.releases = this.template.get('releases');
- this.prereleases = this.template.get('prereleases');
- Object.values(json)
- .filter(release => release.name)
- .forEach(release => this.renderRelease(release));
- this.row.remove();
- }
-
- /**
- * Clone the template row and populate with content from API response.
- * https://developer.github.com/v3/repos/releases/#list-releases-for-a-repository
- * @param {string} name - Release title.
- * @param {string} tag (tag_name) - Release tag.
- * @param {string} url (html_url) - URL to the release page on GitHub.
- * @param {string} date (published_at) - Timestamp of release publication.
- * @param {boolean} prerelease - Whether the release is a prerelease.
- */
- renderRelease({ name, tag_name: tag, html_url: url, published_at: date, prerelease }) {
- const container = prerelease ? this.prereleases : this.releases;
- const tagLink = `${tag}
`;
- const title = (name.split(': ').length == 2) ? name.split(': ')[1] : name;
- const row = this.row.cloneNode(true);
- this.getField(row, 'date').textContent = date.split('T')[0];
- this.getField(row, 'tag').innerHTML = tagLink;
- this.getField(row, 'title').textContent = title;
- container.appendChild(row);
- }
-}
diff --git a/website/assets/js/changelog.vue.js b/website/assets/js/changelog.vue.js
new file mode 100644
index 000000000..a68042d3e
--- /dev/null
+++ b/website/assets/js/changelog.vue.js
@@ -0,0 +1,40 @@
+/**
+ * Initialise changelog table for releases and prereleases
+ * @param {string} selector - The element selector to initialise the app.
+ * @param {string} repo - Repository to load from, in the format user/repo.
+ */
+export default function(selector, repo) {
+ new Vue({
+ el: selector,
+ data: {
+ url: `https://api.github.com/repos/${repo}/releases`,
+ releases: [],
+ prereleases: [],
+ error: false
+ },
+ beforeMount() {
+ fetch(this.url)
+ .then(res => res.json())
+ .then(json => this.$_update(json))
+ .catch(err => { this.error = true });
+ },
+ updated() {
+ window.dispatchEvent(new Event('resize')); // scroll position for progress
+ },
+ methods: {
+ $_update(json) {
+ const allReleases = Object.values(json)
+ .filter(release => release.name)
+ .map(release => ({
+ title: (release.name.split(': ').length == 2) ? release.name.split(': ')[1] : release.name,
+ url: release.html_url,
+ date: release.published_at.split('T')[0],
+ tag: release.tag_name,
+ pre: release.prerelease
+ }));
+ this.releases = allReleases.filter(release => !release.pre);
+ this.prereleases = allReleases.filter(release => release.pre);
+ }
+ }
+ });
+}
diff --git a/website/assets/js/github-embed.js b/website/assets/js/github-embed.js
deleted file mode 100644
index ec72fd713..000000000
--- a/website/assets/js/github-embed.js
+++ /dev/null
@@ -1,42 +0,0 @@
-'use strict';
-
-import { $$ } from './util.js';
-
-export default class GitHubEmbed {
- /**
- * Embed code from GitHub repositories, similar to Gist embeds. Fetches the
- * raw text and places it inside element.
- * Usage:
- * @param {string} user - GitHub user or organization. - * @param {string} attr - Data attribute used to select containers. Attribute - * value should be path to file relative to user. - */ - constructor(user, attr) { - this.url = `https://raw.githubusercontent.com/${user}`; - this.attr = attr; - [...$$(`[${this.attr}]`)].forEach(el => this.embed(el)); - } - - /** - * Fetch code from GitHub and insert it as element content. File path is - * read off the container's data attribute. - * @param {node} el - The element. - */ - embed(el) { - el.parentElement.setAttribute('data-loading', ''); - fetch(`${this.url}/${el.getAttribute(this.attr)}`) - .then(res => res.text().then(text => ({ text, ok: res.ok }))) - .then(({ text, ok }) => ok ? this.render(el, text) : false) - el.parentElement.removeAttribute('data-loading'); - } - - /** - * Add text to container and apply syntax highlighting via Prism, if available. - * @param {node} el - The element. - * @param {string} text - The raw code, fetched from GitHub. - */ - render(el, text) { - el.textContent = text; - if (window.Prism) Prism.highlightElement(el); - } -} diff --git a/website/assets/js/main.js b/website/assets/js/main.js new file mode 100644 index 000000000..f52dbb9ce --- /dev/null +++ b/website/assets/js/main.js @@ -0,0 +1,148 @@ +/** + * Initialise changelog + */ +import initChangelog from './changelog.vue.js'; + +{ + const selector = '[data-vue="changelog"]'; + if (window.Vue && document.querySelector(selector)) { + initChangelog(selector, 'explosion/spacy'); + } +} + +/** + * Initialise models + */ +import initModels from './models.vue.js'; + +{ + if (window.Vue && document.querySelector('[data-model]')) { + initModels('explosion/spacy-models') + } +} + +/** + * Initialise Universe + */ +import initUniverse from './universe.vue.js'; + +{ + const selector = '[data-vue="universe"]'; + if (window.Vue && document.querySelector(selector)) { + initUniverse(selector, '/universe/universe.json'); + } +} + +/** + * Initialise Quickstart + */ +if (document.querySelector('#qs') && window.Quickstart) { + new Quickstart('#qs'); +} + +/** + * Thebelabs + */ +if (window.thebelab) { + window.thebelab.on('status', (ev, data) => { + if (data.status == 'failed') { + const msg = "Failed to connect to kernel :( This can happen if too many users are active at the same time. Please reload the page and try again!"; + const wrapper = `${msg}`; + document.querySelector('.jp-OutputArea-output pre').innerHTML = wrapper; + } + }); +} + +/** + * Highlight section in viewport in sidebar, using in-view library + */ +{ + const sectionAttr = 'data-section'; + const navAttr = 'data-nav'; + const activeClass = 'is-active'; + const sections = [...document.querySelectorAll(`[${navAttr}]`)]; + if (window.inView) { + if (sections.length) { // highlight first item regardless + sections[0].classList.add(activeClass); + } + inView(`[${sectionAttr}]`).on('enter', section => { + const id = section.getAttribute(sectionAttr); + const el = document.querySelector(`[${navAttr}="${id}"]`); + if (el) { + sections.forEach(el => el.classList.remove(activeClass)); + el.classList.add(activeClass); + } + }); + } +} + +/** + * Simple, collapsible accordion sections. + * Inspired by: https://inclusive-components.design/collapsible-sections/ + */ +{ + const elements = [...document.querySelectorAll('.js-accordion')]; + elements.forEach(el => el.addEventListener('click', ({ target }) => { + const exp = target.getAttribute('aria-expanded') === 'true' || false; + target.setAttribute('aria-expanded', !exp); + target.parentElement.nextElementSibling.hidden = exp; + })); +} + +/** + * Reading indicator as progress bar + * @param {string} selector - Selector of