diff --git a/.babelrc b/.babelrc
deleted file mode 100644
index 279d3f105a..0000000000
--- a/.babelrc
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "presets": ["next/babel"],
- "plugins": ["transform-define", "transform-object-assign"]
-}
diff --git a/.gitignore b/.gitignore
index d0ba1dbc90..1fd10aa23e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -56,8 +56,11 @@ typings/
# Next.js build output
.idea
-.next/
*.log
# Mac finder artifacts
.DS_Store
+
+# Gatsby cache
+.cache
+public
diff --git a/.restyled.yaml b/.restyled.yaml
index 8a958a9d83..dc85f8a683 100644
--- a/.restyled.yaml
+++ b/.restyled.yaml
@@ -4,5 +4,5 @@ restylers:
include:
- './*.{js,md}'
- 'pages/**/*.js'
- - 'public/static/docs/**/*.{js,md}'
+ - 'content/docs/**/*.{js,md}'
- 'src/**/*.js'
diff --git a/README.md b/README.md
index dbbf0bf0b7..d71a000618 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-![owl logo](https://dvc.org/static/img/logo-github-readme.png)
+![owl logo](https://dvc.org/img/logo-github-readme.png)
[![Maintainability](https://api.codeclimate.com/v1/badges/5872e0a572ec8b74bd8d/maintainability)](https://codeclimate.com/github/iterative/dvc.org/maintainability)
[![CircleCI](https://circleci.com/gh/iterative/dvc.org.svg?style=svg)](https://circleci.com/gh/iterative/dvc.org)
diff --git a/config/prismjs/dvc-commands.js b/config/prismjs/dvc-commands.js
new file mode 100644
index 0000000000..145e33d3f2
--- /dev/null
+++ b/config/prismjs/dvc-commands.js
@@ -0,0 +1,52 @@
+/* eslint-env node */
+
+module.exports = [
+ 'version',
+ 'update',
+ 'unprotect',
+ 'unlock',
+ 'tag',
+ 'status',
+ 'run',
+ 'root',
+ 'repro',
+ 'remove',
+ 'remote remove',
+ 'remote modify',
+ 'remote list',
+ 'remote default',
+ 'remote add',
+ 'remote',
+ 'push',
+ 'pull',
+ 'pkg',
+ 'pipeline show',
+ 'pipeline list',
+ 'pipeline',
+ 'move',
+ 'metrics show',
+ 'metrics remove',
+ 'metrics modify',
+ 'metrics diff',
+ 'metrics add',
+ 'metrics',
+ 'lock',
+ 'list',
+ 'install',
+ 'init',
+ 'import-url',
+ 'import',
+ 'help',
+ 'get-url',
+ 'get',
+ 'gc',
+ 'fetch',
+ 'diff',
+ 'destroy',
+ 'config',
+ 'commit',
+ 'checkout',
+ 'cache dir',
+ 'cache',
+ 'add'
+]
diff --git a/config/prismjs/dvc-hook.js b/config/prismjs/dvc-hook.js
new file mode 100644
index 0000000000..89caa435c0
--- /dev/null
+++ b/config/prismjs/dvc-hook.js
@@ -0,0 +1,18 @@
+/* eslint-env node */
+
+const Prism = require('prismjs')
+
+// Make sure the $ part of the command prompt in shell
+// examples isn't copiable by making it an 'input' token.
+Prism.hooks.add('after-tokenize', env => {
+ if (env.language !== 'dvc') {
+ return
+ }
+
+ for (const token of env.tokens) {
+ if (token.type === 'line' && /^\$\s+$/.test(token.content[0])) {
+ const old = token.content[0]
+ token.content[0] = new Prism.Token('input', old, null, old, false)
+ }
+ }
+})
diff --git a/config/prismjs/dvc.js b/config/prismjs/dvc.js
new file mode 100644
index 0000000000..7d09682506
--- /dev/null
+++ b/config/prismjs/dvc.js
@@ -0,0 +1,66 @@
+/* eslint-env node */
+
+// we require prism and load its bash module so we have
+// Prism.languages.bash to embed into our DVC language.
+
+const Prism = require('prismjs')
+require('prismjs/components/prism-bash')
+require('./dvc-hook')
+const { bash } = Prism.languages
+
+const dvc = require('./dvc-commands')
+
+// Command arrays are intentionally reverse sorted
+// to prevent shorter matches before longer ones
+
+const git = [
+ 'tag',
+ 'status',
+ 'remote update',
+ 'remote rename',
+ 'remote remove',
+ 'remote add',
+ 'remote',
+ 'push',
+ 'pull',
+ 'merge',
+ 'init',
+ 'fetch',
+ 'commit',
+ 'clone',
+ 'checkout',
+ 'add'
+]
+
+const beforeCommand = String.raw`(\$[\s(]+|;\s*)`
+
+/* tslint:disable object-literal-sort-keys */
+
+Prism.languages.dvc = {
+ line: {
+ pattern: /(?<=(^|\n))\$[\s\S]*?[^\\](:?\n|$)/,
+ inside: {
+ dvc: {
+ pattern: new RegExp(
+ String.raw`${beforeCommand}\b(?:dvc (?:${dvc.join('|')}))\b`
+ ),
+ greedy: true,
+ lookbehind: true
+ },
+ git: {
+ pattern: new RegExp(
+ String.raw`${beforeCommand}\b(?:git (?:${git.join('|')}))\b`
+ ),
+ greedy: true,
+ lookbehind: true
+ },
+ command: {
+ pattern: new RegExp(String.raw`${beforeCommand}\b[a-zA-Z0-9\-_]+\b`),
+ greedy: true,
+ lookbehind: true
+ },
+ ...bash
+ }
+ },
+ comment: bash.comment
+}
diff --git a/config/prismjs/usage.js b/config/prismjs/usage.js
new file mode 100644
index 0000000000..8b1c9493f5
--- /dev/null
+++ b/config/prismjs/usage.js
@@ -0,0 +1,13 @@
+/* eslint-env node */
+
+const dvc = require('./dvc-commands')
+const Prism = require('prismjs')
+
+Prism.languages.usage = {
+ dvc: {
+ pattern: new RegExp(`dvc (?:${dvc.join('|')})`)
+ },
+ usage: {
+ pattern: /(^|\n)\s*(usage|positional arguments|optional arguments)/
+ }
+}
diff --git a/content/docs/api-reference/get_url.md b/content/docs/api-reference/get_url.md
new file mode 100644
index 0000000000..9a83e33a09
--- /dev/null
+++ b/content/docs/api-reference/get_url.md
@@ -0,0 +1,110 @@
+# dvc.api.get_url()
+
+Returns the URL to the storage location of a data file or directory tracked in a
+DVC project.
+
+```py
+def get_url(path: str,
+ repo: str = None,
+ rev: str = None,
+ remote: str = None) -> str
+```
+
+#### Usage:
+
+```py
+import dvc.api
+
+resource_url = dvc.api.get_url(
+ 'get-started/data.xml',
+ repo='https://github.com/iterative/dataset-registry')
+
+# resource_url is now "https://remote.dvc.org/dataset-registry/a3/04afb96060aad90176268345e10355"
+```
+
+## Description
+
+Returns the URL string of the storage location (in a
+[DVC remote](/doc/command-reference/remote)) where a target file or directory,
+specified by its `path` in a `repo` (DVC project), is stored.
+
+The URL is formed by reading the project's
+[remote configuration](/doc/command-reference/config#remote) and the
+[DVC-file](/doc/user-guide/dvc-file-format) where the given `path` is an
+output. The URL schema returned depends on the
+[type](/doc/command-reference/remote/add#supported-storage-types) of the
+`remote` used (see the [Parameters](#parameters) section).
+
+If the target is a directory, the returned URL will end in `.dir`. Refer to
+[Structure of cache directory](/doc/user-guide/dvc-files-and-directories#structure-of-cache-directory)
+and `dvc add` to learn more about how DVC handles data directories.
+
+β οΈ This function does not check for the actual existence of the file or
+directory in the remote storage.
+
+π‘ Having the resource's URL, it should be possible to download it directly with
+an appropriate library, such as
+[`boto3`](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Object.download_fileobj)
+or
+[`paramiko`](https://docs.paramiko.org/en/stable/api/sftp.html#paramiko.sftp_client.SFTPClient.get).
+
+## Parameters
+
+- **`path`** - location and file name of the file or directory in `repo`,
+ relative to the project's root.
+
+- `repo` - specifies the location of the DVC project. It can be a URL or a file
+ system path. Both HTTP and SSH protocols are supported for online Git repos
+ (e.g. `[user@]server:project.git`). _Default_: The current project is used
+ (the current working directory tree is walked up to find it).
+
+- `rev` - Git commit (any [revision](https://git-scm.com/docs/revisions) such as
+ a branch or tag name, or a commit hash). If `repo` is not a Git repo, this
+ option is ignored. _Default_: `HEAD`.
+
+- `remote` - name of the [DVC remote](/doc/command-reference/remote) to use to
+ form the returned URL string. _Default_: The
+ [default remote](/doc/command-reference/remote/default) of `repo` is used.
+
+## Exceptions
+
+- `dvc.api.UrlNotDvcRepoError` - `repo` is not a DVC project.
+
+- `dvc.exceptions.NoRemoteError` - no `remote` is found.
+
+## Example: Getting the URL to a DVC-tracked file
+
+```py
+import dvc.api
+
+resource_url = dvc.api.get_url(
+ 'get-started/data.xml',
+ repo='https://github.com/iterative/dataset-registry'
+ )
+
+print(resource_url)
+```
+
+The script above prints
+
+`https://remote.dvc.org/dataset-registry/a3/04afb96060aad90176268345e10355`
+
+This URL represents the location where the data is stored, and is built by
+reading the corresponding DVC-file
+([`get-started/data.xml.dvc`](https://github.com/iterative/dataset-registry/blob/master/get-started/data.xml.dvc))
+where the `md5` file hash is stored,
+
+```yaml
+outs:
+ - md5: a304afb96060aad90176268345e10355
+ path: get-started/data.xml
+```
+
+and the project configuration
+([`.dvc/config`](https://github.com/iterative/dataset-registry/blob/master/.dvc/config))
+where the remote URL is saved:
+
+```ini
+['remote "storage"']
+url = https://remote.dvc.org/dataset-registry
+```
diff --git a/content/docs/api-reference/index.md b/content/docs/api-reference/index.md
new file mode 100644
index 0000000000..0298b185ab
--- /dev/null
+++ b/content/docs/api-reference/index.md
@@ -0,0 +1,16 @@
+# Python API
+
+DVC can be used as a Python library, simply [install](/doc/install) with `pip`
+or `conda`. This reference provides the details about the functions in the API
+module `dvc.api`, which can be imported any regular way, for example:
+
+```py
+import dvc.api
+```
+
+The purpose of this API is to provide programatic access to the data or models
+[stored and versioned](/doc/use-cases/versioning-data-and-model-files) in
+DVC repositories from Python code.
+
+Please choose a function from the navigation sidebar to the left, or click the
+`Next` button below to jump into the first one β
diff --git a/content/docs/api-reference/open.md b/content/docs/api-reference/open.md
new file mode 100644
index 0000000000..858090e0fb
--- /dev/null
+++ b/content/docs/api-reference/open.md
@@ -0,0 +1,200 @@
+# dvc.api.open()
+
+Opens a tracked file.
+
+```py
+def open(path: str,
+ repo: str = None,
+ rev: str = None,
+ remote: str = None,
+ mode: str = "r",
+ encoding: str = None)
+```
+
+#### Usage:
+
+```py
+import dvc.api
+
+with dvc.api.open(
+ 'get-started/data.xml',
+ repo='https://github.com/iterative/dataset-registry'
+ ) as fd:
+ # ... fd is a file descriptor that can be processed normally.
+```
+
+## Description
+
+Open a data or model file tracked in a DVC project and generate a
+corresponding
+[file object](https://docs.python.org/3/glossary.html#term-file-object). The
+file can be tracked by DVC or by Git.
+
+> The exact type of file object depends on the `mode` used. For more details,
+> please refer to Python's
+> [`open()`](https://docs.python.org/3/library/functions.html#open) built-in,
+> which is used under the hood.
+
+`dvc.api.open()` may only be used as a
+[context manager](https://www.python.org/dev/peps/pep-0343/#context-managers-in-the-standard-library)
+(using the `with` keyword, as shown in the examples).
+
+This function makes a direct connection to the
+[remote storage](/doc/command-reference/remote/add#supported-storage-types)
+(except for Google Drive), so the file contents can be streamed. Your code can
+process the data [buffer](https://docs.python.org/3/c-api/buffer.html) as it's
+streamed, which optimizes memory usage.
+
+> Use `dvc.api.read()` to load the complete file contents in a single function
+> call β no _context manager_ involved. Neither function utilizes disc space.
+
+## Parameters
+
+- **`path`** - location and file name of the file in `repo`, relative to the
+ project's root.
+
+- `repo` - specifies the location of the DVC project. It can be a URL or a file
+ system path. Both HTTP and SSH protocols are supported for online Git repos
+ (e.g. `[user@]server:project.git`). _Default_: The current project is used
+ (the current working directory tree is walked up to find it).
+
+- `rev` - Git commit (any [revision](https://git-scm.com/docs/revisions) such as
+ a branch or tag name, or a commit hash). If `repo` is not a Git repo, this
+ option is ignored. _Default_: `HEAD`.
+
+- `remote` - name of the [DVC remote](/doc/command-reference/remote) to look for
+ the target data. _Default_: The
+ [default remote](/doc/command-reference/remote/default) of `repo` is used if a
+ `remote` argument is not given. For local projects, the cache is
+ tied before the default remote.
+
+- `mode` - specifies the mode in which the file is opened. Defaults to `"r"`
+ (read). Mirrors the namesake parameter in builtin
+ [`open()`](https://docs.python.org/3/library/functions.html#open).
+
+- `encoding` -
+ [codec](https://docs.python.org/3/library/codecs.html#standard-encodings) used
+ to decode the file contents to a string. This should only be used in text
+ mode. Defaults to `"utf-8"`. Mirrors the namesake parameter in builtin
+ `open()`.
+
+## Exceptions
+
+- `dvc.exceptions.FileMissingError` - file in `path` is missing from `repo`.
+
+- `dvc.exceptions.PathMissingError` - `path` cannot be found in `repo`.
+
+- `dvc.api.UrlNotDvcRepoError` - `repo` is not a DVC project.
+
+- `dvc.exceptions.NoRemoteError` - no `remote` is found.
+
+## Example: Use data or models from DVC repositories
+
+Any data artifact hosted online can be processed directly in your
+Python code with this API. For example, an XML file tracked in a public DVC repo
+on Github can be processed like this:
+
+```py
+from xml.sax import parse
+import dvc.api
+from mymodule import mySAXHandler
+
+with dvc.api.open(
+ 'get-started/data.xml',
+ repo='https://github.com/iterative/dataset-registry'
+ ) as fd:
+ parse(fd, mySAXHandler)
+```
+
+Notice that we use a [SAX](http://www.saxproject.org/) XML parser here because
+`dvc.api.open()` is able to stream the data from
+[remote storage](/doc/command-reference/remote/add#supported-storage-types).
+(The `mySAXHandler` object should handle the event-driven parsing of the
+document in this case.) This increases the performance of the code (minimizing
+memory usage), and is typically faster than loading the whole data into memory.
+
+> If you just needed to load the complete file contents into memory, you can use
+> `dvc.api.read()` instead:
+>
+> ```py
+> from xml.dom.minidom import parse
+> import dvc.api
+>
+> xmldata = dvc.api.read('get-started/data.xml',
+> repo='https://github.com/iterative/dataset-registry')
+> xmldom = parse(xmldata)
+> ```
+
+## Example: Accessing private repos
+
+This is just a matter of using the right `repo` argument, for example an SSH URL
+(requires that the
+[credentials are configured](https://help.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh)
+locally):
+
+```py
+import dvc.api
+
+with dvc.api.open(
+ 'features.dat',
+ repo='git@server.com:path/to/repo.git'
+ ) as fd:
+ # ... Process 'features'
+```
+
+## Example: Use different versions of data
+
+The `rev` argument lets you specify any Git commit to look for an artifact. This
+way any previous version, or alternative experiment can be accessed
+programmatically. For example, let's say your DVC repo has tagged releases of a
+CSV dataset:
+
+```py
+import csv
+import dvc.api
+
+with dvc.api.open(
+ 'clean.csv',
+ rev='v1.1.0'
+ ) as fd:
+ reader = csv.reader(fd)
+ # ... Process 'clean' data from version 1.1.0
+```
+
+Also, notice that we didn't supply a `repo` argument in this example. DVC will
+attempt to find a DVC project to use in the current working
+directory tree, and look for the file contents of `clean.csv` in its local
+cache; no download will happen if found. See the
+[Parameters](#parameters) section for more info.
+
+## Example: Chose a specific remote as the data source
+
+Sometimes we may want to choose the [remote](/doc/command-reference/remote) data
+source, for example if the `repo` has no default remote set. This can be done by
+providing a `remote` argument:
+
+```py
+import dvc.api
+
+with open(
+ 'activity.log',
+ repo='location/of/dvc/project',
+ remote='my-s3-bucket'
+ ) as fd:
+ for line in fd:
+ match = re.search(r'user=(\w+)', line)
+ # ... Process users activity log
+```
+
+## Example: Specify the text encoding
+
+To chose which codec to open a text file with, send an `encoding` argument:
+
+```py
+import dvc.api
+
+with dvc.api.open(
+ 'data/nlp/words_ru.txt',
+ encoding='koi8_r') as fd:
+ # ... Process Russian words
+```
diff --git a/content/docs/api-reference/read.md b/content/docs/api-reference/read.md
new file mode 100644
index 0000000000..2083df3728
--- /dev/null
+++ b/content/docs/api-reference/read.md
@@ -0,0 +1,101 @@
+# dvc.api.read()
+
+Returns the contents of a tracked file.
+
+```py
+def open(path: str,
+ repo: str = None,
+ rev: str = None,
+ remote: str = None,
+ mode: str = "r",
+ encoding: str = None)
+```
+
+#### Usage:
+
+```py
+import dvc.api
+
+modelpkl = dvc.api.read(
+ 'model.pkl',
+ repo='https://github.com/example/project.git',
+ mode='rb')
+```
+
+## Description
+
+This function wraps [`dvc.api.open()`](/doc/api-reference/open), for a simple
+way to return the complete contents of a file tracked in a DVC
+project. The file can be tracked by DVC or by Git.
+
+> This is similar to the `dvc get` command in our CLI.
+
+The returned contents can be a
+[string](https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str)
+or a [bytearray](https://docs.python.org/3/library/stdtypes.html#bytearray).
+These are loaded to memory directly (without using any disc space).
+
+> The type returned depends on the `mode` used. For more details, please refer
+> to Python's [`open()`](https://docs.python.org/3/library/functions.html#open)
+> built-in, which is used under the hood.
+
+## Parameters
+
+- **`path`** - location and file name of the file in `repo`, relative to the
+ project's root.
+
+- `repo` - specifies the location of the DVC project. It can be a URL or a file
+ system path. Both HTTP and SSH protocols are supported for online Git repos
+ (e.g. `[user@]server:project.git`). _Default_: The current project is used
+ (the current working directory tree is walked up to find it).
+
+- `rev` - Git commit (any [revision](https://git-scm.com/docs/revisions) such as
+ a branch or tag name, or a commit hash). If `repo` is not a Git repo, this
+ option is ignored. _Default_: `HEAD`.
+
+- `remote` - name of the [DVC remote](/doc/command-reference/remote) to look for
+ the target data. _Default_: The
+ [default remote](/doc/command-reference/remote/default) of `repo` is used if a
+ `remote` argument is not given. For local projects, the cache is
+ tied before the default remote.
+
+- `mode` - specifies the mode in which the file is opened. Defaults to `"r"`
+ (read). Mirrors the namesake parameter in builtin
+ [`open()`](https://docs.python.org/3/library/functions.html#open).
+
+- `encoding` -
+ [codec](https://docs.python.org/3/library/codecs.html#standard-encodings) used
+ to decode the file contents to a string. This should only be used in text
+ mode. Defaults to `"utf-8"`. Mirrors the namesake parameter in builtin
+ `open()`.
+
+## Exceptions
+
+- `dvc.exceptions.FileMissingError` - file in `path` is missing from `repo`.
+
+- `dvc.exceptions.PathMissingError` - `path` cannot be found in `repo`.
+
+- `dvc.api.UrlNotDvcRepoError` - `repo` is not a DVC project.
+
+- `dvc.exceptions.NoRemoteError` - no `remote` is found.
+
+## Example: Load data from a DVC repository
+
+Any data artifact hosted online can be loaded directly in your
+Python code with this API. For example, let's say that you want to load and
+unserialize a binary model from a repo on Github:
+
+```py
+import pickle
+import dvc.api
+
+model = pickle.loads(
+ dvc.api.read(
+ 'model.pkl',
+ repo='https://github.com/example/project.git'
+ mode='rb'
+ )
+ )
+```
+
+> We're using `'rb'` mode here for compatibility with `pickle.loads()`.
diff --git a/public/static/docs/changelog/0.18.md b/content/docs/changelog/0.18.md
similarity index 94%
rename from public/static/docs/changelog/0.18.md
rename to content/docs/changelog/0.18.md
index 27890748e4..08dbf0f167 100644
--- a/public/static/docs/changelog/0.18.md
+++ b/content/docs/changelog/0.18.md
@@ -29,10 +29,10 @@ really excited to share the progress with you:
to use:
- More heavy operations render dynamic progress bar (e.g. file hash
- computation): ![](/static/img/0.18-progress.gif)
+ computation): ![](/img/0.18-progress.gif)
- Pipeline visualization via command line. Just run `dvc pipeline show` with
- option `--ascii` and a target: ![](/static/img/0.18-pipeline.gif)
+ option `--ascii` and a target: ![](/img/0.18-pipeline.gif)
- Many hidden gems: `dvc repro` dry and interactive modes, improved overall
commands verbosity and revised commands help.
diff --git a/public/static/docs/changelog/0.35.md b/content/docs/changelog/0.35.md
similarity index 98%
rename from public/static/docs/changelog/0.35.md
rename to content/docs/changelog/0.35.md
index 774fd547d6..a3063ec96d 100644
--- a/public/static/docs/changelog/0.35.md
+++ b/content/docs/changelog/0.35.md
@@ -57,7 +57,7 @@ improvements) we have done in the last few months:
- π A lot of **UI improvements** . Starting from the finally fixed nasty issue
with Windows command prompt printing a lot of garbage symbols, to using
progress bars for checkouts, better metrics output, and lots of smaller
- things: ![|528x200](/static/img/0.35-metrics.gif)
+ things: ![|528x200](/img/0.35-metrics.gif)
- β‘οΈ **Performance optimizations.** The most notable one is the migration from
using a plain JSON file to an (embedded) SQLLite instance, to cache file and
diff --git a/public/static/docs/command-reference/add.md b/content/docs/command-reference/add.md
similarity index 100%
rename from public/static/docs/command-reference/add.md
rename to content/docs/command-reference/add.md
diff --git a/public/static/docs/command-reference/cache/dir.md b/content/docs/command-reference/cache/dir.md
similarity index 100%
rename from public/static/docs/command-reference/cache/dir.md
rename to content/docs/command-reference/cache/dir.md
diff --git a/public/static/docs/command-reference/cache/index.md b/content/docs/command-reference/cache/index.md
similarity index 100%
rename from public/static/docs/command-reference/cache/index.md
rename to content/docs/command-reference/cache/index.md
diff --git a/public/static/docs/command-reference/checkout.md b/content/docs/command-reference/checkout.md
similarity index 100%
rename from public/static/docs/command-reference/checkout.md
rename to content/docs/command-reference/checkout.md
diff --git a/public/static/docs/command-reference/commit.md b/content/docs/command-reference/commit.md
similarity index 100%
rename from public/static/docs/command-reference/commit.md
rename to content/docs/command-reference/commit.md
diff --git a/public/static/docs/command-reference/config.md b/content/docs/command-reference/config.md
similarity index 100%
rename from public/static/docs/command-reference/config.md
rename to content/docs/command-reference/config.md
diff --git a/public/static/docs/command-reference/destroy.md b/content/docs/command-reference/destroy.md
similarity index 100%
rename from public/static/docs/command-reference/destroy.md
rename to content/docs/command-reference/destroy.md
diff --git a/public/static/docs/command-reference/diff.md b/content/docs/command-reference/diff.md
similarity index 100%
rename from public/static/docs/command-reference/diff.md
rename to content/docs/command-reference/diff.md
diff --git a/public/static/docs/command-reference/fetch.md b/content/docs/command-reference/fetch.md
similarity index 100%
rename from public/static/docs/command-reference/fetch.md
rename to content/docs/command-reference/fetch.md
diff --git a/public/static/docs/command-reference/gc.md b/content/docs/command-reference/gc.md
similarity index 100%
rename from public/static/docs/command-reference/gc.md
rename to content/docs/command-reference/gc.md
diff --git a/public/static/docs/command-reference/get-url.md b/content/docs/command-reference/get-url.md
similarity index 100%
rename from public/static/docs/command-reference/get-url.md
rename to content/docs/command-reference/get-url.md
diff --git a/public/static/docs/command-reference/get.md b/content/docs/command-reference/get.md
similarity index 100%
rename from public/static/docs/command-reference/get.md
rename to content/docs/command-reference/get.md
diff --git a/public/static/docs/command-reference/import-url.md b/content/docs/command-reference/import-url.md
similarity index 100%
rename from public/static/docs/command-reference/import-url.md
rename to content/docs/command-reference/import-url.md
diff --git a/public/static/docs/command-reference/import.md b/content/docs/command-reference/import.md
similarity index 100%
rename from public/static/docs/command-reference/import.md
rename to content/docs/command-reference/import.md
diff --git a/public/static/docs/command-reference/index.md b/content/docs/command-reference/index.md
similarity index 100%
rename from public/static/docs/command-reference/index.md
rename to content/docs/command-reference/index.md
diff --git a/public/static/docs/command-reference/init.md b/content/docs/command-reference/init.md
similarity index 100%
rename from public/static/docs/command-reference/init.md
rename to content/docs/command-reference/init.md
diff --git a/public/static/docs/command-reference/install.md b/content/docs/command-reference/install.md
similarity index 100%
rename from public/static/docs/command-reference/install.md
rename to content/docs/command-reference/install.md
diff --git a/public/static/docs/command-reference/lock.md b/content/docs/command-reference/lock.md
similarity index 100%
rename from public/static/docs/command-reference/lock.md
rename to content/docs/command-reference/lock.md
diff --git a/public/static/docs/command-reference/metrics/add.md b/content/docs/command-reference/metrics/add.md
similarity index 100%
rename from public/static/docs/command-reference/metrics/add.md
rename to content/docs/command-reference/metrics/add.md
diff --git a/public/static/docs/command-reference/metrics/diff.md b/content/docs/command-reference/metrics/diff.md
similarity index 100%
rename from public/static/docs/command-reference/metrics/diff.md
rename to content/docs/command-reference/metrics/diff.md
diff --git a/public/static/docs/command-reference/metrics/index.md b/content/docs/command-reference/metrics/index.md
similarity index 100%
rename from public/static/docs/command-reference/metrics/index.md
rename to content/docs/command-reference/metrics/index.md
diff --git a/public/static/docs/command-reference/metrics/modify.md b/content/docs/command-reference/metrics/modify.md
similarity index 100%
rename from public/static/docs/command-reference/metrics/modify.md
rename to content/docs/command-reference/metrics/modify.md
diff --git a/public/static/docs/command-reference/metrics/remove.md b/content/docs/command-reference/metrics/remove.md
similarity index 100%
rename from public/static/docs/command-reference/metrics/remove.md
rename to content/docs/command-reference/metrics/remove.md
diff --git a/public/static/docs/command-reference/metrics/show.md b/content/docs/command-reference/metrics/show.md
similarity index 100%
rename from public/static/docs/command-reference/metrics/show.md
rename to content/docs/command-reference/metrics/show.md
diff --git a/public/static/docs/command-reference/move.md b/content/docs/command-reference/move.md
similarity index 100%
rename from public/static/docs/command-reference/move.md
rename to content/docs/command-reference/move.md
diff --git a/public/static/docs/command-reference/pipeline/index.md b/content/docs/command-reference/pipeline/index.md
similarity index 100%
rename from public/static/docs/command-reference/pipeline/index.md
rename to content/docs/command-reference/pipeline/index.md
diff --git a/public/static/docs/command-reference/pipeline/list.md b/content/docs/command-reference/pipeline/list.md
similarity index 100%
rename from public/static/docs/command-reference/pipeline/list.md
rename to content/docs/command-reference/pipeline/list.md
diff --git a/public/static/docs/command-reference/pipeline/show.md b/content/docs/command-reference/pipeline/show.md
similarity index 100%
rename from public/static/docs/command-reference/pipeline/show.md
rename to content/docs/command-reference/pipeline/show.md
diff --git a/public/static/docs/command-reference/pull.md b/content/docs/command-reference/pull.md
similarity index 100%
rename from public/static/docs/command-reference/pull.md
rename to content/docs/command-reference/pull.md
diff --git a/public/static/docs/command-reference/push.md b/content/docs/command-reference/push.md
similarity index 100%
rename from public/static/docs/command-reference/push.md
rename to content/docs/command-reference/push.md
diff --git a/public/static/docs/command-reference/remote/add.md b/content/docs/command-reference/remote/add.md
similarity index 100%
rename from public/static/docs/command-reference/remote/add.md
rename to content/docs/command-reference/remote/add.md
diff --git a/public/static/docs/command-reference/remote/default.md b/content/docs/command-reference/remote/default.md
similarity index 100%
rename from public/static/docs/command-reference/remote/default.md
rename to content/docs/command-reference/remote/default.md
diff --git a/public/static/docs/command-reference/remote/index.md b/content/docs/command-reference/remote/index.md
similarity index 100%
rename from public/static/docs/command-reference/remote/index.md
rename to content/docs/command-reference/remote/index.md
diff --git a/public/static/docs/command-reference/remote/list.md b/content/docs/command-reference/remote/list.md
similarity index 100%
rename from public/static/docs/command-reference/remote/list.md
rename to content/docs/command-reference/remote/list.md
diff --git a/public/static/docs/command-reference/remote/modify.md b/content/docs/command-reference/remote/modify.md
similarity index 100%
rename from public/static/docs/command-reference/remote/modify.md
rename to content/docs/command-reference/remote/modify.md
diff --git a/public/static/docs/command-reference/remote/remove.md b/content/docs/command-reference/remote/remove.md
similarity index 100%
rename from public/static/docs/command-reference/remote/remove.md
rename to content/docs/command-reference/remote/remove.md
diff --git a/public/static/docs/command-reference/remove.md b/content/docs/command-reference/remove.md
similarity index 100%
rename from public/static/docs/command-reference/remove.md
rename to content/docs/command-reference/remove.md
diff --git a/public/static/docs/command-reference/repro.md b/content/docs/command-reference/repro.md
similarity index 100%
rename from public/static/docs/command-reference/repro.md
rename to content/docs/command-reference/repro.md
diff --git a/public/static/docs/command-reference/root.md b/content/docs/command-reference/root.md
similarity index 100%
rename from public/static/docs/command-reference/root.md
rename to content/docs/command-reference/root.md
diff --git a/public/static/docs/command-reference/run.md b/content/docs/command-reference/run.md
similarity index 100%
rename from public/static/docs/command-reference/run.md
rename to content/docs/command-reference/run.md
diff --git a/public/static/docs/command-reference/status.md b/content/docs/command-reference/status.md
similarity index 100%
rename from public/static/docs/command-reference/status.md
rename to content/docs/command-reference/status.md
diff --git a/public/static/docs/command-reference/unlock.md b/content/docs/command-reference/unlock.md
similarity index 100%
rename from public/static/docs/command-reference/unlock.md
rename to content/docs/command-reference/unlock.md
diff --git a/public/static/docs/command-reference/unprotect.md b/content/docs/command-reference/unprotect.md
similarity index 100%
rename from public/static/docs/command-reference/unprotect.md
rename to content/docs/command-reference/unprotect.md
diff --git a/public/static/docs/command-reference/update.md b/content/docs/command-reference/update.md
similarity index 100%
rename from public/static/docs/command-reference/update.md
rename to content/docs/command-reference/update.md
diff --git a/public/static/docs/command-reference/version.md b/content/docs/command-reference/version.md
similarity index 100%
rename from public/static/docs/command-reference/version.md
rename to content/docs/command-reference/version.md
diff --git a/public/static/docs/get-started/add-files.md b/content/docs/get-started/add-files.md
similarity index 100%
rename from public/static/docs/get-started/add-files.md
rename to content/docs/get-started/add-files.md
diff --git a/public/static/docs/get-started/agenda.md b/content/docs/get-started/agenda.md
similarity index 97%
rename from public/static/docs/get-started/agenda.md
rename to content/docs/get-started/agenda.md
index d1a6eeffee..1a61701c76 100644
--- a/public/static/docs/get-started/agenda.md
+++ b/content/docs/get-started/agenda.md
@@ -18,7 +18,7 @@ predicting tags for a given StackOverflow question. For example, we might want a
classifier that can classify (or predict) posts about Python by tagging them
with `python`.
-![](/static/img/example-flow-2x.png)
+![](/img/example-flow-2x.png)
This is a natural language processing context, but NLP isn't the only area of
data science where DVC can help. DVC is designed to be agnostic of frameworks,
diff --git a/public/static/docs/get-started/compare-experiments.md b/content/docs/get-started/compare-experiments.md
similarity index 100%
rename from public/static/docs/get-started/compare-experiments.md
rename to content/docs/get-started/compare-experiments.md
diff --git a/public/static/docs/get-started/configure.md b/content/docs/get-started/configure.md
similarity index 100%
rename from public/static/docs/get-started/configure.md
rename to content/docs/get-started/configure.md
diff --git a/public/static/docs/get-started/connect-code-and-data.md b/content/docs/get-started/connect-code-and-data.md
similarity index 100%
rename from public/static/docs/get-started/connect-code-and-data.md
rename to content/docs/get-started/connect-code-and-data.md
diff --git a/public/static/docs/get-started/experiments.md b/content/docs/get-started/experiments.md
similarity index 99%
rename from public/static/docs/get-started/experiments.md
rename to content/docs/get-started/experiments.md
index 1f7fb337b8..b716872a2e 100644
--- a/public/static/docs/get-started/experiments.md
+++ b/content/docs/get-started/experiments.md
@@ -37,7 +37,7 @@ $ git commit -am "Reproduce model using bigrams"
Now, we have a new `model.pkl` captured and saved. To get back to the initial
version, we run `git checkout` along with `dvc checkout` command:
-```
+```dvc
$ git checkout baseline-experiment
$ dvc checkout
```
diff --git a/public/static/docs/get-started/import-data.md b/content/docs/get-started/import-data.md
similarity index 100%
rename from public/static/docs/get-started/import-data.md
rename to content/docs/get-started/import-data.md
diff --git a/public/static/docs/get-started/index.md b/content/docs/get-started/index.md
similarity index 100%
rename from public/static/docs/get-started/index.md
rename to content/docs/get-started/index.md
diff --git a/public/static/docs/get-started/initialize.md b/content/docs/get-started/initialize.md
similarity index 100%
rename from public/static/docs/get-started/initialize.md
rename to content/docs/get-started/initialize.md
diff --git a/public/static/docs/get-started/metrics.md b/content/docs/get-started/metrics.md
similarity index 100%
rename from public/static/docs/get-started/metrics.md
rename to content/docs/get-started/metrics.md
diff --git a/public/static/docs/get-started/older-versions.md b/content/docs/get-started/older-versions.md
similarity index 100%
rename from public/static/docs/get-started/older-versions.md
rename to content/docs/get-started/older-versions.md
diff --git a/public/static/docs/get-started/pipeline.md b/content/docs/get-started/pipeline.md
similarity index 100%
rename from public/static/docs/get-started/pipeline.md
rename to content/docs/get-started/pipeline.md
diff --git a/public/static/docs/get-started/reproduce.md b/content/docs/get-started/reproduce.md
similarity index 100%
rename from public/static/docs/get-started/reproduce.md
rename to content/docs/get-started/reproduce.md
diff --git a/public/static/docs/get-started/retrieve-data.md b/content/docs/get-started/retrieve-data.md
similarity index 100%
rename from public/static/docs/get-started/retrieve-data.md
rename to content/docs/get-started/retrieve-data.md
diff --git a/public/static/docs/get-started/store-data.md b/content/docs/get-started/store-data.md
similarity index 100%
rename from public/static/docs/get-started/store-data.md
rename to content/docs/get-started/store-data.md
diff --git a/public/static/docs/get-started/visualize.md b/content/docs/get-started/visualize.md
similarity index 100%
rename from public/static/docs/get-started/visualize.md
rename to content/docs/get-started/visualize.md
diff --git a/public/static/docs/glossary.js b/content/docs/glossary.js
similarity index 100%
rename from public/static/docs/glossary.js
rename to content/docs/glossary.js
diff --git a/public/static/docs/install/completion.md b/content/docs/install/completion.md
similarity index 99%
rename from public/static/docs/install/completion.md
rename to content/docs/install/completion.md
index 4c139e3330..cd479916bd 100644
--- a/public/static/docs/install/completion.md
+++ b/content/docs/install/completion.md
@@ -134,7 +134,7 @@ $ exec $SHELL -l
This step is optional but will make the DVC output look much nicer, by adding
more colors to it. Add the following to your `~/.zshrc`:
-```zsh
+```bash
# Case insensitive match
zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*'
diff --git a/public/static/docs/install/index.md b/content/docs/install/index.md
similarity index 100%
rename from public/static/docs/install/index.md
rename to content/docs/install/index.md
diff --git a/public/static/docs/install/linux.md b/content/docs/install/linux.md
similarity index 100%
rename from public/static/docs/install/linux.md
rename to content/docs/install/linux.md
diff --git a/public/static/docs/install/macos.md b/content/docs/install/macos.md
similarity index 100%
rename from public/static/docs/install/macos.md
rename to content/docs/install/macos.md
diff --git a/public/static/docs/install/plugins.md b/content/docs/install/plugins.md
similarity index 100%
rename from public/static/docs/install/plugins.md
rename to content/docs/install/plugins.md
diff --git a/public/static/docs/install/pre-release.md b/content/docs/install/pre-release.md
similarity index 100%
rename from public/static/docs/install/pre-release.md
rename to content/docs/install/pre-release.md
diff --git a/public/static/docs/install/windows.md b/content/docs/install/windows.md
similarity index 100%
rename from public/static/docs/install/windows.md
rename to content/docs/install/windows.md
diff --git a/public/static/docs/sidebar.json b/content/docs/sidebar.json
similarity index 100%
rename from public/static/docs/sidebar.json
rename to content/docs/sidebar.json
diff --git a/public/static/docs/tutorials/community.md b/content/docs/tutorials/community.md
similarity index 100%
rename from public/static/docs/tutorials/community.md
rename to content/docs/tutorials/community.md
diff --git a/public/static/docs/tutorials/deep/define-ml-pipeline.md b/content/docs/tutorials/deep/define-ml-pipeline.md
similarity index 100%
rename from public/static/docs/tutorials/deep/define-ml-pipeline.md
rename to content/docs/tutorials/deep/define-ml-pipeline.md
diff --git a/public/static/docs/tutorials/deep/index.md b/content/docs/tutorials/deep/index.md
similarity index 94%
rename from public/static/docs/tutorials/deep/index.md
rename to content/docs/tutorials/deep/index.md
index 2f2e22d222..da9493e990 100644
--- a/public/static/docs/tutorials/deep/index.md
+++ b/content/docs/tutorials/deep/index.md
@@ -13,7 +13,7 @@ and reuse.
DVC has been built to address the reproducibility.
-![](/static/img/reproducibility.png)
+![](/img/reproducibility.png)
Git branches should beautifully reflect the non-linear structure common to the
ML process, where each hypothesis can be presented as a Git branch. However,
@@ -28,4 +28,4 @@ and this approach will not require storing binary files in your Git repository.
The diagram below describes all the DVC commands and relationships between a
local cache and remote storage.
-![](/static/img/flow-large.png)
+![](/img/flow-large.png)
diff --git a/public/static/docs/tutorials/deep/preparation.md b/content/docs/tutorials/deep/preparation.md
similarity index 100%
rename from public/static/docs/tutorials/deep/preparation.md
rename to content/docs/tutorials/deep/preparation.md
diff --git a/public/static/docs/tutorials/deep/reproducibility.md b/content/docs/tutorials/deep/reproducibility.md
similarity index 100%
rename from public/static/docs/tutorials/deep/reproducibility.md
rename to content/docs/tutorials/deep/reproducibility.md
diff --git a/public/static/docs/tutorials/deep/sharing-data.md b/content/docs/tutorials/deep/sharing-data.md
similarity index 100%
rename from public/static/docs/tutorials/deep/sharing-data.md
rename to content/docs/tutorials/deep/sharing-data.md
diff --git a/public/static/docs/tutorials/index.md b/content/docs/tutorials/index.md
similarity index 100%
rename from public/static/docs/tutorials/index.md
rename to content/docs/tutorials/index.md
diff --git a/public/static/docs/tutorials/interactive.md b/content/docs/tutorials/interactive.md
similarity index 100%
rename from public/static/docs/tutorials/interactive.md
rename to content/docs/tutorials/interactive.md
diff --git a/public/static/docs/tutorials/pipelines.md b/content/docs/tutorials/pipelines.md
similarity index 99%
rename from public/static/docs/tutorials/pipelines.md
rename to content/docs/tutorials/pipelines.md
index d6808bb074..9cc5fde18d 100644
--- a/public/static/docs/tutorials/pipelines.md
+++ b/content/docs/tutorials/pipelines.md
@@ -15,7 +15,7 @@ StackOverflow posts and trains the prediction model and saves it as an
examples, tutorials, use cases if you want to cover other aspects of the DVC.
The pipeline itself is a sequence of transformation we apply to the data file:
-![](/static/img/example-flow-2x.png)
+![](/img/example-flow-2x.png)
DVC helps to describe these transformations and capture actual data involved -
input dataset we are processing, intermediate results (useful if some
diff --git a/public/static/docs/tutorials/versioning.md b/content/docs/tutorials/versioning.md
similarity index 99%
rename from public/static/docs/tutorials/versioning.md
rename to content/docs/tutorials/versioning.md
index 12e4de36c3..377fcab698 100644
--- a/public/static/docs/tutorials/versioning.md
+++ b/content/docs/tutorials/versioning.md
@@ -7,7 +7,7 @@ datasets and ML models using DVC commands. We'll work with a
that [François Chollet](https://twitter.com/fchollet) put together to show how
to build a powerful image classifier using a pretty small dataset.
-![](/static/img/cats-and-dogs.jpg) _Dataset to classify cats and dogs_
+![](/img/cats-and-dogs.jpg) _Dataset to classify cats and dogs_
> We highly recommend reading the François' tutorial itself. It's a great
> demonstration of how a general pre-trained model can be leveraged to build a
@@ -95,7 +95,7 @@ This command downloads and extracts our raw dataset, consisting of 1000 labeled
images for training and 800 labeled images for validation. In total, it's a 43
MB dataset, with a directory structure like this:
-```sh
+```bash
data
βββ train
β βββ dogs
@@ -199,7 +199,7 @@ For simplicity's sake, we keep the validation subset the same. Now our dataset
has 2000 images for training and 800 images for validation, with a total size of
67 MB:
-```sh
+```bash
data
βββ train
β βββ dogs
@@ -248,7 +248,7 @@ to be similar to `git checkout`. All we need to do in our case is to
additionally run `dvc checkout` to get the right data into the
workspace.
-![](/static/img/versioning.png)
+![](/img/versioning.png)
There are two ways of doing this: a full workspace checkout or checkout of a
specific data or model file. Let's consider the full checkout first. It's pretty
diff --git a/public/static/docs/understanding-dvc/collaboration-issues.md b/content/docs/understanding-dvc/collaboration-issues.md
similarity index 100%
rename from public/static/docs/understanding-dvc/collaboration-issues.md
rename to content/docs/understanding-dvc/collaboration-issues.md
diff --git a/public/static/docs/understanding-dvc/core-features.md b/content/docs/understanding-dvc/core-features.md
similarity index 100%
rename from public/static/docs/understanding-dvc/core-features.md
rename to content/docs/understanding-dvc/core-features.md
diff --git a/public/static/docs/understanding-dvc/existing-tools.md b/content/docs/understanding-dvc/existing-tools.md
similarity index 100%
rename from public/static/docs/understanding-dvc/existing-tools.md
rename to content/docs/understanding-dvc/existing-tools.md
diff --git a/public/static/docs/understanding-dvc/how-it-works.md b/content/docs/understanding-dvc/how-it-works.md
similarity index 100%
rename from public/static/docs/understanding-dvc/how-it-works.md
rename to content/docs/understanding-dvc/how-it-works.md
diff --git a/public/static/docs/understanding-dvc/related-technologies.md b/content/docs/understanding-dvc/related-technologies.md
similarity index 100%
rename from public/static/docs/understanding-dvc/related-technologies.md
rename to content/docs/understanding-dvc/related-technologies.md
diff --git a/public/static/docs/understanding-dvc/resources.md b/content/docs/understanding-dvc/resources.md
similarity index 100%
rename from public/static/docs/understanding-dvc/resources.md
rename to content/docs/understanding-dvc/resources.md
diff --git a/public/static/docs/understanding-dvc/what-is-dvc.md b/content/docs/understanding-dvc/what-is-dvc.md
similarity index 100%
rename from public/static/docs/understanding-dvc/what-is-dvc.md
rename to content/docs/understanding-dvc/what-is-dvc.md
diff --git a/public/static/docs/use-cases/data-registries.md b/content/docs/use-cases/data-registries.md
similarity index 99%
rename from public/static/docs/use-cases/data-registries.md
rename to content/docs/use-cases/data-registries.md
index 5d258b54f7..558cdcbcbd 100644
--- a/public/static/docs/use-cases/data-registries.md
+++ b/content/docs/use-cases/data-registries.md
@@ -8,7 +8,7 @@ with commands such as `dvc add`. With the aim to enable reusability of these
depend on data from an external DVC repository, **similar to package management
systems, but for data science projects**.
-![](/static/img/data-registry.png) _Data and models as code_
+![](/img/data-registry.png) _Data and models as code_
Keeping this in mind, we could build a DVC project dedicated to
tracking and versioning _datasets_ (or any large data, even ML models). This way
diff --git a/public/static/docs/use-cases/index.md b/content/docs/use-cases/index.md
similarity index 100%
rename from public/static/docs/use-cases/index.md
rename to content/docs/use-cases/index.md
diff --git a/public/static/docs/use-cases/shared-development-server.md b/content/docs/use-cases/shared-development-server.md
similarity index 98%
rename from public/static/docs/use-cases/shared-development-server.md
rename to content/docs/use-cases/shared-development-server.md
index a96a19150a..4827163ae4 100644
--- a/public/static/docs/use-cases/shared-development-server.md
+++ b/content/docs/use-cases/shared-development-server.md
@@ -7,7 +7,7 @@ storage on a server accessed by several users, in a way that enables almost
instantaneous workspace restoration/switching speed for everyone β
similar to `git checkout` for your code.
-![](/static/img/shared-server.png)
+![](/img/shared-server.png)
## Preparation
diff --git a/public/static/docs/use-cases/sharing-data-and-model-files.md b/content/docs/use-cases/sharing-data-and-model-files.md
similarity index 98%
rename from public/static/docs/use-cases/sharing-data-and-model-files.md
rename to content/docs/use-cases/sharing-data-and-model-files.md
index a354c9988e..77c583e562 100644
--- a/public/static/docs/use-cases/sharing-data-and-model-files.md
+++ b/content/docs/use-cases/sharing-data-and-model-files.md
@@ -9,7 +9,7 @@ supports Amazon S3, Microsoft Azure Blob Storage, Google Drive, Google Cloud
Storage, SSH, HDFS, and other remote locations. The list is constantly growing.
(For a complete list and configuration instructions, refer to `dvc remote add`.)
-![](/static/img/model-sharing-digram.png)
+![](/img/model-sharing-digram.png)
As an example, let's take a look at how you could setup an S3
[remote storage](/doc/command-reference/remote) for a DVC project,
diff --git a/public/static/docs/use-cases/versioning-data-and-model-files.md b/content/docs/use-cases/versioning-data-and-model-files.md
similarity index 98%
rename from public/static/docs/use-cases/versioning-data-and-model-files.md
rename to content/docs/use-cases/versioning-data-and-model-files.md
index 8c4c3b4e29..dbf45e37ce 100644
--- a/public/static/docs/use-cases/versioning-data-and-model-files.md
+++ b/content/docs/use-cases/versioning-data-and-model-files.md
@@ -13,7 +13,7 @@ for versioning. To actually store the data, DVC supports various types of
[remote storage](/doc/command-reference/remote). This allows easily saving and
sharing data alongside code.
-![](/static/img/model-versioning-diagram.png)
+![](/img/model-versioning-diagram.png)
In this basic scenario, DVC is a better replacement for `git-lfs` (see
[Related Technologies](/doc/understanding-dvc/related-technologies)) and for
@@ -113,7 +113,7 @@ If you run `git status` you will see that `data.dvc` is modified and currently
points to the `v1.0` version of the cached data. Meanwhile, code
and model files are their latest versions.
-![](/static/img/versioning.png)
+![](/img/versioning.png)
To share your data with others you need to setup a
[data storage](/doc/command-reference/remote). See the
diff --git a/public/static/docs/user-guide/analytics.md b/content/docs/user-guide/analytics.md
similarity index 100%
rename from public/static/docs/user-guide/analytics.md
rename to content/docs/user-guide/analytics.md
diff --git a/public/static/docs/user-guide/contributing/core.md b/content/docs/user-guide/contributing/core.md
similarity index 100%
rename from public/static/docs/user-guide/contributing/core.md
rename to content/docs/user-guide/contributing/core.md
diff --git a/public/static/docs/user-guide/contributing/docs.md b/content/docs/user-guide/contributing/docs.md
similarity index 93%
rename from public/static/docs/user-guide/contributing/docs.md
rename to content/docs/user-guide/contributing/docs.md
index bdb41f0301..49f43a5239 100644
--- a/public/static/docs/user-guide/contributing/docs.md
+++ b/content/docs/user-guide/contributing/docs.md
@@ -7,16 +7,15 @@ website.
## Structure of the project
-To contribute documentation, these are the relevant locations under
-`public/static/`:
+To contribute documentation, these are the relevant locations:
-- [Content](https://github.com/iterative/dvc.org/tree/master/public/static/docs)
+- [Content](https://github.com/iterative/dvc.org/tree/master/content/docs)
(`docs/`): [Markdown](https://guides.github.com/features/mastering-markdown/)
files of the different pages to render dynamically in the browser.
-- [Images](https://github.com/iterative/dvc.org/tree/master/public/static/img)
+- [Images](https://github.com/iterative/dvc.org/tree/master/static/img)
(`img/`): Add new images (png, svg, etc.) here. Use them in Markdown files
- like this: `![](/static/img/.gif)`.
-- [Sections](https://github.com/iterative/dvc.org/tree/master/public/static/docs/sidebar.json)
+ like this: `![](/img/.gif)`.
+- [Sections](https://github.com/iterative/dvc.org/tree/master/content/docs/sidebar.json)
(`docs/sidebar.json`): Edit it to register a new section for the navigation
menu.
@@ -153,7 +152,7 @@ pre-commit hook that is integrated when `yarn` installs the project dependencies
> Check out the `.md` source code of any command reference to get a better idea,
> for example in
-> [this very file](https://raw.githubusercontent.com/iterative/dvc.org/master/public/static/docs/user-guide/contributing/docs.md).
+> [this very file](https://raw.githubusercontent.com/iterative/dvc.org/master/content/docs/user-guide/contributing/docs.md).
## General language guidelines
diff --git a/public/static/docs/user-guide/dvc-file-format.md b/content/docs/user-guide/dvc-file-format.md
similarity index 100%
rename from public/static/docs/user-guide/dvc-file-format.md
rename to content/docs/user-guide/dvc-file-format.md
diff --git a/public/static/docs/user-guide/dvc-files-and-directories.md b/content/docs/user-guide/dvc-files-and-directories.md
similarity index 100%
rename from public/static/docs/user-guide/dvc-files-and-directories.md
rename to content/docs/user-guide/dvc-files-and-directories.md
diff --git a/public/static/docs/user-guide/dvcignore.md b/content/docs/user-guide/dvcignore.md
similarity index 100%
rename from public/static/docs/user-guide/dvcignore.md
rename to content/docs/user-guide/dvcignore.md
diff --git a/public/static/docs/user-guide/external-dependencies.md b/content/docs/user-guide/external-dependencies.md
similarity index 100%
rename from public/static/docs/user-guide/external-dependencies.md
rename to content/docs/user-guide/external-dependencies.md
diff --git a/public/static/docs/user-guide/index.md b/content/docs/user-guide/index.md
similarity index 100%
rename from public/static/docs/user-guide/index.md
rename to content/docs/user-guide/index.md
diff --git a/public/static/docs/user-guide/large-dataset-optimization.md b/content/docs/user-guide/large-dataset-optimization.md
similarity index 100%
rename from public/static/docs/user-guide/large-dataset-optimization.md
rename to content/docs/user-guide/large-dataset-optimization.md
diff --git a/public/static/docs/user-guide/managing-external-data.md b/content/docs/user-guide/managing-external-data.md
similarity index 100%
rename from public/static/docs/user-guide/managing-external-data.md
rename to content/docs/user-guide/managing-external-data.md
diff --git a/public/static/docs/user-guide/privacy.md b/content/docs/user-guide/privacy.md
similarity index 100%
rename from public/static/docs/user-guide/privacy.md
rename to content/docs/user-guide/privacy.md
diff --git a/public/static/docs/user-guide/running-dvc-on-windows.md b/content/docs/user-guide/running-dvc-on-windows.md
similarity index 100%
rename from public/static/docs/user-guide/running-dvc-on-windows.md
rename to content/docs/user-guide/running-dvc-on-windows.md
diff --git a/public/static/docs/user-guide/setup-google-drive-remote.md b/content/docs/user-guide/setup-google-drive-remote.md
similarity index 97%
rename from public/static/docs/user-guide/setup-google-drive-remote.md
rename to content/docs/user-guide/setup-google-drive-remote.md
index 2ed6530032..2b620bfd6f 100644
--- a/public/static/docs/user-guide/setup-google-drive-remote.md
+++ b/content/docs/user-guide/setup-google-drive-remote.md
@@ -24,7 +24,7 @@ API connections, and its
ENABLE APIS AND SERVICES**. Find and select the "Google Drive API" in the API
Library, and click on the **ENABLE** button.
- ![](/static/img/gdrive-enable-apis-and-services.png)
+ ![](/img/gdrive-enable-apis-and-services.png)
4. Go back to **APIs & Services** in the left sidebar, and select **OAuth
consent screen**. Chose a **User Type** and click **CREATE**. On the next
@@ -35,7 +35,7 @@ API connections, and its
credentials** dropdown to select **OAuth client ID**. Chose **Other** and
click **Create** to proceed with a default client name.
- ![](/static/img/gdrive-create-credentials.png)
+ ![](/img/gdrive-create-credentials.png)
6. The newly generated **client ID** and **client secret** should be shown to
you now, and you can always come back to **Credentials** to fetch them.
diff --git a/public/static/docs/user-guide/troubleshooting.md b/content/docs/user-guide/troubleshooting.md
similarity index 100%
rename from public/static/docs/user-guide/troubleshooting.md
rename to content/docs/user-guide/troubleshooting.md
diff --git a/public/static/docs/user-guide/updating-tracked-files.md b/content/docs/user-guide/updating-tracked-files.md
similarity index 100%
rename from public/static/docs/user-guide/updating-tracked-files.md
rename to content/docs/user-guide/updating-tracked-files.md
diff --git a/gatsby-browser.js b/gatsby-browser.js
new file mode 100644
index 0000000000..8b0fea8d96
--- /dev/null
+++ b/gatsby-browser.js
@@ -0,0 +1,5 @@
+/* eslint-env node */
+
+const PageWrapper = require('./src/components/PageWrapper').default
+
+exports.wrapPageElement = PageWrapper
diff --git a/gatsby-config.js b/gatsby-config.js
new file mode 100644
index 0000000000..9952819eaf
--- /dev/null
+++ b/gatsby-config.js
@@ -0,0 +1,100 @@
+/* eslint-env node */
+
+const path = require('path')
+
+require('./config/prismjs/dvc')
+require('./config/prismjs/usage')
+
+const apiMiddleware = require('./middleware/api')
+const redirectsMiddleware = require('./middleware/redirects')
+
+const title = 'Data Version Control Β· DVC'
+const description =
+ 'Open-source version control system for Data Science and Machine Learning ' +
+ 'projects. Git-like experience to organize your data, models, and ' +
+ 'experiments.'
+
+const keywords = [
+ 'data version control',
+ 'machine learning',
+ 'models management'
+]
+
+const plugins = [
+ {
+ resolve: 'gatsby-source-filesystem',
+ options: {
+ name: 'blog',
+ path: path.join(__dirname, 'content', 'docs')
+ }
+ },
+ {
+ resolve: 'gatsby-transformer-remark',
+ options: {
+ plugins: [
+ 'gatsby-remark-dvc-linker',
+ 'gatsby-remark-prismjs',
+ 'gatsby-remark-copy-linked-files',
+ 'gatsby-remark-smartypants',
+ {
+ resolve: 'gatsby-remark-external-links'
+ },
+ {
+ resolve: 'gatsby-remark-autolink-headers',
+ options: {
+ enableCustomId: true,
+ isIconAfterHeader: true
+ }
+ }
+ ]
+ }
+ },
+ 'gatsby-plugin-catch-links',
+ {
+ resolve: 'gatsby-plugin-manifest',
+ options: {
+ background_color: '#eff4f8',
+ display: 'minimal-ui',
+ icon: 'static/favicon-512x512.png',
+ name: 'dvc.org',
+ short_name: 'dvc.org',
+ start_url: '/',
+ theme_color: '#eff4f8'
+ }
+ },
+ 'gatsby-plugin-react-helmet',
+ 'gatsby-plugin-styled-components',
+ 'gatsby-plugin-sitemap',
+ {
+ resolve: 'gatsby-plugin-sentry',
+ options: {
+ dsn: process.env.SENTRY_DSN,
+ environment: process.env.NODE_ENV,
+ enabled: process.env.NODE_ENV === 'production'
+ }
+ }
+]
+
+if (process.env.CONTEXT === 'production') {
+ plugins.push({
+ options: {
+ respectDNT: true,
+ trackingId: process.env.GA_ID
+ },
+ resolve: 'gatsby-plugin-google-analytics'
+ })
+}
+
+module.exports = {
+ plugins,
+ siteMetadata: {
+ description,
+ keywords,
+ siteUrl: 'https://dvc.org',
+ title
+ },
+ developMiddleware: app => {
+ app.use(redirectsMiddleware)
+ app.use('/api', apiMiddleware)
+ }
+}
diff --git a/gatsby-node.js b/gatsby-node.js
new file mode 100644
index 0000000000..2c3a68763c
--- /dev/null
+++ b/gatsby-node.js
@@ -0,0 +1,115 @@
+/* eslint-env node */
+
+const path = require('path')
+const GithubSlugger = require('github-slugger')
+
+const { getItemBySource } = require('./src/utils/sidebar')
+
+const slugger = new GithubSlugger()
+
+// Generate hedings data from markdown
+
+const SLUG_REGEXP = /\s+{#([a-z0-9-]*[a-z0-9]+)}\s*$/
+
+function extractSlugFromTitle(title) {
+ // extracts expressions like {#too-many-files} from the end of a title
+ const meta = title.match(SLUG_REGEXP)
+
+ if (meta) {
+ return [title.substring(0, meta.index), meta[1]]
+ }
+ return [title, slugger.slug(title)]
+}
+
+const parseHeadings = text => {
+ const headingRegex = /\n(## \s*)(.*)/g
+ const matches = []
+ let match
+ do {
+ match = headingRegex.exec(text)
+ if (match) {
+ const [title, slug] = extractSlugFromTitle(match[2])
+ matches.push({
+ text: title,
+ slug: slug
+ })
+ }
+ } while (match)
+
+ slugger.reset()
+ return matches
+}
+
+exports.onCreateNode = ({ node, actions }) => {
+ const { createNodeField } = actions
+
+ if (node.internal.type === 'MarkdownRemark') {
+ const docsPath = path.join(__dirname, 'content')
+
+ const source = node.fileAbsolutePath.replace(docsPath, '')
+
+ const { path: value } = getItemBySource(source)
+
+ createNodeField({
+ name: 'slug',
+ node,
+ value
+ })
+ }
+}
+
+exports.createPages = async ({ graphql, actions }) => {
+ const { createPage } = actions
+
+ const docPage = path.resolve('./src/templates/doc.js')
+
+ const result = await graphql(
+ `
+ {
+ docs: allMarkdownRemark(
+ filter: { fileAbsolutePath: { regex: "/content/docs/" } }
+ limit: 9999
+ ) {
+ edges {
+ node {
+ rawMarkdownBody
+ fields {
+ slug
+ }
+ }
+ }
+ }
+ }
+ `
+ )
+
+ if (result.errors) {
+ throw result.errors
+ }
+
+ const docs = result.data.docs.edges
+
+ docs.forEach(doc => {
+ const headings = parseHeadings(doc.node.rawMarkdownBody)
+
+ if (doc.node.fields.slug) {
+ createPage({
+ component: docPage,
+ path: doc.node.fields.slug,
+ context: {
+ slug: doc.node.fields.slug,
+ headings
+ }
+ })
+ }
+ })
+}
+
+exports.onCreatePage = ({ page, actions }) => {
+ if (/^\/404/.test(page.path)) {
+ const newPage = { ...page, context: { ...page.context, is404: true } }
+
+ actions.deletePage(page)
+ actions.createPage(newPage)
+ }
+}
diff --git a/gatsby-ssr.js b/gatsby-ssr.js
new file mode 100644
index 0000000000..8b0fea8d96
--- /dev/null
+++ b/gatsby-ssr.js
@@ -0,0 +1,5 @@
+/* eslint-env node */
+
+const PageWrapper = require('./src/components/PageWrapper').default
+
+exports.wrapPageElement = PageWrapper
diff --git a/jest.config.js b/jest.config.js
index 118fc179d2..d344eca3cb 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -1,3 +1,5 @@
+/* eslint-env node */
+
// For a detailed explanation regarding each configuration property, visit:
// https://jestjs.io/docs/en/configuration.html
@@ -5,5 +7,6 @@ module.exports = {
testEnvironment: 'node',
transform: {
'^.+\\.js?$': 'babel-jest'
- }
+ },
+ testPathIgnorePatterns: ['/node_modules/', '/.cache', '/public/']
}
diff --git a/pages/api/blog.js b/middleware/api/blog.js
similarity index 66%
rename from pages/api/blog.js
rename to middleware/api/blog.js
index ce1d3f4e33..9b0643f6cf 100644
--- a/pages/api/blog.js
+++ b/middleware/api/blog.js
@@ -1,6 +1,8 @@
-import fetch from 'isomorphic-fetch'
+/* eslint-env node */
-export default async (_, res) => {
+const fetch = require('isomorphic-fetch')
+
+module.exports = async (_, res) => {
try {
const response = await fetch(`https://blog.dvc.org/api/posts.json`)
@@ -10,7 +12,7 @@ export default async (_, res) => {
return
}
- const data = await response.text()
+ const data = await response.json()
res.status(200).json(data)
} catch {
diff --git a/pages/api/comments.js b/middleware/api/comments.js
similarity index 86%
rename from pages/api/comments.js
rename to middleware/api/comments.js
index 1b131e8655..f177aff6d2 100644
--- a/pages/api/comments.js
+++ b/middleware/api/comments.js
@@ -9,11 +9,11 @@
* potential ability to cache comments count in the future.
*/
-import fetch from 'isomorphic-fetch'
-import Cors from 'micro-cors'
-import NodeCache from 'node-cache'
+const fetch = require('isomorphic-fetch')
+const Cors = require('micro-cors')
+const NodeCache = require('node-cache')
-import { BLOG_URL, FORUM_URL } from '../../src/consts'
+const { BLOG_URL, FORUM_URL } = require('../../src/consts')
const cache = new NodeCache({ stdTTL: 900 })
@@ -73,4 +73,4 @@ const getCommentCount = async (req, res) => {
}
}
-export default cors(getCommentCount)
+module.exports = cors(getCommentCount)
diff --git a/pages/api/discourse.js b/middleware/api/discourse.js
similarity index 85%
rename from pages/api/discourse.js
rename to middleware/api/discourse.js
index ba5463c69a..9fbe2759a1 100644
--- a/pages/api/discourse.js
+++ b/middleware/api/discourse.js
@@ -1,15 +1,15 @@
/* eslint-env node */
-import fetch from 'isomorphic-fetch'
-import NodeCache from 'node-cache'
+const fetch = require('isomorphic-fetch')
+const NodeCache = require('node-cache')
-import { FORUM_URL } from '../../src/consts'
+const { FORUM_URL } = require('../../src/consts')
const cache = new NodeCache({ stdTTL: 900 })
const dev = process.env.NODE_ENV === 'development'
-export default async (_, res) => {
+module.exports = async (_, res) => {
if (cache.get('topics')) {
if (dev) console.log('Using cache for "topics"')
diff --git a/pages/api/github.js b/middleware/api/github.js
similarity index 92%
rename from pages/api/github.js
rename to middleware/api/github.js
index 1a7165b0fe..cc239a8ab6 100644
--- a/pages/api/github.js
+++ b/middleware/api/github.js
@@ -1,13 +1,13 @@
/* eslint-env node */
-import { graphql } from '@octokit/graphql'
-import NodeCache from 'node-cache'
+const { graphql } = require('@octokit/graphql')
+const NodeCache = require('node-cache')
const cache = new NodeCache({ stdTTL: 900 })
const dev = process.env.NODE_ENV === 'development'
-export default async (_, res) => {
+module.exports = async (_, res) => {
if (!process.env.GITHUB_TOKEN) {
res.status(200).json({ issues: [] })
} else {
diff --git a/middleware/api/index.js b/middleware/api/index.js
new file mode 100644
index 0000000000..6fc73fbd95
--- /dev/null
+++ b/middleware/api/index.js
@@ -0,0 +1,15 @@
+/* eslint-env node */
+
+const routes = require('express').Router()
+
+const blog = require('./blog')
+const comments = require('./comments')
+const discourse = require('./discourse')
+const github = require('./github')
+
+routes.get('/blog', blog)
+routes.get('/comments', comments)
+routes.get('/discourse', discourse)
+routes.get('/github', github)
+
+module.exports = routes
diff --git a/middleware/notFound/index.js b/middleware/notFound/index.js
new file mode 100644
index 0000000000..677c77e159
--- /dev/null
+++ b/middleware/notFound/index.js
@@ -0,0 +1,7 @@
+/* eslint-env node */
+
+const path = require('path')
+
+module.exports = (req, res) => {
+ res.sendFile(path.join(`${__dirname}`, '..', '..', 'public', '404.html'))
+}
diff --git a/middleware/redirects/index.js b/middleware/redirects/index.js
new file mode 100644
index 0000000000..5fffc9df93
--- /dev/null
+++ b/middleware/redirects/index.js
@@ -0,0 +1,36 @@
+/* eslint-env node */
+
+const { getRedirect } = require('../../src/utils/redirects')
+const { parse } = require('url')
+const { stringify } = require('querystring')
+
+const dev = process.env.NODE_ENV !== 'production'
+
+module.exports = (req, res, next) => {
+ const parsedUrl = parse(req.url, true)
+ const { pathname, query } = parsedUrl
+ const host = req.headers.host
+
+ let [redirectCode, redirectLocation] = getRedirect(host, pathname, {
+ req,
+ dev
+ })
+
+ if (redirectLocation) {
+ // HTTP redirects
+
+ const queryStr = stringify(query)
+ if (queryStr) {
+ redirectLocation += '?' + queryStr
+ }
+ res.writeHead(redirectCode, {
+ Location: redirectLocation
+ })
+
+ res.end()
+
+ return
+ }
+
+ next()
+}
diff --git a/next.config.js b/next.config.js
deleted file mode 100644
index c1a8c1a98c..0000000000
--- a/next.config.js
+++ /dev/null
@@ -1,14 +0,0 @@
-/* eslint-env node */
-
-const withSourceMaps = require('@zeit/next-source-maps')
-
-const settings = withSourceMaps({
- webpack(config) {
- return config
- },
- env: {
- SENTRY_DSN: process.env.SENTRY_DSN
- }
-})
-
-module.exports = settings
diff --git a/package.json b/package.json
index 4d8fe4ebd8..b698963263 100644
--- a/package.json
+++ b/package.json
@@ -4,15 +4,15 @@
"description": "dvc.org β website source code",
"main": "index.js",
"scripts": {
- "dev": "node server.js",
+ "develop": "gatsby develop",
"debug": "node --inspect-brk server.js",
- "build": "next build",
+ "build": "gatsby build",
"test": "jest",
"start": "./scripts/clear-cloudflare-cache.js; NODE_ENV=production node server.js",
"format-staged": "pretty-quick --staged --no-restage --bail",
- "format-check": "prettier --check '{.,pages/**,public/static/docs/**,src/**}/*.{js,md,json}'",
- "lint-check": "eslint --ext .json,.js src pages",
- "format-all": "prettier --write '{.,pages/**,public/static/docs/**,src/**}/*.{js,md,json}'",
+ "format-check": "prettier --check '{.,pages/**,content/docs/**,src/**}/*.{js,md,json}'",
+ "lint-check": "eslint --ext .json,.js src middleware",
+ "format-all": "prettier --write '{.,pages/**,content/docs/**,src/**}/*.{js,md,json}'",
"format": "prettier --write",
"link-check": "scripts/link-check-git-all.sh",
"link-check-diff": "scripts/link-check-git-diff.sh"
@@ -29,11 +29,15 @@
"homepage": "https://github.com/iterative/dvc.org#readme",
"dependencies": {
"@octokit/graphql": "^4.3.1",
+ "@reach/router": "^1.3.1",
"@sentry/browser": "^5.12.1",
- "@zeit/next-source-maps": "^0.0.3",
"color": "^3.1.2",
"date-fns": "^2.8.1",
+ "docsearch.js": "^2.6.3",
"dom-scroll-into-view": "^2.0.1",
+ "express": "^4.17.1",
+ "gatsby": "^2.19.21",
+ "gatsby-link": "^2.2.29",
"github-markdown-css": "^3.0.1",
"isomorphic-fetch": "^2.2.1",
"lodash.fill": "^3.4.0",
@@ -43,22 +47,24 @@
"lodash.throttle": "^4.1.1",
"lodash.topairs": "^4.3.0",
"micro-cors": "^0.1.1",
- "next": "^9.1.6",
"node-cache": "^5.1.0",
"perfect-scrollbar": "^1.4.0",
+ "prismjs": "^1.19.0",
"prop-types": "^15.7.2",
"react": "^16.12.0",
"react-collapse": "^5.0.1",
"react-collapsible": "^2.6.2",
"react-dom": "^16.12.0",
"react-ga": "^2.7.0",
+ "react-helmet": "^5.2.1",
"react-markdown": "^4.2.2",
"react-popover": "^0.5.10",
"react-scroll": "^1.7.13",
"react-slick": "^0.25.2",
- "react-syntax-highlighter": "^11.0.2",
"react-use": "^13.24.0",
+ "rehype-react": "^4.0.1",
"request": "^2.88.0",
+ "slick-carousel": "^1.8.1",
"styled-components": "^4.4.1",
"styled-reset": "^4.0.8",
"unist-util-visit": "2.0.1"
@@ -67,6 +73,7 @@
"@babel/core": "^7.7.7",
"babel-eslint": "^10.0.3",
"babel-jest": "^24.9.0",
+ "babel-plugin-styled-components": "^1.10.7",
"babel-plugin-transform-define": "^2.0.0",
"babel-plugin-transform-object-assign": "^6.22.0",
"eslint": "^6.7.2",
@@ -75,6 +82,20 @@
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-prettier": "^3.1.1",
"eslint-plugin-react": "^7.17.0",
+ "gatsby-plugin-catch-links": "^2.1.26",
+ "gatsby-plugin-google-analytics": "^2.1.36",
+ "gatsby-plugin-manifest": "^2.2.42",
+ "gatsby-plugin-react-helmet": "^3.1.22",
+ "gatsby-plugin-sentry": "^1.0.1",
+ "gatsby-plugin-sitemap": "^2.2.27",
+ "gatsby-plugin-styled-components": "^3.1.19",
+ "gatsby-remark-autolink-headers": "^2.1.24",
+ "gatsby-remark-copy-linked-files": "^2.1.37",
+ "gatsby-remark-external-links": "^0.0.4",
+ "gatsby-remark-prismjs": "^3.3.31",
+ "gatsby-remark-smartypants": "^2.1.21",
+ "gatsby-source-filesystem": "^2.1.48",
+ "gatsby-transformer-remark": "^2.6.53",
"husky": "^4.0.10",
"jest": "^24.9.0",
"lint-staged": "^10.0.0",
diff --git a/pages/_app.js b/pages/_app.js
deleted file mode 100644
index 10f9f70d27..0000000000
--- a/pages/_app.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/* global process */
-
-import React from 'react'
-import App from 'next/app'
-import * as Sentry from '@sentry/browser'
-
-Sentry.init({
- dsn: process.env.SENTRY_DSN
-})
-
-class MyApp extends App {
- componentDidCatch(error, errorInfo) {
- Sentry.withScope(scope => {
- Object.keys(errorInfo).forEach(key => {
- scope.setExtra(key, errorInfo[key])
- })
-
- Sentry.captureException(error)
- })
-
- super.componentDidCatch(error, errorInfo)
- }
-
- render() {
- const { Component, pageProps } = this.props
-
- return
- }
-}
-
-export default MyApp
diff --git a/pages/_document.js b/pages/_document.js
deleted file mode 100644
index c9e36105e5..0000000000
--- a/pages/_document.js
+++ /dev/null
@@ -1,145 +0,0 @@
-/* eslint-env node */
-
-import React from 'react'
-import Document, { Head, Main, NextScript } from 'next/document'
-import { ServerStyleSheet } from 'styled-components'
-import * as Sentry from '@sentry/browser'
-
-process.on('unhandledRejection', err => {
- Sentry.captureException(err)
-})
-
-process.on('uncaughtException', err => {
- Sentry.captureException(err)
-})
-
-import {
- META_BASE_TITLE,
- META_DESCRIPTION,
- META_KEYWORDS,
- META_SOCIAL_IMAGE
-} from '../src/consts'
-
-const inject = str => (
-
-)
-
-export default class Page extends Document {
- static getInitialProps({ renderPage }) {
- const sheet = new ServerStyleSheet()
- const page = renderPage(App => props =>
- sheet.collectStyles()
- )
- const styleTags = sheet.getStyleElement()
- return { ...page, styleTags }
- }
-
- render() {
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {this.props.styleTags}
-
-
-
-
- {inject(
- `
-
- `
- )}
-
-
- >
- )
- }
-}
diff --git a/pages/community.js b/pages/community.js
deleted file mode 100644
index 2553720e5a..0000000000
--- a/pages/community.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import React from 'react'
-import Head from 'next/head'
-
-import Community from '../src/components/Community'
-
-import { META_BASE_TITLE } from '../src/consts'
-
-export default function CommunityPage() {
- return (
- <>
-
-
-
- Community | {META_BASE_TITLE}
-
-
- >
- )
-}
diff --git a/pages/doc.js b/pages/doc.js
deleted file mode 100644
index 0521bf3258..0000000000
--- a/pages/doc.js
+++ /dev/null
@@ -1,65 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import fetch from 'isomorphic-fetch'
-
-import Error from 'next/error'
-import Head from 'next/head'
-
-import Documentation from '../src/components/Documentation'
-
-import { getItemByPath } from '../src/utils/sidebar'
-import { makeAbsoluteURL } from '../src/utils/api'
-
-import { META_BASE_TITLE } from '../src/consts'
-
-export default function DocumentationPage({ item, markdown, errorCode }) {
- if (errorCode) {
- return
- }
-
- return (
- <>
-
-
- {item.label} | {META_BASE_TITLE}
-
-
-
- >
- )
-}
-
-DocumentationPage.propTypes = {
- item: PropTypes.object,
- markdown: PropTypes.string,
- errorCode: PropTypes.number
-}
-
-DocumentationPage.getInitialProps = async ({ asPath, req }) => {
- const item = getItemByPath(asPath.split(/[?#]/)[0])
-
- if (!item) {
- return {
- errorCode: 404
- }
- }
-
- try {
- const res = await fetch(makeAbsoluteURL(req, item.source))
-
- if (res.status !== 200) {
- return {
- errorCode: res.status
- }
- }
-
- const markdown = await res.text()
-
- return {
- item,
- markdown
- }
- } catch {
- window.location.reload()
- }
-}
diff --git a/pages/features.js b/pages/features.js
deleted file mode 100644
index e8d0145e79..0000000000
--- a/pages/features.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import React from 'react'
-
-import Head from 'next/head'
-
-import Features from '../src/components/Features'
-
-import { META_BASE_TITLE } from '../src/consts'
-
-export default function FeaturesPage() {
- return (
- <>
-
- Features | {META_BASE_TITLE}
-
-
- >
- )
-}
diff --git a/pages/index.js b/pages/index.js
deleted file mode 100644
index 73c2c0faa3..0000000000
--- a/pages/index.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import React from 'react'
-
-import Head from 'next/head'
-
-import Home from '../src/components/Home'
-
-import { META_BASE_TITLE } from '../src/consts'
-
-export default function HomePage() {
- return (
- <>
-
-
-
- {META_BASE_TITLE}
-
-
- >
- )
-}
diff --git a/pages/support.js b/pages/support.js
deleted file mode 100644
index 79a80ce0b8..0000000000
--- a/pages/support.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import React from 'react'
-
-import Head from 'next/head'
-
-import Support from '../src/components/Support'
-
-import { META_BASE_TITLE } from '../src/consts'
-
-export default function SupportPage() {
- return (
- <>
-
- Support | {META_BASE_TITLE}
-
-
- >
- )
-}
diff --git a/plugins/gatsby-remark-dvc-linker/index.js b/plugins/gatsby-remark-dvc-linker/index.js
new file mode 100644
index 0000000000..9a6f13a937
--- /dev/null
+++ b/plugins/gatsby-remark-dvc-linker/index.js
@@ -0,0 +1,43 @@
+/* eslint-env node */
+
+const visit = require('unist-util-visit')
+const { getItemByPath } = require('../../src/utils/sidebar')
+
+const DVC_REGEXP = /dvc\s+[a-z][a-z-.]*/
+const COMMAND_REGEXP = /^[a-z][a-z-]*$/
+const COMMAND_ROOT = '/doc/command-reference/'
+
+module.exports = ({ markdownAST }) => {
+ visit(markdownAST, 'inlineCode', function(node, index, parent) {
+ if (parent.type !== 'link' && DVC_REGEXP.test(node.value)) {
+ let parts = node.value.split(/\s+/)
+ let url
+
+ const hasThirdSegment = parts[2] && COMMAND_REGEXP.test(parts[2])
+ const isCommandPageExists = getItemByPath(`${COMMAND_ROOT}${parts[1]}`)
+ const isSubcommandPageExists =
+ isCommandPageExists &&
+ hasThirdSegment &&
+ getItemByPath(`${COMMAND_ROOT}${parts[1]}/${parts[2]}`)
+
+ if (isSubcommandPageExists) {
+ url = `${COMMAND_ROOT}${parts[1]}/${parts[2]}`
+ } else if (isCommandPageExists && hasThirdSegment) {
+ url = `${COMMAND_ROOT}${parts[1]}#${parts[2]}`
+ } else if (isCommandPageExists) {
+ url = `${COMMAND_ROOT}${parts[1]}`
+ }
+
+ if (url) {
+ parent.children[index] = {
+ type: 'link',
+ url: url,
+ children: [node],
+ position: node.position
+ }
+ }
+ }
+ })
+
+ return markdownAST
+}
diff --git a/plugins/gatsby-remark-dvc-linker/package.json b/plugins/gatsby-remark-dvc-linker/package.json
new file mode 100644
index 0000000000..f4227d784e
--- /dev/null
+++ b/plugins/gatsby-remark-dvc-linker/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "gatsby-remark-dvc-linker",
+ "version": "1.0.0",
+ "main": "index.js",
+ "author": "Ivan Shcheklein",
+ "license": "Apache-2.0"
+}
diff --git a/redirects-list.json b/redirects-list.json
index b8f64af146..2f3bcb6ab8 100644
--- a/redirects-list.json
+++ b/redirects-list.json
@@ -9,5 +9,9 @@
"^/doc/commands-reference(/.*)?$ /doc/command-reference$1",
"^/doc/tutorial/?$ /doc/tutorials",
"^/doc/tutorial/(.*)? /doc/tutorials/deep/$1",
- "^/doc/use-cases/data-and-model-files-versioning/?$ /doc/use-cases/versioning-data-and-model-files"
+ "^/doc/use-cases/data-and-model-files-versioning/?$ /doc/use-cases/versioning-data-and-model-files",
+ "^/doc/?$ /doc/get-started 307",
+ "^/doc/understanding-dvc/?$ /doc/understanding-dvc/collaboration-issues 307",
+ "^/doc/changelog/?$ /doc/changelog/0.18 307",
+ "^/doc/user-guide/contributing/?$ /doc/user-guide/contributing/core 307"
]
diff --git a/scripts/exclude-links.txt b/scripts/exclude-links.txt
index d9f10dcbea..37933688b8 100644
--- a/scripts/exclude-links.txt
+++ b/scripts/exclude-links.txt
@@ -16,7 +16,7 @@ https://drive.google.com/drive/folders/0AIac4JZqHhKmUk9PDA
https://dvc.org$
https://dvc.org/doc/command-reference/foo
https://dvc.org/foo
-https://dvc.org/static/img/.gif
+https://dvc.org/img/.gif
https://example.com/data.txt
https://example.com/foo
https://dvc.org/foo/bar?baz
diff --git a/scripts/link-check-git-all.sh b/scripts/link-check-git-all.sh
index 2251fb36e5..fe7e7227c4 100755
--- a/scripts/link-check-git-all.sh
+++ b/scripts/link-check-git-all.sh
@@ -1,3 +1,3 @@
#!/usr/bin/env bash
-(find pages/ public/static/docs/ src/ .github/ -name '*.md' -o -name '*.js' && ls *.md *.js) \
+(find pages/ content/docs/ src/ .github/ -name '*.md' -o -name '*.js' && ls *.md *.js) \
| xargs -n1 -P8 $(dirname "$0")/link-check.sh
diff --git a/server.js b/server.js
index 673efcab86..467723dff0 100644
--- a/server.js
+++ b/server.js
@@ -1,68 +1,19 @@
/* eslint-env node */
-/*
- * Custom server (with custom routes) See
- * https://nextjs.org/docs/advanced-features/custom-server
- *
- * NOTE: This file doesn't go through babel or webpack. Make sure the syntax and
- * sources this file requires are compatible with the current node version you
- * are running.
- */
+const express = require('express')
+const app = express()
-const { createServer } = require('http')
-const { parse } = require('url')
-const { stringify } = require('querystring')
-const next = require('next')
+const apiMiddleware = require('./middleware/api')
+const redirectsMiddleware = require('./middleware/redirects')
+const notFoundMiddleware = require('./middleware/notFound')
-const { getItemByPath } = require('./src/utils/sidebar')
-const { getRedirect } = require('./src/utils/redirects')
-
-const dev = process.env.NODE_ENV !== 'production'
-const app = next({ dev })
-const handle = app.getRequestHandler()
const port = process.env.PORT || 3000
-app.prepare().then(() => {
- createServer((req, res) => {
- const parsedUrl = parse(req.url, true)
- const { pathname, query } = parsedUrl
- const host = req.headers.host
-
- res.setHeader('Cache-Control', 'public, max-age=0, s-maxage=99999')
-
- let [redirectCode, redirectLocation] = getRedirect(host, pathname, {
- req,
- dev
- })
-
- if (redirectLocation) {
- // HTTP redirects
-
- const queryStr = stringify(query)
- if (queryStr) {
- redirectLocation += '?' + queryStr
- }
- res.writeHead(redirectCode, {
- Location: redirectLocation
- })
- res.end()
- } else if (/^\/doc(\/.*)?$/.test(pathname)) {
- // Docs Engine handler
+app.use(redirectsMiddleware)
+app.use('/api', apiMiddleware)
- // Force 404 response code for any inexistent /doc item.
- if (!getItemByPath(pathname)) {
- res.statusCode = 404
- }
+app.use(express.static('public', { cacheControl: true, maxAge: 0 }))
- // Custom route for all docs
- app.render(req, res, '/doc', query)
- } else {
- // Regular Next.js handler
+app.use(notFoundMiddleware)
- handle(req, res, parsedUrl)
- }
- }).listen(port, err => {
- if (err) throw err
- console.info(`> Ready on localhost:${port}`)
- })
-})
+app.listen(port, () => console.log(`Ready on localhost:${port}!`))
diff --git a/src/components/404/index.js b/src/components/404/index.js
new file mode 100644
index 0000000000..c2869a7ce5
--- /dev/null
+++ b/src/components/404/index.js
@@ -0,0 +1,20 @@
+import React from 'react'
+import Subscribe from '../Subscribe'
+
+import { Wrapper, Title, Content } from './styles'
+
+function Page404() {
+ return (
+ <>
+
+ Not Found
+
+ You just hit a route that doesn't exist... the sadness.
+
+
+
+ >
+ )
+}
+
+export default Page404
diff --git a/src/components/404/styles.js b/src/components/404/styles.js
new file mode 100644
index 0000000000..97dc2bcc75
--- /dev/null
+++ b/src/components/404/styles.js
@@ -0,0 +1,38 @@
+import styled from 'styled-components'
+import { media } from '../../styles'
+
+export const Wrapper = styled.div`
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ margin: 100px auto 150px;
+`
+
+export const Title = styled.h1`
+ ${media.desktop`
+ font-weight: 500;
+ font-size: 30px;
+ line-height: 40px;
+ `}
+
+ font-family: BrandonGrotesqueMed;
+ font-size: 40px;
+ line-height: 60px;
+ margin-top: 0.67em;
+ margin-bottom: 0.67em;
+`
+
+export const Content = styled.div`
+ ${media.desktop`
+ padding: 0 15px;
+ text-align: center;
+ font-size: 20px;
+ line-height: 30px;
+ `}
+
+ padding: 0;
+ text-align: left;
+ font-size: 24px;
+ line-height: 34px;
+`
diff --git a/src/components/Community/Button/index.js b/src/components/Community/Button/index.js
deleted file mode 100644
index 97df73f6ff..0000000000
--- a/src/components/Community/Button/index.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-
-import { Wrapper } from './styles'
-
-function CommunityButton({ theme, children, forwardedRef, ...props }) {
- return (
-
- {children}
-
- )
-}
-
-CommunityButton.propTypes = {
- children: PropTypes.node,
- theme: PropTypes.shape({
- backgroundColor: PropTypes.string,
- color: PropTypes.string
- }),
- forwardedRef: PropTypes.func
-}
-
-// eslint-disable-next-line react/display-name
-export default React.forwardRef((props, ref) => (
-
-))
diff --git a/src/components/Community/Button/styles.js b/src/components/Community/Button/styles.js
deleted file mode 100644
index dd7fe14fa9..0000000000
--- a/src/components/Community/Button/styles.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import styled from 'styled-components'
-
-export const Wrapper = styled.a`
- display: block;
- height: 38px;
- border-radius: 4px;
- font-size: 16px;
- font-family: BrandonGrotesqueMed;
- line-height: 38px;
- text-decoration: none;
- text-align: center;
- color: ${({ color }) => (color ? color : '#999')};
- background-color: ${({ backgroundColor }) =>
- backgroundColor ? backgroundColor : '#ddd'};
-
- &:hover {
- opacity: 0.7;
- }
-`
diff --git a/src/components/Community/Contribute/index.js b/src/components/Community/Contribute/index.js
index de93153a38..ea3323df83 100644
--- a/src/components/Community/Contribute/index.js
+++ b/src/components/Community/Contribute/index.js
@@ -3,13 +3,12 @@ import PropTypes from 'prop-types'
import { logEvent } from '../../../utils/ga'
-import CommunityButton from '../Button'
import CommunityBlock from '../Block'
import CommunitySection from '../Section'
import data from '../data'
-import { Item, Items, Wrapper } from '../styles'
+import { Button, Item, Items, Wrapper } from '../styles'
const { description, mobileDescription, title } = data.section.contribute
@@ -23,10 +22,10 @@ export default function CommunityContribute({ theme }) {
@@ -35,7 +34,7 @@ export default function CommunityContribute({ theme }) {
Go to Github
-
+
}
>
Let's build something great together. Become a DVC
@@ -54,7 +53,7 @@ export default function CommunityContribute({ theme }) {
Letβs talk!
-
+
}
>
We're always interested in guest writers for our blog. If you
@@ -73,7 +72,7 @@ export default function CommunityContribute({ theme }) {
Letβs talk!
-
+
}
>
We support speakers all over the world and help with preparation,
@@ -92,7 +91,7 @@ export default function CommunityContribute({ theme }) {
Letβs talk!
-
+
}
>
Get perks and benefits for contributing to the code base, writing
diff --git a/src/components/Community/Events/index.js b/src/components/Community/Events/index.js
index c63900ecf0..5ce5e13c55 100644
--- a/src/components/Community/Events/index.js
+++ b/src/components/Community/Events/index.js
@@ -6,12 +6,11 @@ import fill from 'lodash.fill'
import { logEvent } from '../../../utils/ga'
import CommunityBlock from '../Block'
-import CommunityButton from '../Button'
import CommunitySection from '../Section'
import data from '../data'
-import { Item, Items, Line, Link, Wrapper } from '../styles'
+import { Button, Item, Items, Line, Link, Wrapper } from '../styles'
import { Image, ImageWrapper, Meta } from './styles'
@@ -39,7 +38,7 @@ function CommunityEvent({
-
Event Info
-
+
}
>
@@ -101,7 +100,7 @@ export default function CommunityEvents({ theme }) {
anchor="events"
color={theme.color}
description={description}
- icon="/static/img/community/events.svg"
+ icon="/img/community/events.svg"
mobileDescription={mobileDescription}
title={title}
>
diff --git a/src/components/Community/Learn/index.js b/src/components/Community/Learn/index.js
index 39862c2bcd..16fc3fc229 100644
--- a/src/components/Community/Learn/index.js
+++ b/src/components/Community/Learn/index.js
@@ -5,15 +5,16 @@ import format from 'date-fns/format'
import LocalLink from '../../LocalLink'
import { logEvent } from '../../../utils/ga'
+import { getFirstPage } from '../../../utils/sidebar'
import CommunityBlock from '../Block'
-import CommunityButton from '../Button'
import CommunitySection from '../Section'
import { usePosts, useCommentsCount } from '../../../utils/api'
import { pluralizeComments } from '../../../utils/i18n'
import {
+ Button,
Comments,
HeaderLink,
ImageLine,
@@ -32,6 +33,7 @@ import { Image } from './styles'
import data from '../data'
+const docsPage = getFirstPage()
const { description, mobileDescription, title } = data.section.learn
const { documentation, userContent } = data
@@ -160,7 +162,7 @@ function CommunityDocumentation({ url, title, description, color }) {
href={url}
as={Link}
color={color}
- large
+ large="true"
onClick={logDocumentation}
>
{title}
@@ -184,10 +186,10 @@ export default function CommunityLearn({ theme }) {
@@ -196,7 +198,7 @@ export default function CommunityLearn({ theme }) {
@@ -205,8 +207,8 @@ export default function CommunityLearn({ theme }) {
}
action={
@@ -237,7 +239,7 @@ export default function CommunityLearn({ theme }) {
}
action={
posts && (
-
See all Posts
-
+
)
}
>
diff --git a/src/components/Community/Meet/index.js b/src/components/Community/Meet/index.js
index 8b682a94af..98c12383ac 100644
--- a/src/components/Community/Meet/index.js
+++ b/src/components/Community/Meet/index.js
@@ -3,7 +3,6 @@ import PropTypes from 'prop-types'
import formatDistanceToNow from 'date-fns/formatDistanceToNow'
import CommunityBlock from '../Block'
-import CommunityButton from '../Button'
import CommunitySection from '../Section'
import { pluralizeComments } from '../../../utils/i18n'
@@ -17,6 +16,7 @@ const { description, mobileDescription, title } = data.section.meet
import { Stats, StatLabel, StatLine, StatValue } from './styles'
import {
+ Button,
Comments,
HeaderLink,
Item,
@@ -119,11 +119,11 @@ export default function CommunityMeet({ theme }) {
@@ -141,7 +141,7 @@ export default function CommunityMeet({ theme }) {
}
action={
-
Open Chat
-
+
}
- icon="/static/img/community/discord.svg"
+ icon="/img/community/discord.svg"
>
Need urgent help? Ask advice from experienced developers online
@@ -182,7 +182,7 @@ export default function CommunityMeet({ theme }) {
}
action={
topics && (
-
Read All Topics
-
+
)
}
- icon="/static/img/community/discourse.svg"
+ icon="/img/community/discourse.svg"
>
{!topicsReady && Loading...}
{topicsError && (
@@ -223,7 +223,7 @@ export default function CommunityMeet({ theme }) {
}
action={
issues && (
-
Read All Issues
-
+
)
}
- icon="/static/img/community/github.svg"
+ icon="/img/community/github.svg"
>
{!issuesReady && Loading...}
{issuesError && (
diff --git a/src/components/Community/Section/index.js b/src/components/Community/Section/index.js
index 8cc4871144..c13a6ff357 100644
--- a/src/components/Community/Section/index.js
+++ b/src/components/Community/Section/index.js
@@ -1,10 +1,9 @@
import PropTypes from 'prop-types'
import React, { useCallback, useEffect, useState } from 'react'
+import { useLocation } from '@reach/router'
import { Collapse } from 'react-collapse'
import { useWindowSize } from 'react-use'
-import Router from 'next/router'
-
import {
DesktopDescription,
Header,
@@ -36,24 +35,13 @@ export default function CommunitySection({
)
const { width } = useWindowSize()
+ const location = useLocation()
useEffect(() => {
- const updateVisibility = () => {
- const { hash } = window.location
-
- if (anchor && hash === `#${anchor}`) {
- setIsContentVisible(true)
- }
- }
-
- updateVisibility()
-
- Router.events.on('hashChangeComplete', updateVisibility)
-
- return () => {
- Router.events.off('hashChangeComplete', updateVisibility)
+ if (anchor && location.hash === `#${anchor}`) {
+ setIsContentVisible(true)
}
- }, [])
+ }, [location.hash])
useEffect(() => setIsTablet(width <= sizes.tablet), [width])
diff --git a/src/components/Community/data.json b/src/components/Community/data.json
index da37d8f93a..6f550868a2 100644
--- a/src/components/Community/data.json
+++ b/src/components/Community/data.json
@@ -1,7 +1,7 @@
{
"hero": {
- "pictureDesktop": "/static/img/community/banner.png",
- "pictureMobile": "/static/img/community/banner-mobile.png",
+ "pictureDesktop": "/img/community/banner.png",
+ "pictureMobile": "/img/community/banner-mobile.png",
"url": "https://www.mlprague.com/#schedule-saturday"
},
"section": {
@@ -49,21 +49,21 @@
"title": "Remote training with GitLab-CI and DVC",
"author": "Marcel Mikl and Bert Besser",
"date": "2020-01-28",
- "pictureUrl": "/static/img/community/ugc/codecentric.png"
+ "pictureUrl": "/img/community/ugc/codecentric.png"
},
{
"url": "https://martinfowler.com/articles/cd4ml.html",
"title": "Continuous Delivery for Machine Learning",
"author": "Danilo Sato, Arif Wider and Christoph Windheuser",
"date": "2019-09-20",
- "pictureUrl": "/static/img/community/ugc/fowler_icon.ico"
+ "pictureUrl": "/img/community/ugc/fowler_icon.ico"
},
{
"url": "https://towardsdatascience.com/mlops-reducing-the-technical-debt-of-machine-learning-dac528ef39de",
"title": "MLOps: Reducing the Technical Debt of Machine Learning",
"author": "Saurav Chakravorty",
"date": "2019-12-21",
- "pictureUrl": "/static/img/community/ugc/tds_logo.png"
+ "pictureUrl": "/img/community/ugc/tds_logo.png"
}
],
"events": [
@@ -80,7 +80,7 @@
"description": "PaweΕ RedzyΕski will talk about open source tools for versioning machine learning projects",
"city": "Prague",
"date": "2020-03-20",
- "pictureUrl": "/static/img/community/events/mlprague.jpg"
+ "pictureUrl": "/img/community/events/mlprague.jpg"
},
{
"url": "https://divops.org",
@@ -88,7 +88,7 @@
"description": "Elle O'Brien is talking about open source software in the growing field of MLOps.",
"city": "Remote",
"date": "2020-03-25",
- "pictureUrl": "/static/img/community/events/divops.jpg"
+ "pictureUrl": "/img/community/events/divops.jpg"
}
],
"stats": {
diff --git a/src/components/Community/index.js b/src/components/Community/index.js
index 07b2b61fdb..e711d01f63 100644
--- a/src/components/Community/index.js
+++ b/src/components/Community/index.js
@@ -1,6 +1,5 @@
import React from 'react'
-import Page from '../Page'
import Subscribe from '../Subscribe'
import CommunityContribute from './Contribute'
@@ -19,7 +18,7 @@ const themes = {
export default function Community() {
return (
-
+ <>
@@ -28,6 +27,6 @@ export default function Community() {
-
+ >
)
}
diff --git a/src/components/Community/styles.js b/src/components/Community/styles.js
index 8515ab1524..e9d76436d8 100644
--- a/src/components/Community/styles.js
+++ b/src/components/Community/styles.js
@@ -120,3 +120,21 @@ export const PageWrapper = styled.div`
padding-bottom: 0;
`}
`
+
+export const Button = styled.a`
+ display: block;
+ height: 38px;
+ border-radius: 4px;
+ font-size: 16px;
+ font-family: BrandonGrotesqueMed;
+ line-height: 38px;
+ text-decoration: none;
+ text-align: center;
+ color: ${({ theme: { color } }) => (color ? color : '#999')};
+ background-color: ${({ theme: { backgroundColor } }) =>
+ backgroundColor ? backgroundColor : '#ddd'};
+
+ &:hover {
+ opacity: 0.7;
+ }
+`
diff --git a/src/components/Diagram/index.js b/src/components/Diagram/index.js
index 6148dc1338..cdfcc069c6 100644
--- a/src/components/Diagram/index.js
+++ b/src/components/Diagram/index.js
@@ -5,6 +5,9 @@ import PropTypes from 'prop-types'
import { Element } from 'react-scroll'
import Slider from 'react-slick'
+import 'slick-carousel/slick/slick.css'
+import 'slick-carousel/slick/slick-theme.css'
+
import LocalLink from '../LocalLink'
import { OnlyDesktop, OnlyMobile } from '../../styles'
@@ -29,12 +32,7 @@ const LearnMore = ({ href }) => (
Learn more
-
+
)
@@ -130,7 +128,7 @@ export default class DiagramSection extends Component {
-
+
@@ -144,23 +142,17 @@ export default class DiagramSection extends Component {
-
+
-
+
diff --git a/src/components/Documentation/SidebarMenu/index.js b/src/components/DocLayout/SidebarMenu/index.js
similarity index 87%
rename from src/components/Documentation/SidebarMenu/index.js
rename to src/components/DocLayout/SidebarMenu/index.js
index 7253437034..bbbd346214 100644
--- a/src/components/Documentation/SidebarMenu/index.js
+++ b/src/components/DocLayout/SidebarMenu/index.js
@@ -5,10 +5,15 @@ import scrollIntoView from 'dom-scroll-into-view'
import PropTypes from 'prop-types'
import includes from 'lodash.includes'
+import 'perfect-scrollbar/css/perfect-scrollbar.css'
+
import DownloadButton from '../../DownloadButton'
import LocalLink from '../../LocalLink'
-import { getParentsListFromPath } from '../../../utils/sidebar'
+import {
+ getParentsListFromPath,
+ getPathWithSoruce
+} from '../../../utils/sidebar'
import { OnlyDesktop } from '../../../styles'
@@ -22,7 +27,7 @@ function SidebarMenuItem({ children, label, path, activePaths, onClick }) {
return (
<>
{
psRef.current.update()
- scrollIntoView(node, parent, { onlyScrollIfNeeded: true })
+
+ if (node && parent) {
+ scrollIntoView(node, parent, { onlyScrollIfNeeded: true })
+ }
+
setIsScrollHidden(false)
}, 400)
diff --git a/src/components/Documentation/SidebarMenu/styles.js b/src/components/DocLayout/SidebarMenu/styles.js
similarity index 95%
rename from src/components/Documentation/SidebarMenu/styles.js
rename to src/components/DocLayout/SidebarMenu/styles.js
index 9a0f7bedaf..aea066423c 100644
--- a/src/components/Documentation/SidebarMenu/styles.js
+++ b/src/components/DocLayout/SidebarMenu/styles.js
@@ -81,7 +81,7 @@ export const SectionLink = styled.a`
position: absolute;
width: 8px;
height: 5px;
- background: url('/static/img/triangle_dark.svg') no-repeat center center;
+ background: url('/img/triangle_dark.svg') no-repeat center center;
left: 0px;
top: 10px;
diff --git a/src/components/DocLayout/index.js b/src/components/DocLayout/index.js
new file mode 100644
index 0000000000..49b989aba5
--- /dev/null
+++ b/src/components/DocLayout/index.js
@@ -0,0 +1,77 @@
+/* global docsearch:readonly */
+
+import React, { useCallback, useEffect, useState } from 'react'
+import PropTypes from 'prop-types'
+import Hamburger from '../Hamburger'
+import SearchForm from '../SearchForm'
+import MainLayout from '../MainLayout'
+import SidebarMenu from './SidebarMenu'
+
+import { Container, Backdrop, SearchArea, Side, SideToggle } from './styles'
+
+import { structure } from '../../utils/sidebar'
+
+const SIDEBAR_MENU = 'sidebar-menu'
+
+function DocLayout({ children, ...restProps }) {
+ const [isMenuOpen, setIsMenuOpen] = useState(false)
+ const [isSearchAvaible, setIsSearchAvaible] = useState(false)
+
+ const toggleMenu = useCallback(() => setIsMenuOpen(!isMenuOpen), [isMenuOpen])
+
+ useEffect(() => {
+ try {
+ docsearch
+
+ setIsSearchAvaible(true)
+
+ if (docsearch && isSearchAvaible) {
+ docsearch({
+ apiKey: '755929839e113a981f481601c4f52082',
+ indexName: 'dvc',
+ inputSelector: '#doc-search',
+ debug: false // Set to `true` if you want to inspect the dropdown
+ })
+ }
+ } catch (ReferenceError) {
+ // nothing there
+ }
+ }, [isSearchAvaible])
+
+ return (
+
+
+
+
+
+
+
+
+
+ {isSearchAvaible && (
+
+
+
+ )}
+
+
+
+ {children}
+
+
+ )
+}
+
+DocLayout.propTypes = {
+ children: PropTypes.element.isRequired,
+ location: PropTypes.shape({
+ pathname: PropTypes.string.isRequired
+ })
+}
+
+export default DocLayout
diff --git a/src/components/DocLayout/styles.js b/src/components/DocLayout/styles.js
new file mode 100644
index 0000000000..a1a7d38bbc
--- /dev/null
+++ b/src/components/DocLayout/styles.js
@@ -0,0 +1,128 @@
+import styled from 'styled-components'
+
+import { media } from '../../styles'
+
+export const Container = styled.div`
+ display: flex;
+ flex-direction: row;
+ max-width: 1200px;
+ margin: 0 auto;
+ background: white;
+ z-index: 2;
+
+ &:before {
+ content: '';
+ display: block;
+ position: fixed;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ width: 50%;
+ background-color: #eef4f8;
+ z-index: -1;
+ pointer-events: none;
+ }
+`
+
+export const Backdrop = styled.div`
+ display: none;
+
+ ${media.phablet`
+ display: block;
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity .3s linear;
+
+ ${props =>
+ props.visible &&
+ `
+ content: '';
+ position: fixed;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ background-color: rgba(0, 0, 0, 0.4);
+ z-index: 1;
+ opacity: 1;
+ pointer-events: all;
+ `}
+ `};
+`
+
+export const Side = styled.div`
+ width: 280px;
+ background-color: #eef4f8;
+
+ @media only screen and (max-width: 1200px) {
+ padding-left: 15px;
+ }
+
+ ${media.phablet`
+ position: fixed;
+ display: block;
+ z-index: 2;
+ top: 78px;
+ bottom: 0;
+ left: 0;
+ right: 60px;
+ box-shadow: rgba(0, 0, 0, 0.14) 0px 0px 4px, rgba(0, 0, 0, 0.28) 0px 4px 8px;
+ transform: translateX(-110%);
+ transition: transform .35s ease;
+
+ ${props =>
+ props.isOpen &&
+ `
+ transform: translateX(0);
+ `}
+ `};
+`
+
+export const SearchArea = styled.div`
+ height: 60px;
+ display: flex;
+ align-items: center;
+ background-color: #eef4f8;
+ z-index: 10;
+ position: sticky;
+ top: 0;
+
+ ${media.phablet`
+ position: relative;
+ padding: 0 20px;
+ `};
+
+ form {
+ height: 40px;
+ }
+`
+
+export const SideToggle = styled.div`
+ display: none;
+ position: fixed;
+ z-index: 2;
+ left: 8px;
+ bottom: 20px;
+ width: 45px;
+ height: 45px;
+ border-radius: 50%;
+ background-color: rgba(255, 255, 255, 0.9);
+ box-shadow: 0 0px 9px 0 rgba(0, 0, 0, 0.15);
+ transition: transform 0.3s ease;
+ justify-content: center;
+ align-items: center;
+
+ ${media.phablet`
+ display: flex;
+
+ > div {
+ transform: scale(0.75);
+ }
+ `};
+
+ ${({ isMenuOpen }) =>
+ isMenuOpen &&
+ `
+ transform: translateX(calc(100vw - 60px));
+ `};
+`
diff --git a/src/components/Documentation/Markdown/index.js b/src/components/Documentation/Markdown/index.js
index 3ea4ab591c..e23898a27e 100644
--- a/src/components/Documentation/Markdown/index.js
+++ b/src/components/Documentation/Markdown/index.js
@@ -1,279 +1,147 @@
-import React from 'react'
+import React, { useCallback, useEffect, useRef } from 'react'
+import rehypeReact from 'rehype-react'
import PropTypes from 'prop-types'
-import ReactMarkdown from 'react-markdown'
import Collapsible from 'react-collapsible'
-import kebabCase from 'lodash.kebabcase'
-import Router from 'next/router'
+import 'github-markdown-css/github-markdown.css'
+
+import { navigate } from '@reach/router'
+
+import { getPathWithSoruce } from '../../../utils/sidebar'
import LocalLink from '../../LocalLink'
import Tooltip from '../../Tooltip'
import Tutorials from '../Tutorials'
-import { Light as SyntaxHighlighter } from 'react-syntax-highlighter'
-import { docco } from 'react-syntax-highlighter/dist/cjs/styles/hljs'
-import python from 'react-syntax-highlighter/dist/cjs/languages/hljs/python'
-import yaml from 'react-syntax-highlighter/dist/cjs/languages/hljs/yaml'
-import ini from 'react-syntax-highlighter/dist/cjs/languages/hljs/ini'
-import bash from 'react-syntax-highlighter/dist/cjs/languages/hljs/bash'
-import diff from 'react-syntax-highlighter/dist/cjs/languages/hljs/diff'
-import vim from 'react-syntax-highlighter/dist/cjs/languages/hljs/vim'
-import usage from './lang/usage'
-import dvc from './lang/dvc'
-import linker from './utils/remark-linker'
-
-import { PAGE_DOC } from '../../../consts'
-
import {
Button,
Content,
- ExternalLink,
GithubLink,
NavigationButtons,
TutorialsWrapper
} from './styles'
-SyntaxHighlighter.registerLanguage('dvc', dvc)
-SyntaxHighlighter.registerLanguage('python', python)
-SyntaxHighlighter.registerLanguage('usage', usage)
-SyntaxHighlighter.registerLanguage('yaml', yaml)
-SyntaxHighlighter.registerLanguage('ini', ini)
-SyntaxHighlighter.registerLanguage('bash', bash)
-SyntaxHighlighter.registerLanguage('vim', vim)
-SyntaxHighlighter.registerLanguage('diff', diff)
-
-function flatten(text, child) {
- return typeof child === 'string'
- ? text + child
- : React.Children.toArray(child.props.children).reduce(flatten, text)
-}
-
-const SLUG_REGEXP = /\s+{#([a-z0-9-]*[a-z0-9]+)}\s*$/
-
-function isTitleHasSlug(title) {
- return typeof title === 'string' && SLUG_REGEXP.test(title)
-}
-
-export function extractSlugFromTitle(title) {
- // extracts expressions like {#too-many-files} from the end of a title
- const meta = title.match(SLUG_REGEXP)
-
- if (meta) {
- return [title.substring(0, meta.index), meta[1]]
+const isInsideCodeBlock = elem => {
+ for (let el = elem; el && el !== document; el = el.parentNode) {
+ if (el.tagName === 'PRE') return true
+ if (el.tagName === 'ARTICLE') return false
}
- return [title, kebabCase(title)]
+ return false
}
-const HeadingRenderer = ({ level, children }) => {
- const content = React.Children.toArray(children)
- const text = children.reduce(flatten, '')
- let slug = kebabCase(text)
+function Details({ children }) {
+ const filteredChildren = children.filter(child => child !== '\n')
- const lastElement = content[content.length - 1].props.children
- if (isTitleHasSlug(lastElement)) {
- const [newValue, newSlug] = extractSlugFromTitle(lastElement)
- content.push(React.cloneElement(content.pop(), [], newValue))
- slug = newSlug
- }
-
- const anchor =
- level !== 1 ? (
-
-
-
- ) : null
- return React.createElement('h' + level, { id: slug }, anchor, content)
-}
-
-HeadingRenderer.propTypes = {
- level: PropTypes.number.isRequired,
- children: PropTypes.node.isRequired
-}
-
-const HtmlRenderer = props => {
- if (props.tag !== 'details' && props.tag !== 'abbr') {
- return React.createElement(props.tag, {}, props.children)
- } else if (props.tag === 'details') {
- const text = props.children[0].props.children[0]
- return (
-
- {props.children.slice(1)}
-
- )
- } else if (props.tag === 'abbr') {
- const text = props.children[0]
- const key = props.children[0].key
- return
- }
-}
-
-const CodeBlock = ({ value, language }) => {
- const dvcStyle = Object.assign({}, docco)
- dvcStyle['hljs-comment'] = { color: '#999' }
- dvcStyle['hljs-meta'] = { color: '#333', fontSize: '14px' }
- dvcStyle['hljs']['padding'] = '0.5em 0.5em 0.5em 2em'
- dvcStyle['hljs-skipped'] = { userSelect: 'none' }
+ const text = filteredChildren[0].props.children[0]
return (
-
- {value}
-
+
+ {filteredChildren.slice(1)}
+
)
}
-CodeBlock.propTypes = {
- language: PropTypes.string.isRequired,
- value: PropTypes.node.isRequired
+Details.propTypes = {
+ children: PropTypes.node
}
-const Link = ({ children, href, ...props }) => {
- const externalLink = href.match(/^(\/\/|http(s)?:\/\/)/)
- const showIcon =
- externalLink && children && typeof children[0].props.children === 'string'
-
- const modifiedProps = externalLink
- ? { ...props, target: '_blank', rel: 'noreferrer noopener' }
- : props
-
- if (showIcon) {
- return (
-
- {children}
-
- )
- }
-
- return (
-
- {children}
-
- )
+function ABBR({ children }) {
+ return
}
-Link.propTypes = {
- children: PropTypes.node.isRequired,
- href: PropTypes.string.isRequired
+ABBR.propTypes = {
+ children: PropTypes.node
}
-export default class Markdown extends React.PureComponent {
- constructor() {
- super()
- this.touchstartX = 0
- this.touchendX = 0
- this.isCodeBlock = false
- }
-
- componentDidMount() {
- document.addEventListener('touchstart', this.onTouchStart, false)
- document.addEventListener('touchend', this.onTouchEnd, false)
- }
-
- componentWillUnmount() {
- document.removeEventListener('touchstart', this.onTouchStart)
- document.removeEventListener('touchend', this.onTouchEnd)
- }
-
- isInsideCodeBlock = elem => {
- for (let el = elem; el && el !== document; el = el.parentNode) {
- if (el.tagName === 'PRE') return true
- if (el.tagName === 'ARTICLE') return false
+const renderAst = new rehypeReact({
+ createElement: React.createElement,
+ components: { details: Details, abbr: ABBR }
+}).Compiler
+
+export default function Markdown({
+ htmlAst,
+ prev,
+ next,
+ tutorials,
+ githubLink
+}) {
+ const touchstartXRef = useRef(0)
+ const touchendXRef = useRef(0)
+ const isCodeBlockRef = useRef(false)
+
+ const handleSwipeGesture = useCallback(() => {
+ if (isCodeBlockRef.current) return
+
+ if (touchstartXRef.current - touchendXRef.current > 100) {
+ navigate(next)
}
- return false
- }
- onTouchStart = e => {
- this.isCodeBlock = this.isInsideCodeBlock(e.target)
- this.touchstartX = event.changedTouches[0].screenX
- }
+ if (touchendXRef.current - touchstartXRef.current > 100) {
+ navigate(prev)
+ }
+ }, [prev, next])
- onTouchEnd = () => {
- this.touchendX = event.changedTouches[0].screenX
- this.handleSwipeGesture()
- }
+ const onTouchStart = useCallback(e => {
+ isCodeBlockRef.current = isInsideCodeBlock(e.target)
+ touchstartXRef.current = event.changedTouches[0].screenX
+ }, [])
- handleSwipeGesture = () => {
- if (this.isCodeBlock) return
- const { prev, next } = this.props
+ const onTouchEnd = useCallback(() => {
+ touchendXRef.current = event.changedTouches[0].screenX
+ handleSwipeGesture()
+ }, [])
- if (this.touchstartX - this.touchendX > 100) {
- Router.push({ asPath: PAGE_DOC, pathname: next })
- }
+ useEffect(() => {
+ document.addEventListener('touchstart', onTouchStart, false)
+ document.addEventListener('touchend', onTouchEnd, false)
- if (this.touchendX - this.touchstartX > 100) {
- Router.push({ asPath: PAGE_DOC, pathname: prev })
+ return () => {
+ document.removeEventListener('touchstart', onTouchStart)
+ document.removeEventListener('touchend', onTouchEnd)
}
- }
+ }, [])
- render() {
- const { markdown, githubLink, prev, next, tutorials } = this.props
-
- return (
-
- {tutorials && (
-
-
-
+ return (
+
+ {tutorials && (
+
+
+
+ )}
+
+ Edit on GitHub
+
+ {renderAst(htmlAst)}
+
+ {prev ? (
+
+
+ Prev
+
+ ) : (
+
)}
-
- Edit on GitHub
-
-
-
- {prev ? (
-
-
- Prev
-
- ) : (
-
- )}
- {next ? (
-
- Next
-
-
- ) : (
-
- )}
-
-
- )
- }
+ {next ? (
+
+ Next
+
+
+ ) : (
+
+ )}
+
+
+ )
}
Markdown.propTypes = {
- markdown: PropTypes.string.isRequired,
+ htmlAst: PropTypes.object.isRequired,
githubLink: PropTypes.string.isRequired,
tutorials: PropTypes.object,
prev: PropTypes.string,
diff --git a/src/components/Documentation/Markdown/styles.js b/src/components/Documentation/Markdown/styles.js
index 4fe58c8603..4dc7316a12 100644
--- a/src/components/Documentation/Markdown/styles.js
+++ b/src/components/Documentation/Markdown/styles.js
@@ -31,6 +31,131 @@ export const Content = styled.article`
animation-duration: 1s;
animation-fill-mode: both;
animation-name: fadeIn;
+
+ a[target='_blank']:after {
+ position: relative;
+ top: 1px;
+ right: 0;
+ width: 12px;
+ height: 12px;
+ margin-left: 1px;
+ content: url(/img/external-link.svg);
+ }
+
+ pre[class*='language-'] {
+ background: #40354d;
+ color: #ccc;
+
+ .token.line {
+ font-weight: bold;
+ color: #a0a0a0;
+ }
+
+ .token.comment {
+ font-weight: normal;
+ color: #a0a0a0;
+ }
+
+ .token.input {
+ user-select: none;
+ }
+
+ .token.comment,
+ .token.block-comment,
+ .token.prolog,
+ .token.doctype,
+ .token.cdata {
+ color: #999;
+ }
+
+ .token.url,
+ .token.constant,
+ .token.operator,
+ .token.punctuation {
+ color: #a0a0a0;
+ }
+
+ .token.property,
+ .token.tag,
+ .token.boolean,
+ .token.function-name,
+ .token.symbol,
+ .token.deleted {
+ color: #4badd2;
+ }
+
+ .token.function {
+ color: #ae41bb;
+ }
+
+ .token.number,
+ .token.attr-name,
+ .token.string,
+ .token.char,
+ .token.builtin,
+ .token.inserted {
+ color: #219161;
+ }
+
+ .token.entity,
+ .token.variable {
+ color: #a67f59;
+ }
+
+ .token.class-name {
+ color: #0086b3;
+ }
+
+ .token.dvc {
+ color: #56b1d0;
+ }
+
+ .token.usage,
+ .token.git {
+ color: #e9836e;
+ }
+
+ .token.command,
+ .token.selector,
+ .token.atrule,
+ .token.attr-value,
+ .token.keyword {
+ color: #e4b872;
+ }
+
+ .token.regex,
+ .token.important {
+ color: #b68;
+ }
+
+ .token.parameter {
+ color: #a0a0a0;
+ }
+
+ .token.function-variable {
+ color: #7ece42;
+ }
+
+ .token.important {
+ font-weight: normal;
+ }
+
+ .token.bold {
+ font-weight: bold;
+ }
+
+ .token.italic {
+ font-style: italic;
+ }
+
+ .token.entity {
+ cursor: help;
+ }
+
+ .token.namespace {
+ opacity: 0.7;
+ }
+ }
}
.Collapsible {
@@ -55,7 +180,7 @@ export const Content = styled.article`
right: 0;
width: 20px;
height: 20px;
- background-image: url('/static/img/click.png');
+ background-image: url('/img/click.png');
content: '';
font-family: monospace;
transition: transform 200ms;
@@ -126,7 +251,7 @@ export const Button = styled.a`
i {
display: inline-block;
- background-image: url(/static/img/arrow.svg);
+ background-image: url(/img/arrow.svg);
background-size: contain;
background-position: center;
background-repeat: no-repeat;
@@ -185,7 +310,7 @@ export const GithubLink = styled(LightButton)`
}
i {
- background-image: url(/static/img/github_icon.svg);
+ background-image: url(/img/github_icon.svg);
}
`
@@ -197,6 +322,6 @@ export const ExternalLink = styled.a`
width: 12px;
height: 12px;
margin-left: 1px;
- content: url(/static/img/external-link.svg);
+ content: url(/img/external-link.svg);
}
`
diff --git a/src/components/Documentation/Markdown/utils/remark-linker.js b/src/components/Documentation/Markdown/utils/remark-linker.js
deleted file mode 100644
index 36a9d24371..0000000000
--- a/src/components/Documentation/Markdown/utils/remark-linker.js
+++ /dev/null
@@ -1,49 +0,0 @@
-;`use strict`
-
-import visit from 'unist-util-visit'
-
-import { getItemByPath } from '../../../../utils/sidebar'
-
-const DVC_REGEXP = /dvc\s+[a-z][a-z-.]*/
-const COMMAND_REGEXP = /^[a-z][a-z-]*$/
-const COMMAND_ROOT = '/doc/command-reference/'
-
-function linker() {
- function transformer(tree) {
- visit(tree, 'inlineCode', function(node, index, parent) {
- if (parent.type !== 'link' && DVC_REGEXP.test(node.value)) {
- let parts = node.value.split(/\s+/)
- let url
-
- const hasThirdSegment = parts[2] && COMMAND_REGEXP.test(parts[2])
- const isCommandPageExists = getItemByPath(`${COMMAND_ROOT}${parts[1]}`)
- const isSubcommandPageExists =
- isCommandPageExists &&
- hasThirdSegment &&
- getItemByPath(`${COMMAND_ROOT}${parts[1]}/${parts[2]}`)
-
- if (isSubcommandPageExists) {
- url = `${COMMAND_ROOT}${parts[1]}/${parts[2]}`
- } else if (isCommandPageExists && hasThirdSegment) {
- url = `${COMMAND_ROOT}${parts[1]}#${parts[2]}`
- } else if (isCommandPageExists) {
- url = `${COMMAND_ROOT}${parts[1]}`
- }
-
- if (url) {
- parent.children[index] = {
- type: 'link',
- url: url,
- children: [node],
- position: node.position
- }
- }
- }
- })
- return tree
- }
-
- return transformer
-}
-
-export default linker
diff --git a/src/components/Documentation/RightPanel/index.js b/src/components/Documentation/RightPanel/index.js
index 804c868042..e270a3805e 100644
--- a/src/components/Documentation/RightPanel/index.js
+++ b/src/components/Documentation/RightPanel/index.js
@@ -91,7 +91,9 @@ export default class RightPanel extends React.PureComponent {
updateHeadingsPosition = () => {
const coordinates = this.props.headings.reduce((result, { slug }) => {
- return { ...result, [document.getElementById(slug).offsetTop]: slug }
+ const headingElement = document.getElementById(slug)
+
+ return { ...result, [headingElement && headingElement.offsetTop]: slug }
}, {})
const height = this.root.offsetHeight
diff --git a/src/components/Documentation/RightPanel/styles.js b/src/components/Documentation/RightPanel/styles.js
index bcebe20874..0827aa721a 100644
--- a/src/components/Documentation/RightPanel/styles.js
+++ b/src/components/Documentation/RightPanel/styles.js
@@ -58,13 +58,13 @@ export const ExternalButton = styled(LightButton)`
export const GithubButton = styled(ExternalButton)`
i {
- background-image: url(/static/img/github_icon.svg);
+ background-image: url(/img/github_icon.svg);
}
`
export const DiscordButton = styled(ExternalButton)`
i {
- background-image: url(/static/img/discord.svg);
+ background-image: url(/img/discord.svg);
width: 1.2em;
height: 1.2em;
}
diff --git a/src/components/Documentation/Tutorials/styles.js b/src/components/Documentation/Tutorials/styles.js
index 1a92f74cc3..9071315bac 100644
--- a/src/components/Documentation/Tutorials/styles.js
+++ b/src/components/Documentation/Tutorials/styles.js
@@ -30,7 +30,7 @@ export const KatacodaButton = styled(ExternalButton)`
white-space: nowrap;
i {
- background-image: url(/static/img/katacoda_grey_small.png);
+ background-image: url(/img/katacoda_grey_small.png);
width: 24px;
height: 24px;
}
diff --git a/src/components/Documentation/index.js b/src/components/Documentation/index.js
index 6e2c279064..dc735ea771 100644
--- a/src/components/Documentation/index.js
+++ b/src/components/Documentation/index.js
@@ -1,137 +1,35 @@
-/* global docsearch:readonly */
-
-import React, { useCallback, useEffect, useMemo, useState } from 'react'
+import React from 'react'
import PropTypes from 'prop-types'
-import Router from 'next/router'
-import Page from '../Page'
-import Hamburger from '../Hamburger'
-import SearchForm from '../SearchForm'
-import SidebarMenu from './SidebarMenu'
-import Markdown, { extractSlugFromTitle } from './Markdown'
+import Markdown from './Markdown'
import RightPanel from './RightPanel'
-import { structure } from '../../utils/sidebar'
-
-import { Backdrop, Container, SearchArea, Side, SideToggle } from './styles'
-
-const ROOT_ELEMENT = 'bodybag'
-const SIDEBAR_MENU = 'sidebar-menu'
-
-const parseHeadings = text => {
- const headingRegex = /\n(## \s*)(.*)/g
- const matches = []
- let match
- do {
- match = headingRegex.exec(text)
- if (match) {
- const [title, slug] = extractSlugFromTitle(match[2])
- matches.push({
- text: title,
- slug: slug
- })
- }
- } while (match)
-
- return matches
-}
-
-export default function Documentation({
- source,
- path,
- next,
- prev,
- tutorials,
- markdown
-}) {
- const headings = useMemo(() => parseHeadings(markdown))
- const [isMenuOpen, setIsMenuOpen] = useState(false)
- const [isSearchAvaible, setIsSearchAvaible] = useState(false)
-
- const toggleMenu = useCallback(() => setIsMenuOpen(!isMenuOpen), [isMenuOpen])
-
- useEffect(() => {
- try {
- docsearch
-
- setIsSearchAvaible(true)
+import { getItemByPath } from '../../utils/sidebar'
- if (isSearchAvaible) {
- docsearch({
- apiKey: '755929839e113a981f481601c4f52082',
- indexName: 'dvc',
- inputSelector: '#doc-search',
- debug: false // Set to `true` if you want to inspect the dropdown
- })
- }
- } catch (ReferenceError) {
- // nothing there
- }
- }, [isSearchAvaible])
-
- useEffect(() => {
- const handleRouteChange = () => {
- const rootElement = document.getElementById(ROOT_ELEMENT)
- if (rootElement) {
- rootElement.scrollTop = 0
- }
- }
-
- Router.events.on('routeChangeComplete', handleRouteChange)
-
- return () => Router.events.off('routeChangeComplete', handleRouteChange)
- }, [])
-
- const githubLink = `https://github.com/iterative/dvc.org/blob/master/public${source}`
+export default function Documentation({ htmlAst, path, headings }) {
+ const { source, prev, next, tutorials } = getItemByPath(path)
+ const githubLink = `https://github.com/iterative/dvc.org/blob/master/Ρontent${source}`
return (
-
-
-
-
-
-
-
-
-
- {isSearchAvaible && (
-
-
-
- )}
-
-
-
-
-
-
-
-
-
+ <>
+
+
+ >
)
}
Documentation.propTypes = {
- source: PropTypes.string,
path: PropTypes.string,
- next: PropTypes.string,
- prev: PropTypes.string,
- tutorials: PropTypes.object,
- markdown: PropTypes.string,
- errorCode: PropTypes.number
+ headings: PropTypes.array,
+ htmlAst: PropTypes.object
}
diff --git a/src/components/Documentation/styles.js b/src/components/Documentation/styles.js
index 0332167b22..48213b3f65 100644
--- a/src/components/Documentation/styles.js
+++ b/src/components/Documentation/styles.js
@@ -1,132 +1,5 @@
import styled from 'styled-components'
-import { media } from '../../styles'
-
-export const Container = styled.div`
- display: flex;
- flex-direction: row;
- max-width: 1200px;
- margin: 0 auto;
- background: white;
- z-index: 2;
-
- &:before {
- content: '';
- display: block;
- position: fixed;
- top: 0;
- left: 0;
- bottom: 0;
- width: 50%;
- background-color: #eef4f8;
- z-index: -1;
- pointer-events: none;
- }
-`
-
-export const Backdrop = styled.div`
- display: none;
-
- ${media.phablet`
- display: block;
- opacity: 0;
- pointer-events: none;
- transition: opacity .3s linear;
-
- ${props =>
- props.visible &&
- `
- content: '';
- position: fixed;
- top: 0;
- left: 0;
- bottom: 0;
- right: 0;
- background-color: rgba(0, 0, 0, 0.4);
- z-index: 1;
- opacity: 1;
- pointer-events: all;
- `}
- `};
-`
-
-export const Side = styled.div`
- width: 280px;
- background-color: #eef4f8;
-
- @media only screen and (max-width: 1200px) {
- padding-left: 15px;
- }
-
- ${media.phablet`
- position: fixed;
- display: block;
- z-index: 2;
- top: 78px;
- bottom: 0;
- left: 0;
- right: 60px;
- box-shadow: rgba(0, 0, 0, 0.14) 0px 0px 4px, rgba(0, 0, 0, 0.28) 0px 4px 8px;
- transform: translateX(-110%);
- transition: transform .35s ease;
-
- ${props =>
- props.isOpen &&
- `
- transform: translateX(0);
- `}
- `};
-`
-
-export const SearchArea = styled.div`
- height: 60px;
- display: flex;
- align-items: center;
- background-color: #eef4f8;
- z-index: 10;
- position: sticky;
- top: 0;
-
- ${media.phablet`
- position: relative;
- padding: 0 20px;
- `};
-
- form {
- height: 40px;
- }
-`
-
-export const SideToggle = styled.div`
- display: none;
- position: fixed;
- z-index: 2;
- left: 8px;
- bottom: 20px;
- width: 45px;
- height: 45px;
- border-radius: 50%;
- background-color: rgba(255, 255, 255, 0.9);
- box-shadow: 0 0px 9px 0 rgba(0, 0, 0, 0.15);
- transition: transform 0.3s ease;
- justify-content: center;
- align-items: center;
-
- ${media.phablet`
- display: flex;
-
- > div {
- transform: scale(0.75);
- }
- `};
-
- ${({ isMenuOpen }) =>
- isMenuOpen &&
- `
- transform: translateX(calc(100vw - 60px));
- `};
-`
-
export const LightButton = styled.a`
display: inline-flex;
justify-content: center;
diff --git a/src/components/DownloadButton/index.js b/src/components/DownloadButton/index.js
index 75138f79a3..675921dc77 100644
--- a/src/components/DownloadButton/index.js
+++ b/src/components/DownloadButton/index.js
@@ -168,7 +168,7 @@ export default class DownloadButton extends Component {
diff --git a/src/components/Features/index.js b/src/components/Features/index.js
index 316d695c96..b762bbebca 100644
--- a/src/components/Features/index.js
+++ b/src/components/Features/index.js
@@ -1,6 +1,5 @@
import React from 'react'
-import Page from '../Page'
import Hero from '../Hero'
import FeaturesHero from '../FeaturesHero'
import TrySection from '../TrySection'
@@ -9,7 +8,7 @@ import { Container, Description, Feature, Features, Icon, Name } from './styles'
export default function FeaturesPage() {
return (
-
+ <>
@@ -18,7 +17,7 @@ export default function FeaturesPage() {
@@ -35,7 +34,7 @@ export default function FeaturesPage() {
@@ -49,10 +48,7 @@ export default function FeaturesPage() {
-
+
Reproducible
@@ -65,7 +61,7 @@ export default function FeaturesPage() {
@@ -81,7 +77,7 @@ export default function FeaturesPage() {
-
+
Metric tracking
@@ -93,7 +89,7 @@ export default function FeaturesPage() {
@@ -108,7 +104,7 @@ export default function FeaturesPage() {
@@ -124,7 +120,7 @@ export default function FeaturesPage() {
@@ -140,7 +136,7 @@ export default function FeaturesPage() {
@@ -155,6 +151,6 @@ export default function FeaturesPage() {
-
+ >
)
}
diff --git a/src/components/Footer/index.js b/src/components/Footer/index.js
index 38f8443f6d..78acc87068 100644
--- a/src/components/Footer/index.js
+++ b/src/components/Footer/index.js
@@ -3,6 +3,8 @@ import PropTypes from 'prop-types'
import LocalLink from '../LocalLink'
+import { getFirstPage } from '../../utils/sidebar'
+
import {
Column,
Columns,
@@ -16,6 +18,8 @@ import {
Wrapper
} from './styles'
+const docsPage = getFirstPage()
+
const SocialLink = ({ src, href, children }) => (
{children}
@@ -35,7 +39,7 @@ export default function Footer(props) {
Community
-
+
Documentation
@@ -75,10 +79,7 @@ export default function Footer(props) {
Company
Blog
-
+
Iterative.ai
Privacy Policy
@@ -88,18 +89,18 @@ export default function Footer(props) {
Social
Twitter
GitHub
-
+
Discord
diff --git a/src/components/GithubLine/index.js b/src/components/GithubLine/index.js
index 8a9db20dba..8094c93da4 100644
--- a/src/components/GithubLine/index.js
+++ b/src/components/GithubLine/index.js
@@ -17,14 +17,10 @@ export default function GithubLine() {
return (
-
+
Weβre on
GitHub
- {' '}
+ {' '}
{count}
)
diff --git a/src/components/HamburgerMenu/index.js b/src/components/HamburgerMenu/index.js
index 44d0ea2f53..1dcc20da50 100644
--- a/src/components/HamburgerMenu/index.js
+++ b/src/components/HamburgerMenu/index.js
@@ -5,6 +5,8 @@ import LocalLink from '../LocalLink'
import { logEvent } from '../../utils/ga'
+import { getFirstPage } from '../../utils/sidebar'
+
import {
Button,
Image,
@@ -20,6 +22,8 @@ import {
Wrapper
} from './styles'
+const docsPage = getFirstPage()
+
export default function HamburgerMenu() {
const [menu, setMenu] = useState(false)
const [clicked, setClicked] = useState(false)
@@ -52,7 +56,7 @@ export default function HamburgerMenu() {
-
+
@@ -89,7 +93,7 @@ export default function HamburgerMenu() {
as={ImageLink}
onClick={itemClick('community')}
>
-
+
Meet Us
-
+
Contribute
-
+
Learn
-
+
Events
@@ -129,7 +133,7 @@ export default function HamburgerMenu() {
rel="noreferrer noopener"
click={itemClick('mail')}
>
-
+
E-Mail
-
+
GitHub
-
+
Discord
-
+
Twitter
diff --git a/src/components/Home/index.js b/src/components/Home/index.js
index 2593eabbc4..331a2affc5 100644
--- a/src/components/Home/index.js
+++ b/src/components/Home/index.js
@@ -1,7 +1,6 @@
import React from 'react'
import LearnMore from '../LearnMore'
-import Page from '../Page'
import Hero from '../Hero'
import LandingHero from '../LandingHero'
import Diagram from '../Diagram'
@@ -13,7 +12,7 @@ import { LearnMoreSection } from './styles'
export default function HomePage() {
return (
-
+ <>
@@ -25,6 +24,6 @@ export default function HomePage() {
-
+ >
)
}
diff --git a/src/components/LandingHero/index.js b/src/components/LandingHero/index.js
index ef9ca7f04c..a76338ced2 100644
--- a/src/components/LandingHero/index.js
+++ b/src/components/LandingHero/index.js
@@ -81,7 +81,7 @@ export default class LandingHero extends Component {
{
+ const location = useLocation()
useEffect(() => {
- if (!window.GA_INITIALIZED) {
- initGA()
- window.GA_INITIALIZED = true
+ if (location.hash) {
+ const node = document.querySelector(location.hash)
+
+ if (node) {
+ node.scrollIntoView()
+ }
+ } else {
+ document
+ .getElementById('bodybag')
+ .scrollTo({ top: 0, behavior: 'smooth' })
}
+ }, [location.href])
+}
+
+export default function Layout(props) {
+ let LayoutComponent = MainLayout
+
+ useAnchorNavigation()
- // Apperently next/head is using promises and because of that
- // it updates after page is already rendered and useEffect is called,
- // because of that we use rAF to place GA call after head update
- requestAnimationFrame(() => logPageView())
- }, [router.asPath])
+ if (!props.pageContext.is404 && /^\/doc/.test(props.location.pathname)) {
+ LayoutComponent = DocLayout
+ }
return (
-
-
-
-
- {children}
-
-
-
-
+ <>
+
+
+ >
)
}
Layout.propTypes = {
- children: PropTypes.node.isRequired,
- enableSmoothScroll: PropTypes.bool,
- isDocPage: PropTypes.bool
+ location: PropTypes.shape({
+ pathname: PropTypes.string.isRequired
+ }),
+ pageContext: PropTypes.shape({
+ is404: PropTypes.bool
+ })
}
diff --git a/src/components/LearnMore/index.js b/src/components/LearnMore/index.js
index 541fee1e57..f4b2742837 100644
--- a/src/components/LearnMore/index.js
+++ b/src/components/LearnMore/index.js
@@ -20,7 +20,7 @@ export default function LearnMore() {
return (
-
+
Learn more
diff --git a/src/components/LocalLink/index.js b/src/components/LocalLink/index.js
index b3badcae7e..33010d55de 100644
--- a/src/components/LocalLink/index.js
+++ b/src/components/LocalLink/index.js
@@ -1,28 +1,17 @@
import React from 'react'
import PropTypes from 'prop-types'
-import NextLink from 'next/link'
+import GatsbyLink from 'gatsby-link'
-import { PAGE_DOC } from '../../consts'
-
-export default function LocalLink({
- children,
- as: Component,
- href,
- ...restProps
-}) {
- const nextProps = href.match(/^\/doc/)
- ? { href: PAGE_DOC, as: href }
- : { href }
-
- return (
-
- {Component ? (
- {children}
- ) : (
- {children}
- )}
-
+export default function LocalLink({ children, as: SC, href, ...restProps }) {
+ return SC ? (
+
+ {children}
+
+ ) : (
+
+ {children}
+
)
}
diff --git a/src/components/MainLayout/index.js b/src/components/MainLayout/index.js
new file mode 100644
index 0000000000..221e189a48
--- /dev/null
+++ b/src/components/MainLayout/index.js
@@ -0,0 +1,33 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+
+import TopMenu from '../TopMenu'
+import Footer from '../Footer'
+import HamburgerMenu from '../HamburgerMenu'
+
+import { Wrapper, Bodybag, ModalRoot } from './styles'
+export default function MainLayout({
+ children,
+ enableSmoothScroll,
+ isDocPage = false
+}) {
+ return (
+ <>
+
+
+
+
+ {children}
+
+
+
+
+ >
+ )
+}
+
+MainLayout.propTypes = {
+ children: PropTypes.node.isRequired,
+ enableSmoothScroll: PropTypes.bool,
+ isDocPage: PropTypes.bool
+}
diff --git a/src/components/Layout/styles.js b/src/components/MainLayout/styles.js
similarity index 100%
rename from src/components/Layout/styles.js
rename to src/components/MainLayout/styles.js
diff --git a/src/components/Nav/index.js b/src/components/Nav/index.js
index 7e97e6c329..923252303f 100644
--- a/src/components/Nav/index.js
+++ b/src/components/Nav/index.js
@@ -4,10 +4,14 @@ import PropTypes from 'prop-types'
import LocalLink from '../LocalLink'
import { logEvent } from '../../utils/ga'
+import { getFirstPage } from '../../utils/sidebar'
+
+const docsPage = getFirstPage()
import {
Dropdown,
DropdownInset,
+ DropdownRootLink,
DropdownLink,
DropdownWrapper,
GetStartedButton,
@@ -30,7 +34,7 @@ export default function Nav({ mobile = false }) {
Features
logEvent('menu', 'doc')}
>
@@ -45,7 +49,7 @@ export default function Nav({ mobile = false }) {
logEvent('menu', 'community')}
>
Community
@@ -95,10 +99,10 @@ export default function Nav({ mobile = false }) {
target="_blank"
rel="noreferrer noopener"
>
-
+
-
+
-
- {children}
- >
- )
- }
-}
-
-Page.propTypes = {
- children: PropTypes.node.isRequired
-}
diff --git a/src/components/PageWrapper/index.js b/src/components/PageWrapper/index.js
new file mode 100644
index 0000000000..8b1696a842
--- /dev/null
+++ b/src/components/PageWrapper/index.js
@@ -0,0 +1,8 @@
+/* eslint-disable react/prop-types */
+
+import React from 'react'
+import Layout from '../Layout'
+
+export default function PageWrapper({ element, props }) {
+ return {element}
+}
diff --git a/src/components/PromoSection/index.js b/src/components/PromoSection/index.js
index 76e21f6767..8534dadcac 100644
--- a/src/components/PromoSection/index.js
+++ b/src/components/PromoSection/index.js
@@ -12,7 +12,7 @@ export default function PromoSection() {
return (
-
+
For data scientists, by data scientists
-
+
)
diff --git a/src/components/PromoSection/styles.js b/src/components/PromoSection/styles.js
index 2908bd06fb..a97b321371 100644
--- a/src/components/PromoSection/styles.js
+++ b/src/components/PromoSection/styles.js
@@ -59,7 +59,7 @@ export const Button = styled.a`
color: #ffffff;
background-color: #945dd6;
- background: url('/static/img/arrow_right_white.svg') right center no-repeat;
+ background: url('/img/arrow_right_white.svg') right center no-repeat;
background-position-x: 147px;
transition: 0.2s background-color ease-out;
@@ -76,7 +76,7 @@ export const Button = styled.a`
background-color: #ffffff;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.21);
- background-image: url('/static/img/arrow_right_dark.svg');
+ background-image: url('/img/arrow_right_dark.svg');
transition: 0.2s background-color ease-out;
&:hover {
diff --git a/src/components/SEO/index.js b/src/components/SEO/index.js
new file mode 100644
index 0000000000..5826a24a00
--- /dev/null
+++ b/src/components/SEO/index.js
@@ -0,0 +1,137 @@
+import PropTypes from 'prop-types'
+import { graphql, useStaticQuery } from 'gatsby'
+import React from 'react'
+import Helmet from 'react-helmet'
+
+function SEO({
+ title,
+ defaultMetaTitle,
+ description,
+ keywords,
+ image,
+ lang,
+ meta
+}) {
+ const { site } = useStaticQuery(
+ graphql`
+ query {
+ site {
+ siteMetadata {
+ title
+ description
+ keywords
+ siteUrl
+ }
+ }
+ }
+ `
+ )
+
+ const metaDescription = description || site.siteMetadata.description
+
+ const metaKeywords = keywords || site.siteMetadata.keywords
+
+ const metaTitle = title && !defaultMetaTitle ? title : site.siteMetadata.title
+
+ const metaImage = image || '/social-share.png'
+
+ const defaultMeta = [
+ {
+ property: 'description',
+ content: metaDescription
+ },
+ {
+ property: 'keywords',
+ content: metaKeywords
+ },
+ {
+ property: 'og:title',
+ content: metaTitle
+ },
+ {
+ property: 'og:description',
+ content: metaDescription
+ },
+ {
+ property: 'og:type',
+ content: 'website'
+ },
+ {
+ property: 'og:image',
+ content: metaImage
+ },
+ {
+ property: 'og:image:secure_url',
+ content: metaImage
+ },
+ {
+ name: 'twitter:card',
+ content: `summary_large_image`
+ },
+ {
+ name: 'twitter:title',
+ content: metaTitle
+ },
+ {
+ name: 'twitter:description',
+ content: metaDescription
+ },
+ {
+ name: 'twitter:image',
+ content: encodeURI(`${site.siteMetadata.siteUrl}${metaImage}`)
+ }
+ ]
+
+ return (
+
+ )
+}
+
+SEO.propTypes = {
+ title: PropTypes.string,
+ defaultMetaTitle: PropTypes.bool,
+ description: PropTypes.string,
+ keywords: PropTypes.array,
+ image: PropTypes.string,
+ lang: PropTypes.string,
+ meta: PropTypes.array
+}
+
+SEO.defaultProps = {
+ lang: `en`,
+ meta: []
+}
+
+export default SEO
diff --git a/src/components/SearchForm/styles.js b/src/components/SearchForm/styles.js
index 6022840c28..ba988dc67b 100644
--- a/src/components/SearchForm/styles.js
+++ b/src/components/SearchForm/styles.js
@@ -15,7 +15,7 @@ export const Input = styled.input`
border: solid 1px #dbe4ea;
padding-left: 48px;
padding-right: 24px;
- background-image: url('/static/img/search.svg');
+ background-image: url('/img/search.svg');
background-repeat: no-repeat;
background-position: 15px center;
font-size: 16px;
diff --git a/src/components/Subscribe/index.js b/src/components/Subscribe/index.js
index a35b315921..ea992e3cba 100644
--- a/src/components/Subscribe/index.js
+++ b/src/components/Subscribe/index.js
@@ -7,14 +7,14 @@ import { Container, Glyph, SubscribeContainer, Title, Wrapper } from './styles'
export default function Subscribe() {
return (
-
+
Subscribe for updates. We won't spam you.
-
+
)
}
diff --git a/src/components/Support/index.js b/src/components/Support/index.js
index 73b5c48e08..397926b3b0 100644
--- a/src/components/Support/index.js
+++ b/src/components/Support/index.js
@@ -1,6 +1,5 @@
import React from 'react'
-import Page from '../Page'
import Hero from '../Hero'
import TrySection from '../TrySection'
import Popover from '../Popover'
@@ -25,7 +24,7 @@ import {
export default function SupportPage() {
return (
-
+ <>
Questions, feedback, or just need to get in touch?
@@ -35,7 +34,7 @@ export default function SupportPage() {
-
+
Slack-like Chat
@@ -70,7 +69,7 @@ export default function SupportPage() {
-
+
Bugs & Features
@@ -89,7 +88,7 @@ export default function SupportPage() {
-
+
Forum
@@ -105,7 +104,7 @@ export default function SupportPage() {
-
+
Email
@@ -124,6 +123,6 @@ export default function SupportPage() {
-
+ >
)
}
diff --git a/src/components/Support/styles.js b/src/components/Support/styles.js
index 62e275ec38..475895ed33 100644
--- a/src/components/Support/styles.js
+++ b/src/components/Support/styles.js
@@ -126,7 +126,7 @@ export const DiscrodWidget = styled.img`
width: 50px;
height: 50px;
cursor: pointer;
- mask-image: url('/static/img/support/discord.svg');
+ mask-image: url('/img/support/discord.svg');
mask-repeat: no-repeat;
mask-position: center;
background-color: #b88eeb;
diff --git a/src/components/Tooltip/index.js b/src/components/Tooltip/index.js
index a8398fb3fb..a43c7b0d57 100644
--- a/src/components/Tooltip/index.js
+++ b/src/components/Tooltip/index.js
@@ -5,7 +5,7 @@ import includes from 'lodash.includes'
import DesktopView from './DesktopView'
import MobileView from './MobileView'
-import glossary from '../../../public/static/docs/glossary'
+import glossary from '../../../content/docs/glossary'
import { OnlyDesktopInline, OnlyMobileInline } from '../../styles'
@@ -21,9 +21,7 @@ class Tooltip extends Component {
if (
includes(
glossaryItem.match.map(word => word.toLowerCase()),
- // In v4 text field in a React.Node,
- // so to get string we need to use it's children
- this.props.text.props.children.replace(/\n/g, ' ').toLowerCase()
+ this.props.text.replace(/\n/g, ' ').toLowerCase()
)
) {
this.setState({
@@ -43,7 +41,7 @@ class Tooltip extends Component {
@@ -63,7 +61,6 @@ class Tooltip extends Component {
}
Tooltip.propTypes = {
- id: PropTypes.string.isRequired,
text: PropTypes.node.isRequired
}
diff --git a/src/components/TopMenu/index.js b/src/components/TopMenu/index.js
index c4bfe432c8..924581fc51 100644
--- a/src/components/TopMenu/index.js
+++ b/src/components/TopMenu/index.js
@@ -54,12 +54,7 @@ export default class TopMenu extends Component {
wide={isDocPage}
>
-
+
diff --git a/src/components/TrySection/index.js b/src/components/TrySection/index.js
index 0be81185eb..575ac89c8b 100644
--- a/src/components/TrySection/index.js
+++ b/src/components/TrySection/index.js
@@ -9,14 +9,14 @@ export default function TrySection({ title, buttonText = 'Get Started' }) {
return (
-
+
{title}
-
+
{buttonText}
-
+
)
diff --git a/src/components/TrySection/styles.js b/src/components/TrySection/styles.js
index 51913260ba..1d6b84b004 100644
--- a/src/components/TrySection/styles.js
+++ b/src/components/TrySection/styles.js
@@ -83,7 +83,7 @@ export const Button = styled.a`
color: #ffffff;
background-color: #945dd6;
- background: url('/static/img/arrow_right_white.svg') right center no-repeat;
+ background: url('/img/arrow_right_white.svg') right center no-repeat;
background-position-x: calc(100% - 15px);
transition: 0.2s background-color ease-out;
@@ -100,6 +100,6 @@ export const Button = styled.a`
background-color: #ffffff;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.21);
- background-image: url('/static/img/arrow_right_dark.svg');
+ background-image: url('/img/arrow_right_dark.svg');
`};
`
diff --git a/src/components/UseCases/index.js b/src/components/UseCases/index.js
index e714f76365..fe173cbc9b 100644
--- a/src/components/UseCases/index.js
+++ b/src/components/UseCases/index.js
@@ -24,7 +24,7 @@ import {
const Heading1 = () => (
-
+
Save and reproduce your experiments
@@ -33,7 +33,7 @@ const Heading1 = () => (
const Heading2 = () => (
-
+
Version control models and data
@@ -42,7 +42,7 @@ const Heading2 = () => (
const Heading3 = () => (
-
+
Establish workflow for deployment & collaboration
diff --git a/src/components/Video/index.js b/src/components/Video/index.js
index 203a2e8088..4608295614 100644
--- a/src/components/Video/index.js
+++ b/src/components/Video/index.js
@@ -19,7 +19,7 @@ const WatchButton = ({ onClick, disabled }) => (