Serverle
Gatsby provides asset pipelining out of the box through its build system on top of Webpack and Babel. Wordpress and Jekyll don't provide this, although you could set up your own. Squarespace has a limited and tightly controlled development environment (no local development) that doesn't allow for creating an asset pipeline.
" ,,CSS Extensions (eg Sass),3,3,1,1,"Languages such as Sass and Less compile to CSS while offering support for variables, functions, hierarchal class definitions; libraries like glamor and aphrodite allow css to be colocated with JS and HTML in React. This solves problems in vanilla CSS like global namespacing, non-determinatism, dead code elimination and minification" -,,Advanced Javascript syntax,3,1,1,0,"Javascript has become more powerful as a language in the last several years, making it easier to write code. These include: +,,Advanced JavaScript syntax,3,1,1,0,"JavaScript has become more powerful as a language in the last several years, making it easier to write code. These include:
+
|
+ |||
{this.props.children} | +|||
+
+
+ |
+
- - | -
-
-
- {comment.by}
- {` `}
- {comment.timeISO}
-
-
- -
-
+
+
-
- |
-
-
- - - - reply - - - - |
+
+
+
+ {comment.by}
+ {` `}
+ {comment.timeISO}
+
+
+ +
+
+
+
+
+ + + + reply + + + + |
+
+ {story.order}. + | ++ + {story.title} + + + {` `}( + {story.domain} + ) + + | +
+ | + + {story.score} points + + {` `} + by + {` `} + + {story.by} + + {` `} + + {story.timeISO} + + {` `} + + {` `} + | + {` `} + + {story.descendants ? story.descendants : 0} comments + + {` `} + | +
-
|
- |||
{this.props.children()} | -|||
-
-
- |
-
- - More - - | -
+ + More + + | +
- - {story.title} - - - {` `}( - {story.domain} - ) - - | -
- {story.score} points - {` `} - by - {` `} - - {story.by} - - {` `} - - {story.timeISO} - - {` `} - | - {` `} - - {story.descendants ? story.descendants : 0} comments - - {` `} - | -
+ + {story.title} + + + {` `}( + {story.domain} + ) + + | +
+ {story.score} points + {` `} + by + {` `} + + {story.by} + + {` `} + + {story.timeISO} + + {` `} + | + {` `} + + {story.descendants ? story.descendants : 0} comments + + {` `} + | +
`-blocks.
- Highlighted lines are wrapped in ``.
- We insert a linebreak before the closing tag of `.gatsby-highlight-code-line`
- so it ends up at the start of the follwing line.
+ so it ends up at the start of the following line.
With all of this in place, we can apply `float:left; min-width:100%` to ``,
throw our overflow and background on `.gatsby-highlight`, and use
diff --git a/packages/gatsby-remark-prismjs/package.json b/packages/gatsby-remark-prismjs/package.json
index 0b8698797f587..a7f131caa41c2 100644
--- a/packages/gatsby-remark-prismjs/package.json
+++ b/packages/gatsby-remark-prismjs/package.json
@@ -1,7 +1,7 @@
{
"name": "gatsby-remark-prismjs",
"description": "Adds syntax highlighting to code blocks at build time using PrismJS",
- "version": "3.0.0-beta.2",
+ "version": "3.0.0-beta.3",
"author": "Kyle Mathews ",
"bugs": {
"url": "https://github.com/gatsbyjs/gatsby/issues"
diff --git a/packages/gatsby-source-contentful/CHANGELOG.md b/packages/gatsby-source-contentful/CHANGELOG.md
index ffb0c1d8482c2..0c602c3c76459 100644
--- a/packages/gatsby-source-contentful/CHANGELOG.md
+++ b/packages/gatsby-source-contentful/CHANGELOG.md
@@ -3,6 +3,24 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [2.0.1-beta.8](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-source-contentful/compare/gatsby-source-contentful@2.0.1-beta.7...gatsby-source-contentful@2.0.1-beta.8) (2018-06-25)
+
+**Note:** Version bump only for package gatsby-source-contentful
+
+
+
+
+
+
+## [2.0.1-beta.7](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-source-contentful/compare/gatsby-source-contentful@2.0.1-beta.6...gatsby-source-contentful@2.0.1-beta.7) (2018-06-25)
+
+**Note:** Version bump only for package gatsby-source-contentful
+
+
+
+
+
## [2.0.1-beta.6](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-source-contentful/compare/gatsby-source-contentful@2.0.1-beta.5...gatsby-source-contentful@2.0.1-beta.6) (2018-06-23)
diff --git a/packages/gatsby-source-contentful/package.json b/packages/gatsby-source-contentful/package.json
index 5260ee8555e37..499d1a73ea55f 100644
--- a/packages/gatsby-source-contentful/package.json
+++ b/packages/gatsby-source-contentful/package.json
@@ -1,7 +1,7 @@
{
"name": "gatsby-source-contentful",
"description": "Gatsby source plugin for building websites using the Contentful CMS as a data source",
- "version": "2.0.1-beta.6",
+ "version": "2.0.1-beta.8",
"author": "Marcus Ericsson (mericsson.com)",
"bugs": {
"url": "https://github.com/gatsbyjs/gatsby/issues"
diff --git a/packages/gatsby-source-contentful/src/fetch.js b/packages/gatsby-source-contentful/src/fetch.js
index 6d89cde51dbc5..cad1db54821bd 100644
--- a/packages/gatsby-source-contentful/src/fetch.js
+++ b/packages/gatsby-source-contentful/src/fetch.js
@@ -2,7 +2,7 @@ const contentful = require(`contentful`)
const _ = require(`lodash`)
const normalize = require(`./normalize`)
-module.exports = async ({ spaceId, host, syncToken, ...options }) => {
+module.exports = async ({ spaceId, syncToken, ...options }) => {
// Fetch articles.
console.time(`Fetch Contentful data`)
diff --git a/packages/gatsby-source-contentful/src/gatsby-node.js b/packages/gatsby-source-contentful/src/gatsby-node.js
index b04b4b30038e4..ad685f470975a 100644
--- a/packages/gatsby-source-contentful/src/gatsby-node.js
+++ b/packages/gatsby-source-contentful/src/gatsby-node.js
@@ -214,20 +214,17 @@ exports.sourceNodes = async (
return
}
-exports.onPreBootstrap = async ({ store }) => {
- const program = store.getState().program
- const CACHE_DIR = path.resolve(
- `${program.directory}/.cache/contentful/assets/`
- )
- await fs.ensureDir(CACHE_DIR)
-}
-
// Check if there are any ContentfulAsset nodes and if gatsby-image is installed. If so,
// add fragments for ContentfulAsset and gatsby-image. The fragment will cause an error
// if there's not ContentfulAsset nodes and without gatsby-image, the fragment is useless.
exports.onPreExtractQueries = async ({ store, getNodes }) => {
const program = store.getState().program
+ const CACHE_DIR = path.resolve(
+ `${program.directory}/.cache/contentful/assets/`
+ )
+ await fs.ensureDir(CACHE_DIR)
+
const nodes = getNodes()
if (!nodes.some(n => n.internal.type === `ContentfulAsset`)) {
diff --git a/packages/gatsby-source-hacker-news/src/gatsby-node.js b/packages/gatsby-source-hacker-news/src/gatsby-node.js
index c7b77681ca87c..e53b2e2b06a9e 100644
--- a/packages/gatsby-source-hacker-news/src/gatsby-node.js
+++ b/packages/gatsby-source-hacker-news/src/gatsby-node.js
@@ -98,12 +98,13 @@ fragment commentsFragment on HackerNewsItem {
kids.kids = []
}
const kidLessStory = _.omit(story, `kids`)
+ const childIds = kids.kids.map(k => createNodeId(k.id))
const storyNode = {
...kidLessStory,
id: createNodeId(kidLessStory.id),
- children: kids.kids.map(k => k.id),
- parent: `__SOURCE__`,
+ children: childIds,
+ parent: null,
content: storyStr,
internal: {
type: `HNStory`,
@@ -122,7 +123,6 @@ fragment commentsFragment on HackerNewsItem {
.digest(`hex`)
storyNode.internal.contentDigest = contentDigest
-
createNode(storyNode)
// Recursively create comment nodes.
@@ -131,10 +131,11 @@ fragment commentsFragment on HackerNewsItem {
if (!comment.kids) {
comment.kids = []
}
+ let commentChildIds = comment.kids.map(k => createNodeId(k.id))
let commentNode = {
..._.omit(comment, `kids`),
id: createNodeId(comment.id),
- children: comment.kids.map(k => k.id),
+ children: commentChildIds,
parent,
internal: {
type: `HNComment`,
diff --git a/packages/gatsby-source-medium/src/gatsby-node.js b/packages/gatsby-source-medium/src/gatsby-node.js
index ee454c7e27b00..8a8579337a856 100644
--- a/packages/gatsby-source-medium/src/gatsby-node.js
+++ b/packages/gatsby-source-medium/src/gatsby-node.js
@@ -59,7 +59,18 @@ exports.sourceNodes = async ({ actions, createNodeId }, { username }) => {
importableResources = importableResources.concat(collections)
}
- const resources = Array.prototype.concat(...importableResources)
+ const resources = Array.prototype
+ .concat(...importableResources)
+ .map(resource => {
+ return {
+ ...resource,
+ medium_id: resource.id,
+ id: createNodeId(resource.id ? resource.id : resource.userId),
+ }
+ })
+
+ const getID = node => (node ? node.id : null)
+
resources.map(resource => {
convertTimestamps(resource)
@@ -71,21 +82,24 @@ exports.sourceNodes = async ({ actions, createNodeId }, { username }) => {
const links =
resource.type === `Post`
? {
- author___NODE: resource.creatorId,
+ author___NODE: getID(
+ resources.find(r => r.userId === resource.creatorId)
+ ),
}
: resource.type === `User`
? {
- posts___NODE: posts
- .filter(post => post.creatorId === resource.userId)
- .map(post => post.id),
+ posts___NODE: resources
+ .filter(
+ r => r.type === `Post` && r.creatorId === resource.userId
+ )
+ .map(r => r.id),
}
: {}
const node = Object.assign(
resource,
{
- id: createNodeId(resource.id ? resource.id : resource.userId),
- parent: `__SOURCE__`,
+ parent: null,
children: [],
internal: {
type: `Medium${resource.type}`,
diff --git a/packages/gatsby-source-mongodb/CHANGELOG.md b/packages/gatsby-source-mongodb/CHANGELOG.md
index 3c0cf44629e82..70f4bb71d6f02 100644
--- a/packages/gatsby-source-mongodb/CHANGELOG.md
+++ b/packages/gatsby-source-mongodb/CHANGELOG.md
@@ -3,6 +3,15 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+# [2.0.0-beta.3](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-source-mongodb/compare/gatsby-source-mongodb@2.0.0-beta.2...gatsby-source-mongodb@2.0.0-beta.3) (2018-06-25)
+
+**Note:** Version bump only for package gatsby-source-mongodb
+
+
+
+
+
# [2.0.0-beta.2](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-source-mongodb/compare/gatsby-source-mongodb@2.0.0-beta.1...gatsby-source-mongodb@2.0.0-beta.2) (2018-06-20)
diff --git a/packages/gatsby-source-mongodb/README.md b/packages/gatsby-source-mongodb/README.md
index 426a41e1648e5..1fd2698110d85 100644
--- a/packages/gatsby-source-mongodb/README.md
+++ b/packages/gatsby-source-mongodb/README.md
@@ -45,6 +45,8 @@ module.exports = {
running locally on the default port.
- **auth**: the authentication data to login a Mongodb collection, with sub
properties user and password. ex. auth: { user: `admin`, password: `12345` }
+- **extraParams**: useful to set additional parameters for the connection, like authSource, ssl or replicaSet
+ (needed for connecting to MongoDB Atlas db as a service), ex: extraParams: { replicaSet: `test-shard-0`, ssl: `true`, authSource: `admin` }
### Mapping mediatype feature
diff --git a/packages/gatsby-source-mongodb/package.json b/packages/gatsby-source-mongodb/package.json
index a13ec3f9ce9d7..400d71f7cfacf 100644
--- a/packages/gatsby-source-mongodb/package.json
+++ b/packages/gatsby-source-mongodb/package.json
@@ -1,7 +1,7 @@
{
"name": "gatsby-source-mongodb",
"description": "Source plugin for pulling data into Gatsby from MongoDB collections",
- "version": "2.0.0-beta.2",
+ "version": "2.0.0-beta.3",
"author": "jhermans85@hotmail.com",
"bugs": {
"url": "https://github.com/gatsbyjs/gatsby/issues"
@@ -9,7 +9,8 @@
"dependencies": {
"@babel/runtime": "7.0.0-beta.51",
"lodash": "^4.17.4",
- "mongodb": "^2.2.30"
+ "mongodb": "^2.2.30",
+ "query-string": "^6.1.0"
},
"devDependencies": {
"@babel/cli": "7.0.0-beta.51",
diff --git a/packages/gatsby-source-mongodb/src/gatsby-node.js b/packages/gatsby-source-mongodb/src/gatsby-node.js
index 1492d3916682e..e5a59a2dbf533 100644
--- a/packages/gatsby-source-mongodb/src/gatsby-node.js
+++ b/packages/gatsby-source-mongodb/src/gatsby-node.js
@@ -2,6 +2,7 @@ const MongoClient = require(`mongodb`).MongoClient
const crypto = require(`crypto`)
const prepareMappingChildNode = require(`./mapping`)
const _ = require(`lodash`)
+const queryString = require(`query-string`)
exports.sourceNodes = (
{ actions, getNode, createNodeId, hasNodeChanged },
@@ -18,9 +19,10 @@ exports.sourceNodes = (
if (pluginOptions.auth)
authUrlPart = `${pluginOptions.auth.user}:${pluginOptions.auth.password}@`
+ let connectionExtraParams = getConnectionExtraParams(pluginOptions.extraParams)
const connectionURL = `mongodb://${authUrlPart}${serverOptions.address}:${
serverOptions.port
- }/${dbName}`
+ }/${dbName}${connectionExtraParams}`
return MongoClient.connect(connectionURL)
.then(db => {
@@ -119,3 +121,12 @@ function createNodes(
function caps(s) {
return s.replace(/\b\w/g, l => l.toUpperCase())
}
+
+function getConnectionExtraParams(extraParams) {
+ let connectionSuffix
+ if (extraParams) {
+ connectionSuffix = queryString.stringify(extraParams, { sort: false })
+ }
+
+ return connectionSuffix ? `?` + connectionSuffix : ``
+}
\ No newline at end of file
diff --git a/packages/gatsby-transformer-sharp/CHANGELOG.md b/packages/gatsby-transformer-sharp/CHANGELOG.md
index ae8e21dcb365d..1beddadde77dd 100644
--- a/packages/gatsby-transformer-sharp/CHANGELOG.md
+++ b/packages/gatsby-transformer-sharp/CHANGELOG.md
@@ -3,6 +3,15 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [2.1.1-beta.3](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-transformer-sharp/compare/gatsby-transformer-sharp@2.1.1-beta.2...gatsby-transformer-sharp@2.1.1-beta.3) (2018-06-26)
+
+**Note:** Version bump only for package gatsby-transformer-sharp
+
+
+
+
+
## [2.1.1-beta.2](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-transformer-sharp/compare/gatsby-transformer-sharp@2.1.1-beta.1...gatsby-transformer-sharp@2.1.1-beta.2) (2018-06-20)
diff --git a/packages/gatsby-transformer-sharp/package.json b/packages/gatsby-transformer-sharp/package.json
index f29d7ccb4d7bf..d420b8e22f3bb 100644
--- a/packages/gatsby-transformer-sharp/package.json
+++ b/packages/gatsby-transformer-sharp/package.json
@@ -1,7 +1,7 @@
{
"name": "gatsby-transformer-sharp",
"description": "Gatsby transformer plugin for images using Sharp",
- "version": "2.1.1-beta.2",
+ "version": "2.1.1-beta.3",
"author": "Kyle Mathews ",
"bugs": {
"url": "https://github.com/gatsbyjs/gatsby/issues"
diff --git a/packages/gatsby-transformer-sharp/src/fragments.js b/packages/gatsby-transformer-sharp/src/fragments.js
index cdc7258aa434d..31ffa0436bd4e 100644
--- a/packages/gatsby-transformer-sharp/src/fragments.js
+++ b/packages/gatsby-transformer-sharp/src/fragments.js
@@ -1,4 +1,6 @@
/* eslint-disable */
+import { graphql } from "gatsby"
+
export const gatsbyImageSharpFixed = graphql`
fragment GatsbyImageSharpFixed on ImageSharpFixed {
base64
diff --git a/packages/gatsby/CHANGELOG.md b/packages/gatsby/CHANGELOG.md
index 3bbbb624c19c6..a9720767a41b1 100644
--- a/packages/gatsby/CHANGELOG.md
+++ b/packages/gatsby/CHANGELOG.md
@@ -3,6 +3,33 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+# [2.0.0-beta.12](https://github.com/gatsbyjs/gatsby/compare/gatsby@2.0.0-beta.11...gatsby@2.0.0-beta.12) (2018-06-26)
+
+**Note:** Version bump only for package gatsby
+
+
+
+
+
+
+# [2.0.0-beta.11](https://github.com/gatsbyjs/gatsby/compare/gatsby@2.0.0-beta.10...gatsby@2.0.0-beta.11) (2018-06-25)
+
+**Note:** Version bump only for package gatsby
+
+
+
+
+
+
+# [2.0.0-beta.10](https://github.com/gatsbyjs/gatsby/compare/gatsby@2.0.0-beta.9...gatsby@2.0.0-beta.10) (2018-06-25)
+
+**Note:** Version bump only for package gatsby
+
+
+
+
+
# [2.0.0-beta.9](https://github.com/gatsbyjs/gatsby/compare/gatsby@2.0.0-beta.8...gatsby@2.0.0-beta.9) (2018-06-21)
diff --git a/packages/gatsby/index.d.ts b/packages/gatsby/index.d.ts
index 839da7d756df9..c7be24341343d 100644
--- a/packages/gatsby/index.d.ts
+++ b/packages/gatsby/index.d.ts
@@ -18,3 +18,5 @@ export interface StaticQueryProps {
}
export class StaticQuery extends React.Component {}
+
+export const graphql: (query: TemplateStringsArray) => void
diff --git a/packages/gatsby/package.json b/packages/gatsby/package.json
index 5d9e687d96f94..6a04b5cccc76c 100644
--- a/packages/gatsby/package.json
+++ b/packages/gatsby/package.json
@@ -1,7 +1,7 @@
{
"name": "gatsby",
"description": "React.js Static Site Generator",
- "version": "2.0.0-beta.9",
+ "version": "2.0.0-beta.12",
"author": "Kyle Mathews ",
"bin": {
"gatsby": "./dist/bin/gatsby.js"
@@ -62,7 +62,7 @@
"front-matter": "^2.1.0",
"fs-extra": "^5.0.0",
"gatsby-cli": "^2.0.0-beta.2",
- "gatsby-link": "^2.0.0-beta.2",
+ "gatsby-link": "^2.0.0-beta.3",
"gatsby-plugin-page-creator": "^2.0.0-beta.2",
"gatsby-react-router-scroll": "^2.0.0-beta.2",
"glob": "^7.1.1",
diff --git a/packages/gatsby/src/cache-dir/gatsby-browser-entry.js b/packages/gatsby/src/cache-dir/gatsby-browser-entry.js
index 8dd14a0cb1b39..30070e3c7bf10 100644
--- a/packages/gatsby/src/cache-dir/gatsby-browser-entry.js
+++ b/packages/gatsby/src/cache-dir/gatsby-browser-entry.js
@@ -1,24 +1,7 @@
import React from "react"
import PropTypes from "prop-types"
import Link, { withPrefix, push, replace, navigateTo } from "gatsby-link"
-import pages from "./pages.json"
-import loader from "./loader"
-import JSONStore from "./json-store"
-
-const PageRenderer = ({ location }) => {
- const pageResources = loader.getResourcesForPathname(location.pathname)
- return React.createElement(JSONStore, {
- pages,
- location,
- pageResources,
- })
-}
-
-PageRenderer.propTypes = {
- location: PropTypes.shape({
- pathname: PropTypes.string.isRequired,
- }).isRequired,
-}
+import PageRenderer from "./public-page-renderer"
const StaticQueryContext = React.createContext({})
diff --git a/packages/gatsby/src/cache-dir/production-app.js b/packages/gatsby/src/cache-dir/production-app.js
index 43326305a4e56..4559afd11f224 100644
--- a/packages/gatsby/src/cache-dir/production-app.js
+++ b/packages/gatsby/src/cache-dir/production-app.js
@@ -52,6 +52,8 @@ apiRunnerAsync(`onClientEntry`).then(() => {
require(`./register-service-worker`)
}
+ let lastNavigateToLocationString = null
+
const navigate = (to, replace) => {
const location = createLocation(to, null, null, history.location)
let { pathname } = location
@@ -77,33 +79,36 @@ apiRunnerAsync(`onClientEntry`).then(() => {
? window.___history.replace
: window.___history.push
- // Listen to loading events. If page resources load before
- // a second, navigate immediately.
- function eventHandler(e) {
- if (e.page.path === loader.getPage(pathname).path) {
- emitter.off(`onPostLoadPageResources`, eventHandler)
- clearTimeout(timeoutId)
- historyNavigateFunc(location)
- }
- }
+ const historyNavigateAction = replace
+ ? `REPLACE`
+ : `PUSH`
// Start a timer to wait for a second before transitioning and showing a
// loader in case resources aren't around yet.
const timeoutId = setTimeout(() => {
- emitter.off(`onPostLoadPageResources`, eventHandler)
emitter.emit(`onDelayedLoadPageResources`, { pathname })
- historyNavigateFunc(location)
+ apiRunner(`onRouteUpdateDelayed`, { location, action: historyNavigateAction })
}, 1000)
- if (loader.getResourcesForPathname(pathname)) {
- // The resources are already loaded so off we go.
- clearTimeout(timeoutId)
- historyNavigateFunc(location)
- } else {
- // They're not loaded yet so let's add a listener for when
- // they finish loading.
- emitter.on(`onPostLoadPageResources`, eventHandler)
+ lastNavigateToLocationString = `${location.pathname}${location.search}${
+ location.hash
+ }`
+
+ apiRunner(`onPreRouteUpdate`, { location, action: historyNavigateAction })
+
+ const loaderCallback = pageResources => {
+ if (!pageResources) {
+ // We fetch resources for 404 page in page-renderer.js. Calling it
+ // here is to ensure that we have needed resouces to render page
+ // before navigating to it
+ loader.getResourcesForPathname(`/404.html`, loaderCallback)
+ } else {
+ clearTimeout(timeoutId)
+ historyNavigateFunc(location)
+ }
}
+
+ loader.getResourcesForPathname(pathname, loaderCallback)
}
// window.___loadScriptsForPath = loadScriptsForPath
@@ -124,6 +129,14 @@ apiRunnerAsync(`onClientEntry`).then(() => {
history.listen((location, action) => {
if (!maybeRedirect(location.pathname)) {
+ // Check if we already ran onPreRouteUpdate API
+ // in navigateTo function
+ if (
+ lastNavigateToLocationString !==
+ `${location.pathname}${location.search}${location.hash}`
+ ) {
+ apiRunner(`onPreRouteUpdate`, { location, action })
+ }
// Make sure React has had a chance to flush to DOM first.
setTimeout(() => {
apiRunner(`onRouteUpdate`, { location, action })
diff --git a/packages/gatsby/src/cache-dir/public-page-renderer-dev.js b/packages/gatsby/src/cache-dir/public-page-renderer-dev.js
new file mode 100644
index 0000000000000..c169409065b3c
--- /dev/null
+++ b/packages/gatsby/src/cache-dir/public-page-renderer-dev.js
@@ -0,0 +1,23 @@
+import React from "react"
+import PropTypes from "prop-types"
+
+import pages from "./pages.json"
+import loader from "./loader"
+import JSONStore from "./json-store"
+
+const DevPageRenderer = ({ location }) => {
+ const pageResources = loader.getResourcesForPathname(location.pathname)
+ return React.createElement(JSONStore, {
+ pages,
+ location,
+ pageResources,
+ })
+}
+
+DevPageRenderer.propTypes = {
+ location: PropTypes.shape({
+ pathname: PropTypes.string.isRequired,
+ }).isRequired,
+}
+
+export default DevPageRenderer
\ No newline at end of file
diff --git a/packages/gatsby/src/cache-dir/public-page-renderer-prod.js b/packages/gatsby/src/cache-dir/public-page-renderer-prod.js
new file mode 100644
index 0000000000000..82f45afd0c831
--- /dev/null
+++ b/packages/gatsby/src/cache-dir/public-page-renderer-prod.js
@@ -0,0 +1,21 @@
+import React from "react"
+import PropTypes from "prop-types"
+
+import InternalPageRenderer from "./page-renderer"
+import loader from "./loader"
+
+const ProdPageRenderer = ({ location }) => {
+ const pageResources = loader.getResourcesForPathname(location.pathname)
+ return React.createElement(InternalPageRenderer, {
+ location,
+ pageResources,
+ })
+}
+
+ProdPageRenderer.propTypes = {
+ location: PropTypes.shape({
+ pathname: PropTypes.string.isRequired,
+ }).isRequired,
+}
+
+export default ProdPageRenderer
\ No newline at end of file
diff --git a/packages/gatsby/src/cache-dir/public-page-renderer.js b/packages/gatsby/src/cache-dir/public-page-renderer.js
new file mode 100644
index 0000000000000..2402fa08d04a6
--- /dev/null
+++ b/packages/gatsby/src/cache-dir/public-page-renderer.js
@@ -0,0 +1,7 @@
+const preferDefault = m => (m && m.default) || m
+
+if (process.env.NODE_ENV === `production`) {
+ module.exports = preferDefault(require(`./public-page-renderer-prod`))
+} else {
+ module.exports = preferDefault(require(`./public-page-renderer-dev`))
+}
\ No newline at end of file
diff --git a/packages/gatsby/src/cache-dir/root.js b/packages/gatsby/src/cache-dir/root.js
index 08e5e2f156169..46ffc58edc0da 100644
--- a/packages/gatsby/src/cache-dir/root.js
+++ b/packages/gatsby/src/cache-dir/root.js
@@ -67,6 +67,7 @@ function attachToHistory(history) {
history.listen((location, action) => {
if (!maybeRedirect(location.pathname)) {
+ apiRunner(`onPreRouteUpdate`, { location, action })
apiRunner(`onRouteUpdate`, { location, action })
}
})
diff --git a/packages/gatsby/src/commands/build-html.js b/packages/gatsby/src/commands/build-html.js
index 30ba5c0c0676f..a7af8fee9a0f1 100644
--- a/packages/gatsby/src/commands/build-html.js
+++ b/packages/gatsby/src/commands/build-html.js
@@ -53,7 +53,7 @@ module.exports = async (program: any) => {
return resolve(null, stats)
})
.catch(e => {
- console.log(e)
+ reject(createErrorFromString(e.stack, `${outputFile}.map`))
})
})
})
diff --git a/packages/gatsby/src/internal-plugins/query-runner/__tests__/__snapshots__/utils.js.snap b/packages/gatsby/src/internal-plugins/query-runner/__tests__/__snapshots__/utils.js.snap
new file mode 100644
index 0000000000000..e66e7d445cebc
--- /dev/null
+++ b/packages/gatsby/src/internal-plugins/query-runner/__tests__/__snapshots__/utils.js.snap
@@ -0,0 +1,16 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Text formatting format error details correctly 1`] = `
+"Field:
+ One line error
+Bar:
+ Three
+ line
+ error"
+`;
+
+exports[`Text formatting indent string correctly 1`] = `
+" Line 1
+ Line 2
+ - Line 3"
+`;
diff --git a/packages/gatsby/src/internal-plugins/query-runner/__tests__/utils.js b/packages/gatsby/src/internal-plugins/query-runner/__tests__/utils.js
new file mode 100644
index 0000000000000..42f41ffc35ef7
--- /dev/null
+++ b/packages/gatsby/src/internal-plugins/query-runner/__tests__/utils.js
@@ -0,0 +1,20 @@
+import { indentString, formatErrorDetails } from "../utils"
+
+describe(`Text formatting `, () => {
+ it(`indent string correctly`, () => {
+ expect(indentString(
+ ` Line 1
+Line 2
+ - Line 3`
+ )).toMatchSnapshot()
+ })
+
+ it(`format error details correctly`, () => {
+ const testErrors = new Map()
+ testErrors.set(`Field`, `One line error`)
+ testErrors.set(`Bar`, `Three
+line
+error`)
+ expect(formatErrorDetails(testErrors)).toMatchSnapshot()
+ })
+})
\ No newline at end of file
diff --git a/packages/gatsby/src/internal-plugins/query-runner/page-query-runner.js b/packages/gatsby/src/internal-plugins/query-runner/page-query-runner.js
index 8dbf993dda41b..4ed2677711c83 100644
--- a/packages/gatsby/src/internal-plugins/query-runner/page-query-runner.js
+++ b/packages/gatsby/src/internal-plugins/query-runner/page-query-runner.js
@@ -127,6 +127,7 @@ const runQueriesForPathnames = pathnames => {
jsonName: page.jsonName,
query: store.getState().components[page.componentPath].query,
isPage: true,
+ componentPath: page.componentPath,
context: {
...page,
...page.context,
diff --git a/packages/gatsby/src/internal-plugins/query-runner/query-compiler.js b/packages/gatsby/src/internal-plugins/query-runner/query-compiler.js
index 037de2f73b139..5e0f38ec24ca1 100644
--- a/packages/gatsby/src/internal-plugins/query-runner/query-compiler.js
+++ b/packages/gatsby/src/internal-plugins/query-runner/query-compiler.js
@@ -185,7 +185,7 @@ class Runner {
name,
text,
originalText: nameDefMap.get(name).text,
- path: path.join(this.baseDir, filePath),
+ path: filePath,
isStaticQuery: nameDefMap.get(name).isStaticQuery,
hash: nameDefMap.get(name).hash,
}
diff --git a/packages/gatsby/src/internal-plugins/query-runner/query-runner.js b/packages/gatsby/src/internal-plugins/query-runner/query-runner.js
index c78820b242239..942170f0cd591 100644
--- a/packages/gatsby/src/internal-plugins/query-runner/query-runner.js
+++ b/packages/gatsby/src/internal-plugins/query-runner/query-runner.js
@@ -8,6 +8,7 @@ const websocketManager = require(`../../utils/websocket-manager`)
const path = require(`path`)
const { store } = require(`../../redux`)
const { generatePathChunkName } = require(`../../utils/js-chunk-names`)
+const { formatErrorDetails } = require(`./utils`)
const resultHashes = {}
@@ -21,8 +22,6 @@ type QueryJob = {
isPage: Boolean,
}
-const indentString = string => string.replace(/\n/g, `\n `)
-
// Run query
module.exports = async (queryJob: QueryJob, component: Any) => {
const { schema, program } = store.getState()
@@ -43,19 +42,22 @@ module.exports = async (queryJob: QueryJob, component: Any) => {
// If there's a graphql error then log the error. If we're building, also
// quit.
if (result && result.errors) {
+ const errorDetails = new Map()
+ errorDetails.set(`Errors`, result.errors || [])
+ if (queryJob.isPage) {
+ errorDetails.set(`URL path`, queryJob.context.path)
+ errorDetails.set(
+ `Context`,
+ JSON.stringify(queryJob.context.context, null, 2)
+ )
+ }
+ errorDetails.set(`Plugin`, queryJob.pluginCreatorId || `none`)
+ errorDetails.set(`Query`, queryJob.query)
+
report.log(`
-The GraphQL query from ${component.componentPath} failed.
-
-Errors:
- ${result.errors || []}
-URL path:
- ${queryJob.path}
-Context:
- ${indentString(JSON.stringify(queryJob.context, null, 2))}
-Plugin:
- ${queryJob.pluginCreatorId || `none`}
-Query:
- ${indentString(component.query)}`)
+The GraphQL query from ${queryJob.componentPath} failed.
+
+${formatErrorDetails(errorDetails)}`)
// Perhaps this isn't the best way to see if we're building?
if (program._[0] === `build`) {
diff --git a/packages/gatsby/src/internal-plugins/query-runner/utils.js b/packages/gatsby/src/internal-plugins/query-runner/utils.js
new file mode 100644
index 0000000000000..f3577749de29d
--- /dev/null
+++ b/packages/gatsby/src/internal-plugins/query-runner/utils.js
@@ -0,0 +1,13 @@
+// @flow
+
+const indentString = (string: string): string => string.replace(/\n/g, `\n `)
+
+const formatErrorDetails = (errorDetails: Map): string =>
+ Array.from(errorDetails.entries())
+ .map(
+ ([name, details]) => `${name}:
+ ${indentString(details.toString())}`
+ )
+ .join(`\n`)
+
+export { indentString, formatErrorDetails }
\ No newline at end of file
diff --git a/packages/gatsby/src/schema/__tests__/data-tree-utils-test.js b/packages/gatsby/src/schema/__tests__/data-tree-utils-test.js
index 849c3cb2f35ff..005c79506984a 100644
--- a/packages/gatsby/src/schema/__tests__/data-tree-utils-test.js
+++ b/packages/gatsby/src/schema/__tests__/data-tree-utils-test.js
@@ -176,34 +176,50 @@ describe(`Gatsby data tree utils`, () => {
it(`prefers float when multiple number types`, () => {
let example
- // nodes starting with integer
+ // nodes starting with 32-bit integer ("big" ints are float)
example = getExampleValues({ nodes: [{ number: 5 }, { number: 2.5 }] })
expect(example.number).toBeDefined()
expect(example.number).toEqual(2.5)
+ example = getExampleValues({ nodes: [{ number: 5 }, { number: 3000000000 }] })
+ expect(example.number).toBeDefined()
+ expect(example.number).toEqual(3000000000)
// with node not containing number field
example = getExampleValues({ nodes: [{ number: 5 }, {}, { number: 2.5 }] })
expect(example.number).toBeDefined()
expect(example.number).toEqual(2.5)
- // nodes starting with float
+ // nodes starting with float ("big" ints are float)
example = getExampleValues({ nodes: [{ number: 2.5 }, { number: 5 }] })
expect(example.number).toBeDefined()
expect(example.number).toEqual(2.5)
+ example = getExampleValues({ nodes: [{ number: 3000000000 }, { number: 5 }] })
+ expect(example.number).toBeDefined()
+ expect(example.number).toEqual(3000000000)
- // array of numbers - starting with integer
+ // array of numbers - starting with float
example = getExampleValues({ nodes: [{ numbers: [2.5, 5] }] })
expect(example.numbers).toBeDefined()
expect(Array.isArray(example.numbers)).toBe(true)
expect(example.numbers.length).toBe(1)
expect(example.numbers[0]).toBe(2.5)
+ example = getExampleValues({ nodes: [{ numbers: [3000000000, 5] }] })
+ expect(example.numbers).toBeDefined()
+ expect(Array.isArray(example.numbers)).toBe(true)
+ expect(example.numbers.length).toBe(1)
+ expect(example.numbers[0]).toBe(3000000000)
- // array of numbers - starting with float
+ // array of numbers - starting with 32-bit integer
example = getExampleValues({ nodes: [{ numbers: [5, 2.5] }] })
expect(example.numbers).toBeDefined()
expect(Array.isArray(example.numbers)).toBe(true)
expect(example.numbers.length).toBe(1)
expect(example.numbers[0]).toBe(2.5)
+ example = getExampleValues({ nodes: [{ numbers: [5, 3000000000] }] })
+ expect(example.numbers).toBeDefined()
+ expect(Array.isArray(example.numbers)).toBe(true)
+ expect(example.numbers.length).toBe(1)
+ expect(example.numbers[0]).toBe(3000000000)
})
it(`handles mix of date strings and date objects`, () => {
diff --git a/packages/gatsby/src/schema/__tests__/infer-graphql-input-type-test.js b/packages/gatsby/src/schema/__tests__/infer-graphql-input-type-test.js
index f8aa7642bba17..b5d4769d95247 100644
--- a/packages/gatsby/src/schema/__tests__/infer-graphql-input-type-test.js
+++ b/packages/gatsby/src/schema/__tests__/infer-graphql-input-type-test.js
@@ -266,6 +266,21 @@ describe(`GraphQL Input args`, () => {
expect(Object.keys(fields.foo.type.getFields())).toHaveLength(2)
})
+ it(`infers number types`, () => {
+ const fields = inferInputObjectStructureFromNodes({
+ nodes: [
+ {
+ int32: 42,
+ float: 2.5,
+ longint: 3000000000,
+ },
+ ],
+ }).inferredFields
+ expect(fields.int32.type.name.endsWith(`Integer`)).toBe(true)
+ expect(fields.float.type.name.endsWith(`Float`)).toBe(true)
+ expect(fields.longint.type.name.endsWith(`Float`)).toBe(true)
+ })
+
it(`handles eq operator`, async () => {
let result = await queryResult(
nodes,
diff --git a/packages/gatsby/src/schema/__tests__/infer-graphql-type-test.js b/packages/gatsby/src/schema/__tests__/infer-graphql-type-test.js
index 7bfd595442544..397ee888ccd3a 100644
--- a/packages/gatsby/src/schema/__tests__/infer-graphql-type-test.js
+++ b/packages/gatsby/src/schema/__tests__/infer-graphql-type-test.js
@@ -124,6 +124,20 @@ describe(`GraphQL type inferance`, () => {
)
})
+ it(`doesn't throw errors at ints longer than 32-bit`, async () => {
+ const result = await queryResult(
+ [
+ {
+ longint: 3000000000,
+ },
+ ],
+ `
+ longint
+ `
+ )
+ expect(result.errors).toBeUndefined()
+ })
+
it(`prefers float when multiple number types`, async () => {
let result = await queryResult(
[{ number: 1.1 }, { number: 1 }],
@@ -199,6 +213,21 @@ describe(`GraphQL type inferance`, () => {
expect(Object.keys(fields.foo.type.getFields())).toHaveLength(4)
})
+ it(`infers number types`, () => {
+ const fields = inferObjectStructureFromNodes({
+ nodes: [
+ {
+ int32: 42,
+ float: 2.5,
+ longint: 3000000000,
+ },
+ ],
+ })
+ expect(fields.int32.type.name).toEqual(`Int`)
+ expect(fields.float.type.name).toEqual(`Float`)
+ expect(fields.longint.type.name).toEqual(`Float`)
+ })
+
it(`Handle invalid graphql field names`, async () => {
let result = await queryResult(
nodes,
diff --git a/packages/gatsby/src/schema/data-tree-utils.js b/packages/gatsby/src/schema/data-tree-utils.js
index 5e53167da2668..d53a33be41384 100644
--- a/packages/gatsby/src/schema/data-tree-utils.js
+++ b/packages/gatsby/src/schema/data-tree-utils.js
@@ -7,6 +7,7 @@ const invariant = require(`invariant`)
const createKey = require(`./create-key`)
const { typeConflictReporter } = require(`./type-conflict-reporter`)
const DateType = require(`./types/type-date`)
+const is32BitInteger = require(`../utils/is-32-bit-integer`)
import type { TypeEntry } from "./type-conflict-reporter"
@@ -118,7 +119,7 @@ const getExampleScalarFromArray = values =>
values,
(value, nextValue) => {
// Prefer floats over ints as they're more specific.
- if (nextValue && _.isNumber(nextValue) && !_.isInteger(nextValue)) {
+ if (nextValue && _.isNumber(nextValue) && !is32BitInteger(nextValue)) {
return nextValue
} else if (value === null) {
return nextValue
diff --git a/packages/gatsby/src/schema/infer-graphql-input-fields.js b/packages/gatsby/src/schema/infer-graphql-input-fields.js
index 14824128ab453..ed6c04a97eb79 100644
--- a/packages/gatsby/src/schema/infer-graphql-input-fields.js
+++ b/packages/gatsby/src/schema/infer-graphql-input-fields.js
@@ -21,6 +21,7 @@ const {
const { findLinkedNode } = require(`./infer-graphql-type`)
const { getNodes } = require(`../redux`)
+const is32BitInteger = require(`../utils/is-32-bit-integer`)
import type {
GraphQLInputFieldConfig,
@@ -76,7 +77,7 @@ function inferGraphQLInputFields({
let headType = typeOf(headValue)
if (headType === `number`)
- headType = _.isInteger(headValue) ? `int` : `float`
+ headType = is32BitInteger(headValue) ? `int` : `float`
// Determine type for in operator.
let inType
@@ -165,7 +166,7 @@ function inferGraphQLInputFields({
}
}
case `number`: {
- if (value % 1 === 0) {
+ if (is32BitInteger(value)) {
return {
type: new GraphQLInputObjectType({
name: createTypeName(`${prefix}QueryInteger`),
diff --git a/packages/gatsby/src/schema/infer-graphql-type.js b/packages/gatsby/src/schema/infer-graphql-type.js
index be2d510ff1c2f..7c4b856fd03ca 100644
--- a/packages/gatsby/src/schema/infer-graphql-type.js
+++ b/packages/gatsby/src/schema/infer-graphql-type.js
@@ -19,6 +19,7 @@ const createKey = require(`./create-key`)
const { getExampleValues, isEmptyObjectOrArray } = require(`./data-tree-utils`)
const DateType = require(`./types/type-date`)
const FileType = require(`./types/type-file`)
+const is32BitInteger = require(`../utils/is-32-bit-integer`)
import type { GraphQLOutputType } from "graphql"
import type {
@@ -117,7 +118,7 @@ function inferGraphQLType({
}),
}
case `number`:
- return _.isInteger(exampleValue)
+ return is32BitInteger(exampleValue)
? { type: GraphQLInt }
: { type: GraphQLFloat }
default:
diff --git a/packages/gatsby/src/utils/__tests__/is-32-bit-integer.js b/packages/gatsby/src/utils/__tests__/is-32-bit-integer.js
new file mode 100644
index 0000000000000..c040eda6f915e
--- /dev/null
+++ b/packages/gatsby/src/utils/__tests__/is-32-bit-integer.js
@@ -0,0 +1,21 @@
+const is32BitInteger = require(`../is-32-bit-integer.js`)
+
+const MAX_INT = 2147483647
+const MIN_INT = -2147483648
+
+describe(`is32BitInteger`, () => {
+ it(`works with all kind of values`, () => {
+ expect(is32BitInteger(MAX_INT)).toBe(true)
+ expect(is32BitInteger(MIN_INT)).toBe(true)
+ expect(is32BitInteger(MAX_INT + 1)).toBe(false)
+ expect(is32BitInteger(MIN_INT - 1)).toBe(false)
+ expect(is32BitInteger(2.4)).toBe(false)
+ expect(is32BitInteger(`42`)).toBe(false)
+ expect(is32BitInteger({})).toBe(false)
+ expect(is32BitInteger([1])).toBe(false)
+ expect(is32BitInteger(true)).toBe(false)
+ expect(is32BitInteger(false)).toBe(false)
+ expect(is32BitInteger(undefined)).toBe(false)
+ expect(is32BitInteger(null)).toBe(false)
+ })
+})
diff --git a/packages/gatsby/src/utils/api-browser-docs.js b/packages/gatsby/src/utils/api-browser-docs.js
index 820e2043f06f8..7a05488ad28b0 100644
--- a/packages/gatsby/src/utils/api-browser-docs.js
+++ b/packages/gatsby/src/utils/api-browser-docs.js
@@ -17,6 +17,30 @@ exports.onClientEntry = true
*/
exports.onInitialClientRender = true
+/**
+ * Called when changing location is started.
+ * @param {object} $0
+ * @param {object} $0.location A location object
+ * @param {object} $0.action The "action" that caused the route change
+ * @example
+ * exports.onPreRouteUpdate = ({ location }) => {
+ * console.log("Gatsby started to change location", location.pathname)
+ * }
+ */
+exports.onPreRouteUpdate = true
+
+/**
+ * Called when changing location is longer than 1 second.
+ * @param {object} $0
+ * @param {object} $0.location A location object
+ * @param {object} $0.action The "action" that caused the route change
+ * @example
+ * exports.onRouteUpdateDelayed = () => {
+ * console.log("We can show loading indicator now")
+ * }
+ */
+exports.onRouteUpdateDelayed = true
+
/**
* Called when the user changes routes
* @param {object} $0
diff --git a/packages/gatsby/src/utils/is-32-bit-integer.js b/packages/gatsby/src/utils/is-32-bit-integer.js
new file mode 100644
index 0000000000000..79571106bcf23
--- /dev/null
+++ b/packages/gatsby/src/utils/is-32-bit-integer.js
@@ -0,0 +1,3 @@
+module.exports = function(x) {
+ return (x | 0) === x
+}
\ No newline at end of file
diff --git a/packages/gatsby/src/utils/websocket-manager.js b/packages/gatsby/src/utils/websocket-manager.js
index 36ae69fd005dc..93e832ddb4b3c 100644
--- a/packages/gatsby/src/utils/websocket-manager.js
+++ b/packages/gatsby/src/utils/websocket-manager.js
@@ -115,7 +115,7 @@ class WebsocketManager {
if (this.isInitialised) {
this.websocket.send({ type: `pageQueryResult`, payload: data })
}
- this.pageResults.set(data.path, data)
+ this.pageResults.set(data.id, data)
}
}
diff --git a/www/gatsby-browser.js b/www/gatsby-browser.js
new file mode 100644
index 0000000000000..7a0b2b00d5460
--- /dev/null
+++ b/www/gatsby-browser.js
@@ -0,0 +1,10 @@
+exports.onClientEntry = () => {
+ ;(function() {
+ const path = `https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.css`
+ const link = document.createElement(`link`)
+ link.setAttribute(`rel`, `stylesheet`)
+ link.setAttribute(`type`, `text/css`)
+ link.setAttribute(`href`, path)
+ document.head.appendChild(link)
+ })()
+}
diff --git a/www/gatsby-node.js b/www/gatsby-node.js
index 22bb739b42a3c..0694a869b0dfe 100644
--- a/www/gatsby-node.js
+++ b/www/gatsby-node.js
@@ -4,7 +4,7 @@ const path = require(`path`)
const parseFilepath = require(`parse-filepath`)
const fs = require(`fs-extra`)
const slash = require(`slash`)
-const slugify = require(`limax`)
+const slugify = require(`slugify`)
const url = require(`url`)
const localPackages = `../packages`
@@ -306,7 +306,9 @@ exports.onCreateNode = ({ node, actions, getNode }) => {
createNodeField({ node, name: `slug`, value: slug })
}
} else if (node.internal.type === `AuthorYaml`) {
- slug = `/contributors/${slugify(node.id)}/`
+ slug = `/contributors/${slugify(node.id, {
+ lower: true,
+ })}/`
createNodeField({ node, name: `slug`, value: slug })
} else if (node.internal.type === `SitesYaml` && node.main_url) {
const parsed = url.parse(node.main_url)
diff --git a/www/package.json b/www/package.json
index 28040f4b443ed..ea45cd0675312 100644
--- a/www/package.json
+++ b/www/package.json
@@ -1,7 +1,7 @@
{
- "name": "gatsby-starter-default",
- "description": "Gatsby default starter",
- "version": "1.1.0-alpha.03b9df85",
+ "name": "gatsbyjs.org",
+ "description": "Gatsby's Website",
+ "version": "2.0.0-beta",
"author": "Kyle Mathews ",
"dependencies": {
"bluebird": "^3.5.1",
@@ -46,7 +46,6 @@
"graphql-request": "^1.5.1",
"gray-percentage": "^2.0.0",
"hex2rgba": "^0.0.1",
- "limax": "^1.5.0",
"lodash": "^4.17.5",
"mitt": "^1.1.3",
"mousetrap": "^1.6.1",
@@ -60,6 +59,7 @@
"react-modal": "^3.4.4",
"react-typography": "^0.16.13",
"slash": "^1.0.0",
+ "slugify": "^1.3.0",
"typeface-space-mono": "^0.0.54",
"typeface-spectral": "^0.0.54",
"typography": "^0.16.6",
diff --git a/www/src/components/blog-post-preview-item.js b/www/src/components/blog-post-preview-item.js
index 65ec7bbf6a7c1..10d67bc085350 100644
--- a/www/src/components/blog-post-preview-item.js
+++ b/www/src/components/blog-post-preview-item.js
@@ -1,5 +1,5 @@
import React from "react"
-import { Link } from "gatsby"
+import { Link, graphql } from "gatsby"
import Img from "gatsby-image"
import typography, { rhythm, scale } from "../utils/typography"
@@ -25,19 +25,35 @@ class BlogPostPreviewItem extends React.Component {
marginBottom: rhythm(2),
}}
>
-
+ >
+
+
- You're viewing the docs for Gatsby v2 beta.{` `}
-
- View the v1 docs instead
+ These are the docs for v2 beta.{` `}
+
+ View the v1 docs
+
+ {` `}
+ instead
+
.
this.props.children}
/>
diff --git a/www/src/components/markdown-page-footer.js b/www/src/components/markdown-page-footer.js
index 51564aa625747..9eaf577bd1f47 100644
--- a/www/src/components/markdown-page-footer.js
+++ b/www/src/components/markdown-page-footer.js
@@ -1,4 +1,5 @@
import React from "react"
+import { graphql } from "gatsby"
import EditIcon from "react-icons/lib/md/create"
import CheckIcon from "react-icons/lib/md/thumb-up"
import CrossIcon from "react-icons/lib/md/thumb-down"
diff --git a/www/src/components/navigation.js b/www/src/components/navigation.js
index cdfa4440fb982..690b154843f33 100644
--- a/www/src/components/navigation.js
+++ b/www/src/components/navigation.js
@@ -87,15 +87,16 @@ export default ({ pathname }) => {
return (
-
+
)
}
diff --git a/www/src/components/showcase-details.js b/www/src/components/showcase-details.js
index 76c9f90f145b0..0aa04f31130b2 100644
--- a/www/src/components/showcase-details.js
+++ b/www/src/components/showcase-details.js
@@ -1,4 +1,5 @@
import React from "react"
+import { graphql } from "gatsby"
import Helmet from "react-helmet"
import url from "url"
import hex2rgba from "hex2rgba"
diff --git a/www/src/components/sidebar-body.js b/www/src/components/sidebar-body.js
deleted file mode 100644
index e033fe25d04ed..0000000000000
--- a/www/src/components/sidebar-body.js
+++ /dev/null
@@ -1,265 +0,0 @@
-import React from "react"
-import { Link } from "gatsby"
-import hex2rgba from "hex2rgba"
-
-import { rhythm, scale, options } from "../utils/typography"
-import presets, { colors } from "../utils/presets"
-
-const Section = props => (
-
-
- {props.title}
-
-
-
-)
-
-const SectionLinks = props => {
- const listStyles = {
- listStyle: `none`,
- margin: 0,
- padding: 0,
- fontFamily: options.headerFontFamily.join(`,`),
- }
-
- return (
- s in the "Tutorial" section
- "& ul": {
- ...listStyles,
- },
- }}
- >
- {props.items.map((item, index) => (
-
- ))}
-
- )
-}
-
-const SectionLink = props => {
- // Don't show the main docs link on mobile as we put these
- // links on that main docs page so it's confusing to have
- // the page link to itself.
- if (props.isInline && props.node.link === `/docs/`) {
- return null
- }
-
- let childnodes = null
- if (props.children) {
- childnodes = props.children.map((childnode, index) => (
-
- ))
- }
-
- const item = props.node
-
- // If the last character is a * then the doc page is still in draft
- const isDraft = item.title.slice(-1) === `*`
- const title = isDraft ? item.title.slice(0, -1) : item.title
- const isTutorialFirstLevel = props.isTutorial && !props.isNested
-
- const styles = {
- listItem: {
- marginBottom: isTutorialFirstLevel
- ? rhythm(1)
- : options.blockMarginBottom / 2,
- lineHeight: 1.3,
- paddingTop: rhythm(1 / 8),
- paddingBottom: rhythm(1 / 8),
- },
- linkDefault: {
- position: `relative`,
- borderBottom: `none`,
- boxShadow: `none`,
- fontWeight: isTutorialFirstLevel ? `bold` : `normal`,
- color: isDraft ? colors.gray.calm : colors.gray.text,
- fontStyle: isDraft ? `italic` : false,
- "&:before": {
- content: ` `,
- height: 4,
- width: 4,
- borderRadius: `100%`,
- top: `.5em`,
- left: `-.7em`,
- fontWeight: `normal`,
- position: `absolute`,
- transform: `scale(0.1)`,
- transition: `all ${presets.animation.speedDefault} ${
- presets.animation.curveDefault
- }`,
- [presets.Hd]: {
- height: 6,
- width: 6,
- top: `.65em`,
- marginTop: -3,
- left: `-1em`,
- },
- },
- },
- linkActive: {
- opacity: 1,
- color: colors.gatsby,
- fontWeight: `bold`,
- "&:before": {
- background: colors.gatsby,
- transform: `scale(1)`,
- },
- },
- }
-
- const linkStyle = props.isNested
- ? {
- ...styles.listItem,
- "& .nav-link": {
- ...styles.linkDefault,
- color: isDraft ? colors.gray.calm : colors.gray.text,
- },
- "& .nav-link-active": {
- ...styles.linkActive,
- color: isDraft ? colors.gray.calm : colors.gray.text,
- fontWeight: `normal`,
- "&:before": {
- display: `none`,
- },
- },
- }
- : {
- ...styles.listItem,
- "& > .nav-link": {
- ...styles.linkDefault,
- },
- "& > .nav-link-active": {
- ...styles.linkActive,
- },
- }
-
- return (
- -
- {item.link.charAt(0) === `#` ? (
-
- {title}
-
- ) : (
-
- {title}
-
- )}
- {childnodes ?
{childnodes}
: null}
-
- )
-}
-
-class SidebarBody extends React.Component {
- render() {
- const menu = this.props.yaml
- const isInline = this.props.inline
-
- // Use original sizes on mobile as the text is inline
- // but smaller on > tablet so as not to compete with body text.
- const fontSize = isInline ? scale(0).fontSize : scale(-2 / 10).fontSize
- const headerStyles = isInline
- ? {
- fontSize: scale(2 / 5).fontSize,
- }
- : {
- fontSize: scale(-2 / 5).fontSize,
- color: colors.lilac,
- textTransform: `uppercase`,
- letterSpacing: `.15em`,
- fontWeight: `normal`,
- }
-
- return (
-
- {menu.map((section, index) => (
-
-
-
- ))}
-
- )
- }
-}
-
-export default SidebarBody
diff --git a/www/src/components/sidebar/body.js b/www/src/components/sidebar/body.js
new file mode 100644
index 0000000000000..ca1d1a8d6014b
--- /dev/null
+++ b/www/src/components/sidebar/body.js
@@ -0,0 +1,105 @@
+import React from "react"
+
+import Section from "./section"
+import presets, { colors } from "../../utils/presets"
+import { options, rhythm, scale } from "../../utils/typography"
+
+class SidebarBody extends React.Component {
+ constructor(props, context) {
+ super(props, context)
+
+ let state = {
+ openSectionHash: {},
+ }
+
+ if (props.sectionList.length === 1) {
+ state.openSectionHash[props.sectionList.title] = true
+ } else {
+ props.sectionList.forEach(child => {
+ state.openSectionHash[child.title] =
+ props.defaultActiveSection.title === child.title ? true : false
+ })
+ }
+
+ this.state = state
+ }
+
+ _toggleSection(section) {
+ const { openSectionHash } = this.state
+ this.setState({
+ openSectionHash: {
+ ...openSectionHash,
+ [section.title]: !openSectionHash[section.title],
+ },
+ })
+ }
+
+ _expandAll = () => {
+ let openSectionHash = { ...this.state.openSectionHash }
+ Object.keys(openSectionHash).forEach(k => (openSectionHash[k] = true))
+ this.setState({ openSectionHash })
+ }
+
+ render() {
+ const {
+ createLink,
+ location,
+ sectionList,
+ closeParentMenu,
+ enableScrollSync,
+ activeItemHash,
+ } = this.props
+ let { openSectionHash } = this.state
+ const singleSection = sectionList.length === 1
+
+ return (
+
+ {sectionList.length > 1 && (
+
+
+
+ )}
+ {sectionList.map((section, index) => (
+ this._toggleSection(section)}
+ section={section}
+ hideSectionTitle={singleSection}
+ activeItemHash={activeItemHash}
+ isScrollSync={enableScrollSync}
+ singleSection={singleSection}
+ />
+ ))}
+
+ )
+ }
+}
+
+export default SidebarBody
diff --git a/www/src/components/sidebar/chevron-svg.js b/www/src/components/sidebar/chevron-svg.js
new file mode 100644
index 0000000000000..f5c32acd3f976
--- /dev/null
+++ b/www/src/components/sidebar/chevron-svg.js
@@ -0,0 +1,31 @@
+import React from "react"
+
+const ChevronSvg = ({ size = 10, cssProps = {} }) => (
+
+)
+
+export default ChevronSvg
diff --git a/www/src/components/sidebar/scroll-sync-body.js b/www/src/components/sidebar/scroll-sync-body.js
new file mode 100644
index 0000000000000..930aaa6987a5d
--- /dev/null
+++ b/www/src/components/sidebar/scroll-sync-body.js
@@ -0,0 +1,109 @@
+import React, { Component } from "react"
+import Body from "./body"
+
+class ScrollSyncSection extends Component {
+ constructor(props, context) {
+ super(props, context)
+
+ this.state = {
+ activeItemHash: `NONE`,
+ itemTopOffsets: [],
+ }
+
+ this.calculateItemTopOffsets = this.calculateItemTopOffsets.bind(this)
+ this.handleResize = this.handleResize.bind(this)
+ this.handleScroll = this.handleScroll.bind(this)
+ }
+
+ componentDidMount() {
+ this.calculateItemTopOffsets()
+
+ window.addEventListener(`resize`, this.handleResize)
+ window.addEventListener(`scroll`, this.handleScroll)
+ }
+
+ componentWillUnmount() {
+ window.removeEventListener(`resize`, this.handleResize)
+ window.removeEventListener(`scroll`, this.handleScroll)
+ }
+
+ calculateItemTopOffsets() {
+ const { sectionList } = this.props
+
+ const itemIds = _getItemIds(sectionList)
+ this.setState({
+ itemTopOffsets: _getElementTopOffsetsById(itemIds),
+ })
+ }
+
+ handleResize() {
+ this.calculateItemTopOffsets()
+ this.handleScroll()
+ }
+
+ handleScroll() {
+ const { itemTopOffsets } = this.state
+ const item = itemTopOffsets.find((itemTopOffset, i) => {
+ const nextItemTopOffset = itemTopOffsets[i + 1]
+
+ return nextItemTopOffset
+ ? window.scrollY >= itemTopOffset.offsetTop &&
+ window.scrollY < nextItemTopOffset.offsetTop
+ : window.scrollY >= itemTopOffset.offsetTop
+ })
+
+ this.setState({
+ activeItemHash: item ? item.hash : `NONE`,
+ })
+ }
+
+ render() {
+ const { activeItemHash } = this.state
+ return (
+
+
+
+ )
+ }
+}
+
+const _getItemIds = sectionList => {
+ let list = []
+
+ sectionList.forEach(section => {
+ let sectionItems = section.items
+ .map(item => {
+ let subItemIds = []
+ if (item.subitems) {
+ subItemIds = item.subitems.map(subitem => subitem.hash)
+ }
+ return [item.hash, ...subItemIds]
+ })
+ .reduce((prev, current) => prev.concat(current))
+
+ list.push(sectionItems)
+ })
+
+ return [].concat(...list)
+}
+
+const _getElementTopOffsetsById = ids => {
+ const banner = document.getElementsByClassName(`banner`)
+ const navigation = document.getElementsByClassName(`navigation`)
+ const bannerHeight = banner[0].offsetHeight || 0
+ const navigationHeight = navigation[0].offsetHeight || 0
+
+ return ids
+ .map(hash => {
+ const element = document.getElementById(hash)
+ return element
+ ? {
+ hash,
+ offsetTop: element.offsetTop - bannerHeight - navigationHeight,
+ }
+ : null
+ })
+ .filter(item => item)
+}
+
+export default ScrollSyncSection
diff --git a/www/src/components/sidebar/section-title.js b/www/src/components/sidebar/section-title.js
new file mode 100644
index 0000000000000..0ee8f412f485a
--- /dev/null
+++ b/www/src/components/sidebar/section-title.js
@@ -0,0 +1,30 @@
+import React from "react"
+import presets, { colors } from "../../utils/presets"
+import { scale, options } from "../../utils/typography"
+
+const SectionTitle = ({ children, isActive }) => (
+
+ {children}
+
+)
+
+export default SectionTitle
diff --git a/www/src/components/sidebar/section.js b/www/src/components/sidebar/section.js
new file mode 100644
index 0000000000000..939318d462ca4
--- /dev/null
+++ b/www/src/components/sidebar/section.js
@@ -0,0 +1,246 @@
+import React from "react"
+
+import getActiveItem from "../../utils/sidebar/get-active-item"
+import presets, { colors } from "../../utils/presets"
+import { scale, rhythm } from "../../utils/typography"
+
+import SectionTitle from "./section-title"
+import ChevronSvg from "./chevron-svg"
+
+const horizontalPadding = rhythm(3 / 4)
+const horizonalPaddingDesktop = rhythm(3 / 2)
+
+const ToggleSectionButton = ({
+ title,
+ isActive,
+ uid,
+ hideSectionTitle,
+ onSectionTitleClick,
+}) => (
+
+)
+
+const Title = ({ title }) => (
+
+ {title}
+
+)
+
+class Section extends React.Component {
+ state = { uid: (`` + Math.random()).replace(/\D/g, ``) }
+
+ _isChildItemActive = (item, activeItemId) => {
+ if (item.subitems) {
+ const matches = item.subitems.filter(function(subitem) {
+ return subitem.link === activeItemId && item.link === subitem.parentLink
+ })
+
+ return matches.length >= 1
+ }
+ }
+
+ render() {
+ const {
+ activeItemHash,
+ createLink,
+ location,
+ onLinkClick,
+ onSectionTitleClick,
+ section,
+ hideSectionTitle,
+ singleSection,
+ } = this.props
+ const uid = `section_` + this.state.uid
+ const activeItemId = getActiveItem(section, location, activeItemHash)
+ const SectionTitleComponent = section.disableAccordions
+ ? Title
+ : ToggleSectionButton
+
+ const isActive = this.props.isActive || section.disableAccordions
+
+ return (
+
+
+
+ {section.items.map(item => (
+ -
+ {createLink({
+ isActive:
+ item.link === activeItemId ||
+ this._isChildItemActive(item, activeItemId),
+ item,
+ section,
+ location,
+ onLinkClick,
+ isParentOfActiveItem: this._isChildItemActive(
+ item,
+ activeItemId
+ ),
+ })}
+ {item.subitems && (
+
+ {item.subitems.map(subitem => (
+ -
+ {createLink({
+ isActive: subitem.link === activeItemId,
+ item: subitem,
+ location,
+ onLinkClick,
+ section,
+ isSubsectionLink: true,
+ })}
+
+ ))}
+
+ )}
+
+ ))}
+
+
+ )
+ }
+}
+
+export default Section
+
+const styles = {
+ ul: {
+ listStyle: `none`,
+ margin: 0,
+ marginBottom: rhythm(1 / 2),
+ position: `relative`,
+ },
+ tutorialSubsection: {
+ "&:before": {
+ background: colors.ui.bright,
+ content: ` `,
+ height: `100%`,
+ left: `.275rem`,
+ position: `absolute`,
+ width: 1,
+ },
+ },
+ button: {
+ backgroundColor: `transparent`,
+ border: 0,
+ cursor: `pointer`,
+ padding: 0,
+ paddingLeft: horizontalPadding,
+ paddingRight: horizontalPadding,
+ position: `relative`,
+ textAlign: `left`,
+ width: `100%`,
+ [presets.Desktop]: {
+ paddingLeft: horizonalPaddingDesktop,
+ paddingRight: horizonalPaddingDesktop,
+ },
+ },
+ liActive: {
+ background: colors.ui.light,
+ "&&": {
+ marginTop: rhythm(1 / 2),
+ marginBottom: rhythm(1),
+ paddingTop: rhythm(1 / 2),
+ },
+ },
+}
diff --git a/www/src/components/sidebar/sidebar.js b/www/src/components/sidebar/sidebar.js
new file mode 100644
index 0000000000000..ad9f06f5b99ef
--- /dev/null
+++ b/www/src/components/sidebar/sidebar.js
@@ -0,0 +1,176 @@
+import React, { Component } from "react"
+import ScrollSyncBody from "./scroll-sync-body"
+import SidebarBody from "./body"
+import ChevronSvg from "./chevron-svg"
+import presets, { colors } from "../../utils/presets"
+import { rhythm } from "../../utils/typography"
+
+class StickyResponsiveSidebar extends Component {
+ constructor(props) {
+ super(props)
+
+ this.state = {
+ open: false,
+ }
+ }
+
+ _openNavMenu = () => {
+ this.setState({ open: !this.state.open })
+ }
+
+ _closeNavMenu = () => {
+ this.setState({ open: false })
+ }
+
+ render() {
+ const { open } = this.state
+ const BodyComponent = this.props.enableScrollSync
+ ? ScrollSyncBody
+ : SidebarBody
+
+ const iconOffset = open ? 8 : -4
+ const menuOpacity = open ? 1 : 0
+ const menuOffset = open ? 0 : rhythm(10)
+
+ const horizontalPadding = rhythm(3 / 4)
+ const horizonalPaddingDesktop = rhythm(3 / 2)
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+ }
+}
+
+export default StickyResponsiveSidebar
+
+const sidebarStyles = {
+ width: rhythm(10),
+ position: `fixed`,
+ overflowY: `auto`,
+ WebkitOverflowScrolling: `touch`,
+ "::-webkit-scrollbar": {
+ width: `6px`,
+ height: `6px`,
+ },
+ "::-webkit-scrollbar-thumb": {
+ background: colors.ui.bright,
+ },
+ "::-webkit-scrollbar-track": {
+ background: colors.ui.light,
+ },
+}
diff --git a/www/src/data/sidebars/doc-links.yaml b/www/src/data/sidebars/doc-links.yaml
index ac7893becc630..c887bb47f5ee7 100644
--- a/www/src/data/sidebars/doc-links.yaml
+++ b/www/src/data/sidebars/doc-links.yaml
@@ -1,130 +1,128 @@
- title: Quick Start
items:
- title: Getting Started
- link: /docs/
+ link: /
- title: Starters
- link: /docs/gatsby-starters/
+ link: /gatsby-starters/
- title: Deploying
- link: /docs/deploy-gatsby/
+ link: /deploy-gatsby/
- title: Community
- link: /docs/community/
+ link: /community/
- title: Awesome Gatsby
- link: /docs/awesome-gatsby/
+ link: /awesome-gatsby/
- title: Core Concepts
items:
- title: Building with Components
- link: /docs/building-with-components/
+ link: /building-with-components/
- title: Lifecycle APIs
- link: /docs/gatsby-lifecycle-apis/
+ link: /gatsby-lifecycle-apis/
- title: Plugins
- link: /docs/plugins/
+ link: /plugins/
- title: PRPL Pattern
- link: /docs/prpl-pattern/
+ link: /prpl-pattern/
- title: Querying Data with GraphQL
- link: /docs/querying-with-graphql/
+ link: /querying-with-graphql/
- title: Guides
items:
- title: Adding a 404 Page
- link: /docs/add-404-page/
+ link: /add-404-page/
- title: Adding Images, Fonts, and Files
- link: /docs/adding-images-fonts-files/
+ link: /adding-images-fonts-files/
- title: Adding Images to a WordPress Site
- link: /docs/image-tutorial/
+ link: /image-tutorial/
- title: Babel.js
- link: /docs/babel/
+ link: /babel/
- title: Browser Support
- link: /docs/browser-support/
+ link: /browser-support/
- title: Building Apps with Gatsby
- link: /docs/building-apps-with-gatsby/
+ link: /building-apps-with-gatsby/
- title: Caching
- link: /docs/caching/
+ link: /caching/
- title: Creating and Modifying Pages
- link: /docs/creating-and-modifying-pages/
+ link: /creating-and-modifying-pages/
- title: Create a Source Plugin
- link: /docs/create-source-plugin/
+ link: /create-source-plugin/
- title: Custom webpack config
- link: /docs/add-custom-webpack-config/
+ link: /add-custom-webpack-config/
- title: Customizing html.js
- link: /docs/custom-html/
+ link: /custom-html/
- title: Debugging HTML Builds
- link: /docs/debugging-html-builds/
+ link: /debugging-html-builds/
- title: Debugging Replace Renderer API
- link: /docs/debugging-replace-renderer-api/
+ link: /debugging-replace-renderer-api/
- title: E-commerce Tutorial
- link: /docs/ecommerce-tutorial/
+ link: /ecommerce-tutorial/
- title: Environment Variables
- link: /docs/environment-variables/
+ link: /environment-variables/
- title: Gatsby on Windows
- link: /docs/gatsby-on-windows/
+ link: /gatsby-on-windows/
- title: Local HTTPS
- link: /docs/local-https/
+ link: /local-https/
- title: Managing Content with Netlify CMS
- link: /docs/netlify-cms/
+ link: /netlify-cms/
- title: How Gatsby Works with GitHub Pages
- link: /docs/how-gatsby-works-with-github-pages/
+ link: /how-gatsby-works-with-github-pages/
- title: Migrating from v1 to v2
- link: /docs/migrating-from-v1-to-v2/
+ link: /migrating-from-v1-to-v2/
- title: Migrating from v0 to v1
- link: /docs/migrating-from-v0-to-v1/
+ link: /migrating-from-v0-to-v1/
- title: Path Prefix
- link: /docs/path-prefix/
+ link: /path-prefix/
- title: Plugin Authoring
- link: /docs/plugin-authoring/
+ link: /plugin-authoring/
- title: Proxying API Requests
- link: /docs/api-proxy/
+ link: /api-proxy/
- title: Querying data with StaticQuery
- link: /docs/static-query/
+ link: /static-query/
- title: Search Engine Optimization (SEO)
- link: /docs/seo/
+ link: /seo/
- title: Source Plugin Tutorial
- link: /docs/source-plugin-tutorial/
+ link: /source-plugin-tutorial/
- title: Using CSS-in-JS Library Glamor
- link: /docs/glamor/
+ link: /glamor/
- title: Using CSS-in-JS Library Styled Components
- link: /docs/styled-components/
+ link: /styled-components/
- title: Adding Markdown Pages
- link: /docs/adding-markdown-pages/
+ link: /adding-markdown-pages/
- title: Adding a List of Markdown Blog Posts
- link: /docs/adding-a-list-of-markdown-blog-posts/
+ link: /adding-a-list-of-markdown-blog-posts/
- title: Adding Tags and Categories to Blog Posts
- link: /docs/adding-tags-and-categories-to-blog-posts/
+ link: /adding-tags-and-categories-to-blog-posts/
- title: Adding search to your Gatsby website
- link: /docs/adding-search/
+ link: /adding-search/
- title: Working With Images in Gatsby
- link: /docs/working-with-images/
+ link: /working-with-images/
- title: Wordpress Source Plugin Tutorial
- link: /docs/wordpress-source-plugin-tutorial/
+ link: /wordpress-source-plugin-tutorial/
- title: Creating Dynamically-Rendered Navigation*
- link: /docs/creating-dynamically-rendered-navigation/
+ link: /creating-dynamically-rendered-navigation/
- title: Dropping Images into Static Folders*
- link: /docs/dropping-images-into-static-folders/
+ link: /dropping-images-into-static-folders/
- title: Reference
items:
- title: Node Interface
- link: /docs/node-interface/
+ link: /node-interface/
- title: API Specification
- link: /docs/api-specification/
+ link: /api-specification/
- title: Actions
- link: /docs/actions/
+ link: /actions/
- title: Gatsby Browser APIs
- link: /docs/browser-apis/
+ link: /browser-apis/
- title: Gatsby Node APIs
- link: /docs/node-apis/
+ link: /node-apis/
- title: Gatsby SSR APIs
- link: /docs/ssr-apis/
+ link: /ssr-apis/
- title: Gatsby Config
- link: /docs/gatsby-config/
+ link: /gatsby-config/
- title: GraphQL Reference
- link: /docs/graphql-reference/
+ link: /graphql-reference/
- title: Contributing
items:
- title: How to Contribute
- link: /docs/how-to-contribute/
+ link: /how-to-contribute/
- title: How to File an Issue
- link: /docs/how-to-file-an-issue/
+ link: /how-to-file-an-issue/
- title: Gatsby Style Guide
- link: /docs/gatsby-style-guide/
+ link: /gatsby-style-guide/
- title: Design Principles*
- link: /docs/design-principles/
- - title: Site Showcase Submissions
- link: /docs/site-showcase-submissions/
+ link: /design-principles/
diff --git a/www/src/data/sidebars/features-links.yaml b/www/src/data/sidebars/features-links.yaml
index 77e9fc81ff6cf..9dc78fd45d1d3 100644
--- a/www/src/data/sidebars/features-links.yaml
+++ b/www/src/data/sidebars/features-links.yaml
@@ -1,72 +1,72 @@
- title: Introduction
items:
- title: Introduction
- link: "#introduction"
+ link: /#introduction
- title: Legend
- link: "#legend"
+ link: /#legend
- title: Performance
items:
- title: Static content
- link: "#static-content"
+ link: /#static-content
- title: CDN
- link: "#cdn"
+ link: /#cdn
- title: AMP support
- link: "#amp-support"
+ link: /#amp-support
- title: Offline access
- link: "#offline-access"
+ link: /#offline-access
- title: Prefetch linked pages
- link: "#prefetch-linked-pages"
+ link: /#prefetch-linked-pages
- title: Page caching
- link: "#page-caching"
+ link: /#page-caching
- title: No extraneous code fetching
- link: "#no-extraneous-code-fetching"
+ link: /#no-extraneous-code-fetching
- title: Progressive image loading
- link: "#progressive-image-loading"
+ link: /#progressive-image-loading
- title: Responsive image loading
- link: "#responsive-image-loading"
+ link: /#responsive-image-loading
- title: Inlines critical CSS
- link: "#inlines-critical-css"
+ link: /#inlines-critical-css
- title: Font self-hosting
- link: "#font-self-hosting"
+ link: /#font-self-hosting
- title: Developer Experience
items:
- title: Serverless
- link: "#serverless"
+ link: /#serverless
- title: Export as Code
- link: "#export-as-code"
+ link: /#export-as-code
- title: Refresh or link to preview
- link: "#refresh-or-link-to-preview"
+ link: /#refresh-or-link-to-preview
- title: Hot reload content
- link: "#hot-reload-content"
+ link: /#hot-reload-content
- title: Hot reload code
- link: "#hot-reload-code"
+ link: /#hot-reload-code
- title: Componentization
- link: "#componentization"
+ link: /#componentization
- title: One-way data binding
- link: "#one-way-data-binding"
+ link: /#one-way-data-binding
- title: Declarative API data queries (GraphQL)
- link: "#declarative-api-data-queries-(graphql)"
+ link: /#declarative-api-data-queries-(graphql)
- title: Declarative UI
- link: "#declarative-ui"
+ link: /#declarative-ui
- title: Asset pipelines
- link: "#asset-pipelines"
+ link: /#asset-pipelines
- title: CSS Extensions (eg Sass)
- link: "#css-extensions-(eg-sass)"
+ link: /#css-extensions-(eg-sass)
- title: Advanced Javascript syntax
- link: "#advanced-javascript-syntax"
+ link: /#advanced-javascript-syntax
- title: Ecosystem
items:
- title: Component ecosystem
- link: "#component-ecosystem"
+ link: /#component-ecosystem
- title: Hosted option
- link: "#hosted-option"
+ link: /#hosted-option
- title: Theme ecosystem
- link: "#theme-ecosystem"
+ link: /#theme-ecosystem
- title: Design
items:
- title: Programmatic Design
- link: "#programmatic-design"
+ link: /#programmatic-design
- title: Design systems
- link: "#design-systems"
+ link: /#design-systems
- title: Component library
- link: "#component-library"
+ link: /#component-library
diff --git a/www/src/data/sidebars/tutorial-links.yaml b/www/src/data/sidebars/tutorial-links.yaml
index 5227898d21cc6..4019d68a2cd1e 100644
--- a/www/src/data/sidebars/tutorial-links.yaml
+++ b/www/src/data/sidebars/tutorial-links.yaml
@@ -1,80 +1,80 @@
- title: Tutorial
items:
- title: Introduction
- link: /tutorial/
+ link: /
- title: 0. Programming basics
- link: /tutorial/part-zero/
+ link: /part-zero/
- title: 1. Introduction to Gatsby basics
- link: /tutorial/part-one/
- items:
+ link: /part-one/
+ subitems:
- title: Check environment
- link: /tutorial/part-one/#check-your-development-environment
+ link: /part-one/#check-your-development-environment
- title: Install the "Hello World" starter
- link: /tutorial/part-one/#install-the-hello-world-starter
+ link: /part-one/#install-the-hello-world-starter
- title: Linking between pages
- link: /tutorial/part-one/#linking-between-pages
+ link: /part-one/#linking-between-pages
- title: Interactive page
- link: /tutorial/part-one/#interactive-page
+ link: /part-one/#interactive-page
- title: Deploying Gatsby.js websites
- link: /tutorial/part-one/#deploying-gatsbyjs-websites
+ link: /part-one/#deploying-gatsbyjs-websites
- title: 2. Introduction to using CSS in Gatsby
- link: /tutorial/part-two/
- items:
+ link: /part-two/
+ subitems:
- title: Building with components
- link: /tutorial/part-two/#building-with-components
+ link: /part-two/#building-with-components
- title: Creating Global Styles
- link: /tutorial/part-two/#creating-global-styles
+ link: /part-two/#creating-global-styles
- title: Typography.js
- link: /tutorial/part-two/#typographyjs
+ link: /part-two/#typographyjs
- title: Gatsby Plugins
- link: /tutorial/part-two/#gatsby-plugins
+ link: /part-two/#gatsby-plugins
- title: Component CSS
- link: /tutorial/part-two/#component-css
+ link: /part-two/#component-css
- title: CSS Modules
- link: /tutorial/part-two/#css-modules
+ link: /part-two/#css-modules
- title: 3. Creating nested layout components
- link: /tutorial/part-three/
- items:
+ link: /part-three/
+ subitems:
- title: Our first layout component
- link: /tutorial/part-three/#our-first-layout-component
+ link: /part-three/#our-first-layout-component
- title: 4. Querying for data in a blog
- link: /tutorial/part-four/
- items:
+ link: /part-four/
+ subitems:
- title: Recap of the first half of the tutorial
- link: /tutorial/part-four/#recap-of-first-half-of-the-tutorial
+ link: /part-four/#recap-of-first-half-of-the-tutorial
- title: Data in Gatsby
- link: /tutorial/part-four/#data-in-gatsby
+ link: /part-four/#data-in-gatsby
- title: How Gatsby's data layer uses GraphQL to pull data into components
- link: /tutorial/part-four/#how-gatsbys-data-layer-uses-graphql-to-pull-data-into-components
+ link: /part-four/#how-gatsbys-data-layer-uses-graphql-to-pull-data-into-components
- title: Our first GraphQL query
- link: /tutorial/part-four/#our-first-graphql-query
+ link: /part-four/#our-first-graphql-query
- title: 5. Source plugins and rendering queried data
- link: /tutorial/part-five/
- items:
+ link: /part-five/
+ subitems:
- title: Introducing GraphiQL
- link: /tutorial/part-five/#introducing-graphiql
+ link: /part-five/#introducing-graphiql
- title: Source Plugins
- link: /tutorial/part-five/#source-plugins
+ link: /part-five/#source-plugins
- title: Build a page with a GraphQL query
- link: /tutorial/part-five/#build-a-page-with-a-graphql-query
+ link: /part-five/#build-a-page-with-a-graphql-query
- title: 6. Transformer plugins
- link: /tutorial/part-six/
- items:
+ link: /part-six/
+ subitems:
- title: Transformer plugins
- link: /tutorial/part-six/#transformer-plugins
+ link: /part-six/#transformer-plugins
- title: Create a list of our site's markdown files
- link: /tutorial/part-six/#create-a-list-of-our-sites-markdown-files-in-srcpagesindexjs
+ link: /part-six/#create-a-list-of-our-sites-markdown-files-in-srcpagesindexjs
- title: 7. Programmatically create pages from data
- link: /tutorial/part-seven/
- items:
+ link: /part-seven/
+ subitems:
- title: Creating slugs for pages
- link: /tutorial/part-seven/#creating-slugs-for-pages
+ link: /part-seven/#creating-slugs-for-pages
- title: Creating pages
- link: /tutorial/part-seven/#creating-pages
+ link: /part-seven/#creating-pages
- title: 8. Preparing a site to go live
- link: /tutorial/part-eight/
- items:
+ link: /part-eight/
+ subitems:
- title: Creating slugs for pages
- link: /tutorial/part-eight/#creating-slugs-for-pages
+ link: /part-eight/#creating-slugs-for-pages
- title: Creating pages
- link: /tutorial/part-eight/#creating-pages
+ link: /part-eight/#creating-pages
diff --git a/www/src/html.js b/www/src/html.js
index 6d0b2ad921246..fe8a28f6f6a4c 100644
--- a/www/src/html.js
+++ b/www/src/html.js
@@ -6,6 +6,11 @@ export default class HTML extends React.Component {
return (
+
-
+
{this.props.postBodyComponents}
-
)
diff --git a/www/src/pages/blog/index.js b/www/src/pages/blog/index.js
index c13651d4fe1fe..19c8ec72e2704 100644
--- a/www/src/pages/blog/index.js
+++ b/www/src/pages/blog/index.js
@@ -1,4 +1,5 @@
import React from "react"
+import { graphql } from "gatsby"
import Helmet from "react-helmet"
import Layout from "../../components/layout"
diff --git a/www/src/pages/blog/tags.js b/www/src/pages/blog/tags.js
index e1f832b57a38d..9315561e3c17a 100644
--- a/www/src/pages/blog/tags.js
+++ b/www/src/pages/blog/tags.js
@@ -1,5 +1,6 @@
import React from "react"
import PropTypes from "prop-types"
+import { graphql } from "gatsby"
// Utilities
import kebabCase from "lodash/kebabCase"
diff --git a/www/src/pages/docs/actions.js b/www/src/pages/docs/actions.js
index f4022512b4784..3660402a05628 100644
--- a/www/src/pages/docs/actions.js
+++ b/www/src/pages/docs/actions.js
@@ -1,4 +1,5 @@
import React from "react"
+import { graphql } from "gatsby"
import Helmet from "react-helmet"
import sortBy from "lodash/sortBy"
@@ -6,7 +7,8 @@ import Functions from "../../components/function-list"
import { rhythm, scale } from "../../utils/typography"
import Layout from "../../components/layout"
import Container from "../../components/container"
-import docsSidebar from "../../data/sidebars/doc-links.yaml"
+import { sectionListDocs } from "../../utils/sidebar/section-list"
+import { createLinkDocs } from "../../utils/sidebar/create-link"
class ActionCreatorsDocs extends React.Component {
render() {
@@ -16,7 +18,11 @@ class ActionCreatorsDocs extends React.Component {
).filter(func => func.name !== `deleteNodes`)
return (
-
+
Actions
diff --git a/www/src/pages/docs/browser-apis.js b/www/src/pages/docs/browser-apis.js
index 6ce5f1d21cefd..05c899739a498 100644
--- a/www/src/pages/docs/browser-apis.js
+++ b/www/src/pages/docs/browser-apis.js
@@ -1,4 +1,5 @@
import React from "react"
+import { graphql } from "gatsby"
import Helmet from "react-helmet"
import sortBy from "lodash/sortBy"
@@ -6,7 +7,8 @@ import Functions from "../../components/function-list"
import { rhythm, scale } from "../../utils/typography"
import Layout from "../../components/layout"
import Container from "../../components/container"
-import docsSidebar from "../../data/sidebars/doc-links.yaml"
+import { sectionListDocs } from "../../utils/sidebar/section-list"
+import { createLinkDocs } from "../../utils/sidebar/create-link"
class BrowserAPIDocs extends React.Component {
render() {
@@ -16,7 +18,11 @@ class BrowserAPIDocs extends React.Component {
)
return (
-
+
Browser APIs
diff --git a/www/src/pages/docs/index.js b/www/src/pages/docs/index.js
index 2e6e143a8ae86..6fcf5c20b38fd 100644
--- a/www/src/pages/docs/index.js
+++ b/www/src/pages/docs/index.js
@@ -3,7 +3,8 @@ import { Link } from "gatsby"
import Helmet from "react-helmet"
import Layout from "../../components/layout"
-import docsSidebar from "../../data/sidebars/doc-links.yaml"
+import { sectionListDocs } from "../../utils/sidebar/section-list"
+import { createLinkDocs } from "../../utils/sidebar/create-link"
import Container from "../../components/container"
import DocSearchContent from "../../components/docsearch-content"
import presets from "../../utils/presets"
@@ -11,7 +12,11 @@ import presets from "../../utils/presets"
class IndexRoute extends React.Component {
render() {
return (
-
+
diff --git a/www/src/pages/docs/node-apis.js b/www/src/pages/docs/node-apis.js
index 3843b55c3ce9c..a261194ec0278 100644
--- a/www/src/pages/docs/node-apis.js
+++ b/www/src/pages/docs/node-apis.js
@@ -1,4 +1,5 @@
import React from "react"
+import { graphql } from "gatsby"
import Helmet from "react-helmet"
import sortBy from "lodash/sortBy"
@@ -6,7 +7,8 @@ import Functions from "../../components/function-list"
import { rhythm, scale } from "../../utils/typography"
import Layout from "../../components/layout"
import Container from "../../components/container"
-import docsSidebar from "../../data/sidebars/doc-links.yaml"
+import { sectionListDocs } from "../../utils/sidebar/section-list"
+import { createLinkDocs } from "../../utils/sidebar/create-link"
class NodeAPIDocs extends React.Component {
render() {
@@ -15,7 +17,11 @@ class NodeAPIDocs extends React.Component {
func => func.name
)
return (
-
+
Node APIs
diff --git a/www/src/pages/docs/ssr-apis.js b/www/src/pages/docs/ssr-apis.js
index aa2d022e5ccb8..acb4056f282c3 100644
--- a/www/src/pages/docs/ssr-apis.js
+++ b/www/src/pages/docs/ssr-apis.js
@@ -1,4 +1,5 @@
import React from "react"
+import { graphql } from "gatsby"
import Helmet from "react-helmet"
import sortBy from "lodash/sortBy"
@@ -6,7 +7,8 @@ import Functions from "../../components/function-list"
import { rhythm, scale } from "../../utils/typography"
import Layout from "../../components/layout"
import Container from "../../components/container"
-import docsSidebar from "../../data/sidebars/doc-links.yaml"
+import { sectionListDocs } from "../../utils/sidebar/section-list"
+import { createLinkDocs } from "../../utils/sidebar/create-link"
class SSRAPIs extends React.Component {
render() {
@@ -15,7 +17,11 @@ class SSRAPIs extends React.Component {
func => func.name
)
return (
-
+
SSR APIs
diff --git a/www/src/pages/features.js b/www/src/pages/features.js
index 7936d2e86e244..06b3357355ea4 100644
--- a/www/src/pages/features.js
+++ b/www/src/pages/features.js
@@ -1,11 +1,13 @@
import React, { Component } from "react"
+import { graphql } from "gatsby"
import Helmet from "react-helmet"
import Layout from "../components/layout"
import EvaluationTable from "../components/evaluation-table"
import EvaluationCell from "../components/evaluation-cell"
import FuturaParagraph from "../components/futura-paragraph"
-import featuresSidebar from "../data/sidebars/features-links.yaml"
+import { createLinkTutorial } from "../utils/sidebar/create-link"
+import { sectionListFeatures } from "../utils/sidebar/section-list"
import Container from "../components/container"
import { options, rhythm } from "../utils/typography"
import presets, { colors } from "../utils/presets"
@@ -201,7 +203,12 @@ class FeaturesPage extends Component {
)
return (
-
+
@@ -963,7 +965,7 @@ const styles = {
position: `sticky`,
top: 0,
[presets.Desktop]: {
- top: `calc(${presets.headerHeight} - 1px)`,
+ top: `calc(${presets.headerHeight} + ${presets.bannerHeight} - 1px)`,
},
},
scrollbar: {
diff --git a/www/src/templates/tags.js b/www/src/templates/tags.js
index b2ebad326e8d0..fa84db97d702c 100644
--- a/www/src/templates/tags.js
+++ b/www/src/templates/tags.js
@@ -1,8 +1,8 @@
import React from "react"
import PropTypes from "prop-types"
-import Container from "../components/container"
+import { Link, graphql } from "gatsby"
-import { Link } from "gatsby"
+import Container from "../components/container"
import Layout from "../components/layout"
const Tags = ({ pageContext, data, location }) => {
diff --git a/www/src/templates/template-blog-post.js b/www/src/templates/template-blog-post.js
index b3b6aa5240372..e6f85fdb0c4eb 100644
--- a/www/src/templates/template-blog-post.js
+++ b/www/src/templates/template-blog-post.js
@@ -1,6 +1,6 @@
import React from "react"
import Helmet from "react-helmet"
-import { Link } from "gatsby"
+import { Link, graphql } from "gatsby"
import ArrowForwardIcon from "react-icons/lib/md/arrow-forward"
import ArrowBackIcon from "react-icons/lib/md/arrow-back"
import Img from "gatsby-image"
@@ -61,7 +61,7 @@ class BlogPostTemplate extends React.Component {
return (
-
+
{/* Add long list of social meta tags */}
{post.frontmatter.title}
@@ -133,17 +133,19 @@ class BlogPostTemplate extends React.Component {
flex: `0 0 auto`,
}}
>
-
+
+
+
- {post.frontmatter.author.id}
+
+ {post.frontmatter.author.id}
+
{post.frontmatter.author.bio}
diff --git a/www/src/templates/template-contributor-page.js b/www/src/templates/template-contributor-page.js
index 26a1f864d2764..73abb431a34df 100644
--- a/www/src/templates/template-contributor-page.js
+++ b/www/src/templates/template-contributor-page.js
@@ -1,4 +1,5 @@
import React from "react"
+import { graphql } from "gatsby"
import Img from "gatsby-image"
import { OutboundLink } from "gatsby-plugin-google-analytics"
diff --git a/www/src/templates/template-docs-local-packages.js b/www/src/templates/template-docs-local-packages.js
index e0dd69678ebb1..9e535fd7df987 100644
--- a/www/src/templates/template-docs-local-packages.js
+++ b/www/src/templates/template-docs-local-packages.js
@@ -1,4 +1,5 @@
import React from "react"
+import { graphql } from "gatsby"
import _ from "lodash"
import Layout from "../components/layout"
diff --git a/www/src/templates/template-docs-markdown.js b/www/src/templates/template-docs-markdown.js
index eddc5bbf6db55..369cd1548a02b 100644
--- a/www/src/templates/template-docs-markdown.js
+++ b/www/src/templates/template-docs-markdown.js
@@ -1,51 +1,48 @@
import React from "react"
import Helmet from "react-helmet"
+import { graphql } from "gatsby"
import Layout from "../components/layout"
-import docsSidebar from "../data/sidebars/doc-links.yaml"
-import tutorialSidebar from "../data/sidebars/tutorial-links.yaml"
+import {
+ createLinkDocs,
+ createLinkTutorial,
+} from "../utils/sidebar/create-link"
+import {
+ sectionListDocs,
+ sectionListTutorial,
+} from "../utils/sidebar/section-list"
import MarkdownPageFooter from "../components/markdown-page-footer"
import DocSearchContent from "../components/docsearch-content"
import Container from "../components/container"
-import { rhythm } from "../utils/typography"
class DocsTemplate extends React.Component {
render() {
const page = this.props.data.markdownRemark
+ const isDocsPage = this.props.location.pathname.slice(0, 5) === `/docs`
return (
-
-
-
-
-
- {page.frontmatter.title}
-
-
-
-
-
-
-
-
+
+
+ {page.frontmatter.title}
+
+
+
+
+
+
+
+
+
+
+
{page.frontmatter.title}
@@ -55,10 +52,10 @@ class DocsTemplate extends React.Component {
}}
/>
-
-
-
-
+
+
+
+
)
}
}
diff --git a/www/src/templates/template-docs-remote-packages.js b/www/src/templates/template-docs-remote-packages.js
index 3d81ae70003e2..6ef31ae493207 100644
--- a/www/src/templates/template-docs-remote-packages.js
+++ b/www/src/templates/template-docs-remote-packages.js
@@ -1,4 +1,5 @@
import React from "react"
+import { graphql } from "gatsby"
import Layout from "../components/layout"
import PageWithPluginSearchBar from "../components/page-with-plugin-searchbar"
diff --git a/www/src/templates/template-showcase-details.js b/www/src/templates/template-showcase-details.js
index daa37574035de..b32d497c4cdf2 100644
--- a/www/src/templates/template-showcase-details.js
+++ b/www/src/templates/template-showcase-details.js
@@ -1,5 +1,5 @@
import React from "react"
-import { push } from "gatsby"
+import { push, graphql } from "gatsby"
import ShowcaseDetails from "../components/showcase-details"
diff --git a/www/src/utils/colors.js b/www/src/utils/colors.js
index dacd63c57969c..e1cb157192302 100644
--- a/www/src/utils/colors.js
+++ b/www/src/utils/colors.js
@@ -73,6 +73,7 @@ const colors = {
dark: gray(8, 270),
copy: gray(12, 270),
calm: gray(46, 270),
+ light: gray(80, 270),
},
}
diff --git a/www/src/utils/presets.js b/www/src/utils/presets.js
index 9cfff2533e8f3..9a42cdb9ffb1a 100644
--- a/www/src/utils/presets.js
+++ b/www/src/utils/presets.js
@@ -35,4 +35,5 @@ module.exports = {
},
logoOffset: 1.8,
headerHeight: `3.5rem`,
+ bannerHeight: `2.55rem`,
}
diff --git a/www/src/utils/scroll-to-anchor.js b/www/src/utils/scroll-to-anchor.js
index ef7642ccd6020..1557746166ac4 100644
--- a/www/src/utils/scroll-to-anchor.js
+++ b/www/src/utils/scroll-to-anchor.js
@@ -68,9 +68,6 @@ const scrollToAnchor = (target, callback) => event => {
event.preventDefault()
const rootElement = getScrollableElement()
const targetOffset = target.offsetTop
- console.log(rootElement)
- console.log(target)
- console.log(targetOffset)
scrollToLocation(rootElement, targetOffset, 750, callback)
}
diff --git a/www/src/utils/sidebar/create-link.js b/www/src/utils/sidebar/create-link.js
new file mode 100644
index 0000000000000..539f050d23bb1
--- /dev/null
+++ b/www/src/utils/sidebar/create-link.js
@@ -0,0 +1,158 @@
+import Link from "gatsby-link"
+import React from "react"
+import presets, { colors } from "../presets"
+import { options } from "../typography"
+
+const _getTitle = (title, isDraft) => (isDraft ? title.slice(0, -1) : title)
+const _isDraft = title => title.slice(-1) === `*`
+
+const createLinkDocs = ({
+ isActive,
+ item,
+ section,
+ onLinkClick,
+ isParentOfActiveItem,
+}) => {
+ const isDraft = _isDraft(item.title)
+ const title = _getTitle(item.title, isDraft)
+
+ return (
+
+ {title}
+
+ )
+}
+
+const createLinkTutorial = ({
+ isActive,
+ item,
+ section,
+ onLinkClick,
+ isParentOfActiveItem,
+ isSubsectionLink,
+}) => {
+ const isDraft = _isDraft(item.title)
+ const title = _getTitle(item.title, isDraft)
+
+ return (
+
+ {isSubsectionLink && }
+ {title}
+
+ )
+}
+
+const bulletOffset = {
+ left: `-1rem`,
+ top: `.2rem`,
+}
+
+const bulletSize = 8
+
+const styles = {
+ draft: {
+ "&&": {
+ color: colors.gray.calm,
+ fontStyle: `italic`,
+ },
+ },
+ parentOfActiveLink: {
+ "&:after": {
+ display: `none`,
+ },
+ "&:before": {
+ display: `none`,
+ },
+ },
+ activeLink: {
+ "&&": {
+ color: colors.gatsby,
+ },
+ "&:before": {
+ background: colors.gatsby,
+ transform: `scale(1)`,
+ },
+ "&:after": {
+ width: 200,
+ opacity: 1,
+ },
+ },
+ link: {
+ position: `relative`,
+ zIndex: 1,
+ "&&": {
+ border: 0,
+ boxShadow: `none`,
+ fontFamily: options.systemFontFamily.join(`,`),
+ fontWeight: `normal`,
+ "&:hover": {
+ background: `transparent`,
+ color: colors.gatsby,
+ "&:before": {
+ background: colors.gatsby,
+ transform: `scale(1)`,
+ },
+ },
+ },
+ "&:before": {
+ ...bulletOffset,
+ borderRadius: `100%`,
+ content: ` `,
+ fontWeight: `normal`,
+ height: bulletSize,
+ position: `absolute`,
+ transform: `scale(0.1)`,
+ transition: `all ${presets.animation.speedDefault} ${
+ presets.animation.curveDefault
+ }`,
+ width: bulletSize,
+ },
+ "&:after": {
+ ...bulletOffset,
+ background: colors.gatsby,
+ borderRadius: 4,
+ content: ` `,
+ height: bulletSize,
+ left: `-0.6rem`,
+ opacity: 0,
+ position: `absolute`,
+ transform: `translateX(-200px)`,
+ transition: `all ${presets.animation.speedDefault} ${
+ presets.animation.curveDefault
+ }`,
+ width: 1,
+ },
+ },
+ subsectionLink: {
+ ...bulletOffset,
+ background: `#fff`,
+ border: `1px solid ${colors.ui.bright}`,
+ borderRadius: `100%`,
+ display: `block`,
+ fontWeight: `normal`,
+ height: bulletSize,
+ position: `absolute`,
+ width: bulletSize,
+ zIndex: -1,
+ },
+}
+
+export { createLinkDocs, createLinkTutorial }
diff --git a/www/src/utils/sidebar/find-section-for-path.js b/www/src/utils/sidebar/find-section-for-path.js
new file mode 100644
index 0000000000000..862ce9c5357af
--- /dev/null
+++ b/www/src/utils/sidebar/find-section-for-path.js
@@ -0,0 +1,23 @@
+import getSlugId from "./get-slug-id"
+
+const findSectionForPath = (pathname, sections) => {
+ const slugId = getSlugId(pathname)
+ let activeSection
+
+ sections.forEach(section => {
+ const match = section.items.some(
+ item =>
+ `/${section.directory}${item.link}` === pathname ||
+ slugId === item.id ||
+ (item.link === `/` && slugId === section.directory) ||
+ (item.subitems && item.subitems.some(subitem => slugId === subitem.id))
+ )
+ if (match) {
+ activeSection = section
+ }
+ })
+
+ return activeSection || sections[0]
+}
+
+export default findSectionForPath
diff --git a/www/src/utils/sidebar/get-active-item.js b/www/src/utils/sidebar/get-active-item.js
new file mode 100644
index 0000000000000..97c3a9df083a0
--- /dev/null
+++ b/www/src/utils/sidebar/get-active-item.js
@@ -0,0 +1,55 @@
+import getSlugId from "./get-slug-id"
+
+const isItemActive = (location, item, directory, slugId, activeItemHash) => {
+ if (activeItemHash) {
+ if (
+ activeItemHash === `NONE` &&
+ `/${directory}/${getSlugId(item.link)}/` === `${location.pathname}`
+ ) {
+ return true
+ }
+
+ if (
+ `/${directory}${item.link}` === `${location.pathname}#${activeItemHash}`
+ ) {
+ return true
+ }
+ }
+
+ if (item.link === `/` && slugId === directory) {
+ return true
+ }
+
+ if (
+ `/${directory}${item.link}` === `${location.pathname}${location.hash}` &&
+ !activeItemHash
+ ) {
+ return true
+ }
+
+ return false
+}
+
+const getActiveItem = (sectionList, location, activeItemHash) => {
+ const directory = sectionList.directory
+ const slugId = getSlugId(location.pathname)
+
+ for (let item of sectionList.items) {
+ if (isItemActive(location, item, directory, slugId, activeItemHash)) {
+ return item.link
+ }
+ if (item.subitems) {
+ for (let subitem of item.subitems) {
+ if (
+ isItemActive(location, subitem, directory, slugId, activeItemHash)
+ ) {
+ return subitem.link
+ }
+ }
+ }
+ }
+
+ return false
+}
+
+export default getActiveItem
diff --git a/www/src/utils/sidebar/get-slug-id.js b/www/src/utils/sidebar/get-slug-id.js
new file mode 100644
index 0000000000000..984810312e418
--- /dev/null
+++ b/www/src/utils/sidebar/get-slug-id.js
@@ -0,0 +1,7 @@
+const getSlugId = pathname =>
+ pathname
+ .split(`/`)
+ .slice(0, -1)
+ .pop()
+
+export default getSlugId
diff --git a/www/src/utils/sidebar/section-list.js b/www/src/utils/sidebar/section-list.js
new file mode 100644
index 0000000000000..243e25599c808
--- /dev/null
+++ b/www/src/utils/sidebar/section-list.js
@@ -0,0 +1,51 @@
+import docsSidebar from "../../data/sidebars/doc-links.yaml"
+import featuresSidebar from "../../data/sidebars/features-links.yaml"
+import tutorialSidebar from "../../data/sidebars/tutorial-links.yaml"
+
+const createId = link => {
+ const index = link.indexOf(`#`)
+ return index >= 0 ? link.substr(index + 1) : false
+}
+
+const extendSectionList = sectionList => {
+ sectionList.forEach(section => {
+ if (section.items) {
+ section.items.forEach((item, index) => {
+ let parent = index
+ item.hash = createId(item.link)
+ if (item.subitems) {
+ item.subitems.forEach(subitem => {
+ subitem.hash = createId(subitem.link)
+ subitem.parentLink = section.items[parent].link
+ })
+ }
+ })
+ }
+ })
+
+ return sectionList
+}
+
+const sectionListDocs = extendSectionList(docsSidebar).map(item => {
+ return {
+ ...item,
+ directory: `docs`,
+ }
+})
+
+const sectionListFeatures = extendSectionList(featuresSidebar).map(item => {
+ return {
+ ...item,
+ directory: `features`,
+ disableAccordions: true,
+ }
+})
+
+const sectionListTutorial = extendSectionList(tutorialSidebar).map(item => {
+ return {
+ ...item,
+ directory: `tutorial`,
+ }
+})
+
+export { sectionListDocs, sectionListFeatures, sectionListTutorial }
diff --git a/www/src/utils/typography.js b/www/src/utils/typography.js
index fde67d9bb3341..73b30375bedf6 100644
--- a/www/src/utils/typography.js
+++ b/www/src/utils/typography.js
@@ -35,6 +35,20 @@ const _options = {
`Courier New`,
`monospace`,
],
+ systemFontFamily: [
+ `-apple-system`,
+ `BlinkMacSystemFont`,
+ `Segoe UI`,
+ `Roboto`,
+ `Oxygen`,
+ `Ubuntu`,
+ `Cantarell`,
+ `Fira Sans`,
+ `Droid Sans`,
+ `Helvetica Neue`,
+ `Arial`,
+ `sans-serif`,
+ ],
baseFontSize: `18px`,
baseLineHeight: 1.4,
headerLineHeight: 1.075,
diff --git a/yarn.lock b/yarn.lock
index a602e9abc7119..257d88b8406e6 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1584,6 +1584,13 @@ agentkeepalive@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-2.2.0.tgz#c5d1bd4b129008f1163f236f86e5faea2026e2ef"
+aggregate-error@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-1.0.0.tgz#888344dad0220a72e3af50906117f48771925fac"
+ dependencies:
+ clean-stack "^1.0.0"
+ indent-string "^3.0.0"
+
ajax-request@^1.2.0:
version "1.2.3"
resolved "https://registry.yarnpkg.com/ajax-request/-/ajax-request-1.2.3.tgz#99fcbec1d6d2792f85fa949535332bd14f5f3790"
@@ -3775,6 +3782,10 @@ clean-css@4.1.x:
dependencies:
source-map "0.5.x"
+clean-stack@^1.0.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-1.3.0.tgz#9e821501ae979986c46b1d66d2d432db2fd4ae31"
+
cli-boxes@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143"
@@ -4436,7 +4447,7 @@ core-js@^1.0.0:
version "1.2.7"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
-core-js@^2.4.0, core-js@^2.4.1, core-js@^2.5.0, core-js@^2.5.3, core-js@^2.5.7:
+core-js@^2.4.0, core-js@^2.4.1, core-js@^2.5.0, core-js@^2.5.7:
version "2.5.7"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e"
@@ -5232,13 +5243,19 @@ dns-equal@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d"
-dns-packet@^1.3.1:
+dns-packet@^1.1.0, dns-packet@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.1.tgz#12aa426981075be500b910eedcd0b47dd7deda5a"
dependencies:
ip "^1.1.0"
safe-buffer "^5.0.1"
+dns-socket@^1.6.2:
+ version "1.6.3"
+ resolved "https://registry.yarnpkg.com/dns-socket/-/dns-socket-1.6.3.tgz#5268724fad4aa46ad9c5ca4ffcd16e1de5342aab"
+ dependencies:
+ dns-packet "^1.1.0"
+
dns-txt@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6"
@@ -7112,7 +7129,7 @@ got@^7.0.0, got@^7.1.0:
url-parse-lax "^1.0.0"
url-to-options "^1.0.1"
-got@^8.0.1:
+got@^8.0.0, got@^8.0.1:
version "8.3.1"
resolved "https://registry.yarnpkg.com/got/-/got-8.3.1.tgz#093324403d4d955f5a16a7a8d39955d055ae10ed"
dependencies:
@@ -8013,6 +8030,10 @@ ip-regex@^1.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-1.0.3.tgz#dc589076f659f419c222039a33316f1c7387effd"
+ip-regex@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
+
ip@1.1.5, ip@^1.1.0, ip@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
@@ -8253,6 +8274,12 @@ is-installed-globally@^0.1.0:
global-dirs "^0.1.0"
is-path-inside "^1.0.0"
+is-ip@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/is-ip/-/is-ip-2.0.0.tgz#68eea07e8a0a0a94c2d080dd674c731ab2a461ab"
+ dependencies:
+ ip-regex "^2.0.0"
+
is-lower-case@^1.1.0:
version "1.1.3"
resolved "https://registry.yarnpkg.com/is-lower-case/-/is-lower-case-1.1.3.tgz#7e147be4768dc466db3bfb21cc60b31e6ad69393"
@@ -8311,6 +8338,15 @@ is-odd@^2.0.0:
dependencies:
is-number "^4.0.0"
+is-online@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/is-online/-/is-online-7.0.0.tgz#7e2408c0ae1e7e37ba8d50bdb237260d32bfd96e"
+ dependencies:
+ got "^6.7.1"
+ p-any "^1.0.0"
+ p-timeout "^1.0.0"
+ public-ip "^2.3.0"
+
is-path-cwd@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
@@ -11106,6 +11142,12 @@ output-file-sync@^2.0.0:
is-plain-obj "^1.1.0"
mkdirp "^0.5.1"
+p-any@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/p-any/-/p-any-1.1.0.tgz#1d03835c7eed1e34b8e539c47b7b60d0d015d4e1"
+ dependencies:
+ p-some "^2.0.0"
+
p-cancelable@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa"
@@ -11162,7 +11204,13 @@ p-reduce@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa"
-p-timeout@^1.1.1:
+p-some@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/p-some/-/p-some-2.0.1.tgz#65d87c8b154edbcf5221d167778b6d2e150f6f06"
+ dependencies:
+ aggregate-error "^1.0.0"
+
+p-timeout@^1.0.0, p-timeout@^1.1.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386"
dependencies:
@@ -12129,6 +12177,15 @@ public-encrypt@^4.0.0:
parse-asn1 "^5.0.0"
randombytes "^2.0.1"
+public-ip@^2.3.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/public-ip/-/public-ip-2.4.0.tgz#f00c028a15366d8c798e47efab6acd09a17666da"
+ dependencies:
+ dns-socket "^1.6.2"
+ got "^8.0.0"
+ is-ip "^2.0.0"
+ pify "^3.0.0"
+
pump@^1.0.0:
version "1.0.3"
resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954"
@@ -12194,6 +12251,13 @@ query-string@^5.0.1:
object-assign "^4.1.0"
strict-uri-encode "^1.0.0"
+query-string@^6.1.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.1.0.tgz#01e7d69f6a0940dac67a937d6c6325647aa4532a"
+ dependencies:
+ decode-uri-component "^0.2.0"
+ strict-uri-encode "^2.0.0"
+
querystring-es3@^0.2.0, querystring-es3@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
@@ -14607,6 +14671,10 @@ strict-uri-encode@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
+strict-uri-encode@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
+
string-hash@^1.1.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b"