diff --git a/chapters/en/chapter1.md b/chapters/en/chapter1.md index af2e46ea5..fe11a1386 100644 --- a/chapters/en/chapter1.md +++ b/chapters/en/chapter1.md @@ -10,9 +10,9 @@ type: chapter id: 1 --- - + - + @@ -104,9 +104,9 @@ To get the token at a certain index, you can index into the `doc`. For example, - + - + @@ -226,9 +226,9 @@ a look at an example. - + - + diff --git a/chapters/en/chapter2.md b/chapters/en/chapter2.md index dc6f3321c..618a046b7 100644 --- a/chapters/en/chapter2.md +++ b/chapters/en/chapter2.md @@ -11,9 +11,9 @@ type: chapter id: 2 --- - + - + @@ -96,9 +96,9 @@ the vocab. - + - + @@ -249,9 +249,9 @@ The `.pos_` attribute returns the coarse-grained part-of-speech tag and - + - + @@ -312,9 +312,9 @@ current object to. - + - + diff --git a/chapters/en/chapter3.md b/chapters/en/chapter3.md index 42e7a3a4f..28c2faa80 100644 --- a/chapters/en/chapter3.md +++ b/chapters/en/chapter3.md @@ -12,9 +12,9 @@ type: chapter id: 3 --- - + - + @@ -79,9 +79,9 @@ full pipeline consisting of `(name, component)` tuples is available as - + - + @@ -198,9 +198,9 @@ created as the variable `matcher`. - + - + @@ -331,9 +331,9 @@ variable `CAPITALS`. - + - + diff --git a/chapters/en/chapter4.md b/chapters/en/chapter4.md index 4ade82f83..777a4a88a 100644 --- a/chapters/en/chapter4.md +++ b/chapters/en/chapter4.md @@ -12,9 +12,9 @@ type: chapter id: 4 --- - + - + @@ -102,9 +102,9 @@ a set of training examples. A list of sentences is available as the variable - + - + @@ -220,9 +220,9 @@ number of total correct entities the model _should_ have predicted. - + - + @@ -373,9 +373,9 @@ the problem here. - + - + diff --git a/locale.json b/locale.json index af87235ce..cce172efa 100644 --- a/locale.json +++ b/locale.json @@ -5,6 +5,7 @@ "slogan": "A free online course", "description": "spaCy is a modern Python library for industrial-strength Natural Language Processing. In this free and interactive online course, you'll learn how to use spaCy to build advanced natural language understanding systems, using both rule-based and machine learning approaches.", "bio": "I'm Ines, one of the core developers of spaCy and the co-founder of Explosion. I specialize in modern developer tools for AI, Machine Learning and NLP. I also really love building stuff for the web.", + "video": "THduWAnG97k", "footerLinks": [ { "text": "spaCy Website", @@ -40,7 +41,10 @@ "launchingDocker": "Launching Docker container on", "reconnectingDocker": "Reconnecting to Docker container on", "prevChapter": "Previous Chapter", - "nextChapter": "Next Chapter" + "nextChapter": "Next Chapter", + "start": "Start", + "video": "Video", + "slides": "Slides" } }, "de": { @@ -84,7 +88,10 @@ "launchingDocker": "Starte Docker-Container auf", "reconnectingDocker": "Verbinde mit Docker-Container auf", "prevChapter": "Vorheriges Kapitel", - "nextChapter": "Nächstes Kapitel" + "nextChapter": "Nächstes Kapitel", + "start": "Start", + "video": "Video", + "slides": "Präsentation" } }, "es": { diff --git a/package-lock.json b/package-lock.json index 6c3893c3a..2ee5e7d9c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4113,6 +4113,11 @@ "array-find-index": "^1.0.1" } }, + "custom-event-polyfill": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/custom-event-polyfill/-/custom-event-polyfill-1.0.7.tgz", + "integrity": "sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w==" + }, "cwebp-bin": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cwebp-bin/-/cwebp-bin-5.0.0.tgz", @@ -9391,6 +9396,11 @@ } } }, + "loadjs": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/loadjs/-/loadjs-4.2.0.tgz", + "integrity": "sha512-AgQGZisAlTPbTEzrHPb6q+NYBMD+DP9uvGSIjSUM5uG+0jG15cb8axWpxuOIqrmQjn6scaaH8JwloiP27b2KXA==" + }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", @@ -11200,6 +11210,25 @@ } } }, + "plyr": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/plyr/-/plyr-3.6.2.tgz", + "integrity": "sha512-CjAhRDtzyGqMRte9Phj4FsZFegS9VxW60boOhQsAnZHuiFG3yVBRcodWsGZ79GuXHHelc4DxMHO+z0QggY+9qQ==", + "requires": { + "core-js": "^3.6.5", + "custom-event-polyfill": "^1.0.7", + "loadjs": "^4.2.0", + "rangetouch": "^2.0.1", + "url-polyfill": "^1.1.8" + }, + "dependencies": { + "core-js": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", + "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==" + } + } + }, "pngjs": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", @@ -12120,6 +12149,11 @@ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" }, + "rangetouch": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/rangetouch/-/rangetouch-2.0.1.tgz", + "integrity": "sha512-sln+pNSc8NGaHoLzwNBssFSf/rSYkqeBXzX1AtJlkJiUaVSJSbRAWJk+4omsXkN+EJalzkZhWQ3th1m0FpR5xA==" + }, "raw-body": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", @@ -15316,6 +15350,11 @@ "prepend-http": "^1.0.1" } }, + "url-polyfill": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/url-polyfill/-/url-polyfill-1.1.8.tgz", + "integrity": "sha512-Ey61F4FEqhcu1vHSOMmjl0Vd/RPRLEjMj402qszD/dhMBrVfoUsnIj8KSZo2yj+eIlxJGKFdnm6ES+7UzMgZ3Q==" + }, "url-regex": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/url-regex/-/url-regex-3.2.0.tgz", diff --git a/package.json b/package.json index 22372c6fa..97c1af959 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "gatsby-transformer-sharp": "^2.1.17", "juniper-js": "^0.1.0", "node-sass": "^4.11.0", + "plyr": "^3.6.2", "prismjs": "^1.15.0", "react": "^16.8.2", "react-dom": "^16.8.2", diff --git a/src/components/button.js b/src/components/button.js index 441f131bb..10c308474 100644 --- a/src/components/button.js +++ b/src/components/button.js @@ -1,7 +1,7 @@ import React, { useContext } from 'react' import classNames from 'classnames' -import { UiTextContext } from '../context' +import { LocaleContext } from '../context' import IconCheck from '../../static/icon_check.svg' import classes from '../styles/button.module.sass' @@ -19,7 +19,7 @@ export const Button = ({ Component = 'button', children, onClick, variant, small } export const CompleteButton = ({ completed, toggleComplete, small = true }) => { - const uiText = useContext(UiTextContext) + const { uiText } = useContext(LocaleContext) const buttonClassNames = classNames({ [classes.completeInactive]: !completed, [classes.completeActive]: completed, diff --git a/src/components/choice.js b/src/components/choice.js index 4be943db6..de06a860c 100644 --- a/src/components/choice.js +++ b/src/components/choice.js @@ -2,11 +2,11 @@ import React, { useState, useCallback, useContext } from 'react' import classNames from 'classnames' import { Button } from './button' -import { UiTextContext } from '../context' +import { LocaleContext } from '../context' import classes from '../styles/choice.module.sass' const Choice = ({ id = '0', children = [] }) => { - const uiText = useContext(UiTextContext) + const { uiText } = useContext(LocaleContext) const [selected, setSelected] = useState(null) const [answer, setAnswer] = useState(null) const handleAnswer = useCallback(() => setAnswer(selected), [selected]) diff --git a/src/components/code.js b/src/components/code.js index b0808c78a..35af28107 100644 --- a/src/components/code.js +++ b/src/components/code.js @@ -3,7 +3,7 @@ import { StaticQuery, graphql } from 'gatsby' import { Hint } from './hint' import { Button } from './button' -import { ChapterContext, UiTextContext } from '../context' +import { ChapterContext, LocaleContext } from '../context' import classes from '../styles/code.module.sass' function getFiles({ allCode }, lang) { @@ -109,8 +109,8 @@ class CodeBlock extends React.Component { const solutionFile = files[solutionId] const testFile = files[testId] return ( - - {uiText => ( + + {({ uiText }) => (
{Juniper && (
)} -
+ ) }} /> diff --git a/src/components/exercise.js b/src/components/exercise.js index d4f42bc20..239023930 100644 --- a/src/components/exercise.js +++ b/src/components/exercise.js @@ -2,14 +2,16 @@ import React, { useRef, useCallback, useContext, useEffect } from 'react' import classNames from 'classnames' import { Button, CompleteButton } from './button' -import { ChapterContext, UiTextContext } from '../context' +import { ChapterContext, LocaleContext } from '../context' import IconSlides from '../../static/icon_slides.svg' +import IconVideo from '../../static/icon_video.svg' import classes from '../styles/exercise.module.sass' const Exercise = ({ id, title, type, children }) => { - const uiText = useContext(UiTextContext) + const { uiText } = useContext(LocaleContext) const excRef = useRef() const excId = parseInt(id) + const types = type ? type.split(',').map(t => t.trim()) : [] const { activeExc, setActiveExc, completed, setCompleted } = useContext(ChapterContext) const isExpanded = activeExc === excId const isCompleted = completed.includes(excId) @@ -31,7 +33,7 @@ const Exercise = ({ id, title, type, children }) => { }, [isCompleted, completed, excId]) const rootClassNames = classNames(classes.root, { [classes.expanded]: isExpanded, - [classes.wide]: isExpanded && type === 'slides', + [classes.wide]: isExpanded && types.includes('slides'), [classes.completed]: !isExpanded && isCompleted, }) const titleClassNames = classNames(classes.title, { @@ -48,7 +50,12 @@ const Exercise = ({ id, title, type, children }) => { {title} - {type === 'slides' && } + {types.includes('slides') && ( + + )} + {types.includes('video') && ( + + )} {isExpanded && (
diff --git a/src/components/hint.js b/src/components/hint.js index 2ee490675..cf4564b31 100644 --- a/src/components/hint.js +++ b/src/components/hint.js @@ -1,10 +1,10 @@ import React, { useState, useCallback, useContext } from 'react' -import { UiTextContext } from '../context' +import { LocaleContext } from '../context' import classes from '../styles/hint.module.sass' export const Hint = ({ expanded = false, actions = [], children }) => { - const uiText = useContext(UiTextContext) + const { uiText } = useContext(LocaleContext) const [isExpanded, setIsExpanded] = useState(expanded) const handleExpand = useCallback(() => setIsExpanded(!isExpanded), [isExpanded]) return ( diff --git a/src/components/layout.js b/src/components/layout.js index 99b34d366..ec9af5e9a 100644 --- a/src/components/layout.js +++ b/src/components/layout.js @@ -5,7 +5,7 @@ import SEO from './seo' import { Link } from './link' import { H3 } from './typography' import { Logo } from './logo' -import { UiTextContext } from '../context' +import { LocaleContext } from '../context' import '../styles/index.sass' import classes from '../styles/layout.module.sass' @@ -26,7 +26,7 @@ const Layout = ({ isHome, title, description, lang, pageName, children }) => { return ( <> - +
{langs.length > 1 && ( setSlideType(value)} + /> + {uiText[value]} + + ) + })} + + {slideType === 'video' ? ( +