diff --git a/docs/docs/adding-search-with-js-search.md b/docs/docs/adding-search-with-js-search.md index eb4fa287fb65f..0c5c0847db61b 100644 --- a/docs/docs/adding-search-with-js-search.md +++ b/docs/docs/adding-search-with-js-search.md @@ -1,8 +1,8 @@ ---- +======= title: Adding search with js-search --- This is a stub. Help our community expand it. Please use the [Gatsby Style Guide](/docs/gatsby-style-guide/) to ensure your -pull request gets accepted. +pull request gets accepted. \ No newline at end of file diff --git a/docs/tutorial/appendix/source-JSON-YAML/index.md b/docs/tutorial/appendix/source-JSON-YAML/index.md new file mode 100644 index 0000000000000..2dcd6519556a7 --- /dev/null +++ b/docs/tutorial/appendix/source-JSON-YAML/index.md @@ -0,0 +1,274 @@ +--- +title: "Sourcing from JSON or YAML" +--- + +# Beforehand + +As you're presented with Gatsby, you'll see that you have at your disposal a myriad of ways to pull data from into your website, ranging from the most used ones like [Contenfull](https://www.contentful.com/), or [WordPress](https://wordpress.com/), [Drupal](https://www.drupal.org/), to the most edgier ones like [ButterCMS](https://buttercms.com/), [GraphCMS](https://graphcms.com/) and their appropriate plugins to ensure connectivity. + +With this tutorial, it will help you return to the origins and instead of pulling data in from the providers above, you'll use a plain JSON file and YAML to achieve this. + +It will presented a way to use either JSON or YAML files, for creating the bare structure of a gatsby website, by adding some pages dynamically with either one of the above. + +Also a way to load contents from both sources to a page. + +## Prerequisites + +Before we go through the steps needed to add plain JSON or YAML into your Gatsby website, it would be advised +if the reader is not familiar on how Gatsby works and is set up to follow through the [tutorial](https://www.gatsbyjs.org/tutorial/) and brush up on the [documentation](https://www.gatsbyjs.org/docs/). + +Otherwise just skip this part and move onto the next part. + +## Setup + +Open up a terminal and create a new folder that will be used for the project: + +```bash +mkdir mywebsite +``` + +Inside that folder, create a new Gatsby website using a starter template, using the command bellow. + +```bash +npx gatsby new gatsby-with-JSON-YAML https://github.com/gatsbyjs/gatsby-starter-default +``` + +After the process is complete, some additional packages are needed. + +Navigate into the `gatsby-with-JSON-YAML` folder and issue the following command: + +```bash +npm install --save js-yaml uuid axios +``` + +Or if Yarn is being used: + +```bash +yarn add js-yaml uuid axios +``` + +[Axios](https://github.com/axios/axios) will be used to handle all promise based requests, as it can be seen later. [js-yaml](https://github.com/nodeca/js-yaml) for parsing the yaml file contents. [uuid](https://github.com/kelektiv/node-uuid#readme) is used as a safety measure for React element key handling. + +Create a folder called `data` in the root of project folder and two more, one with the name `json` and another one called `yaml` inside that. + +Also another folder called `static`, as per documented [here](https://www.gatsbyjs.org/docs/static-folder/), so that the file contents can be handled more easily as you can read about later. + +We can now move onto the actual implementation of the code. + +### Using JSON as a source for building a site + +In this section it will be presented a way to create the bare structure of a site using a JSON file and Gatsby API. + +Start by copying the contents of the example JSON provided [here](https://github.com/gatsbyjs/gatsby/tree/master/examples/sourcing-from-JSON-or-Yaml/content/data/json/) into the `json` folder created above. + +Change the `gatsby-node.js` file to the following: + +```javascript +exports.createPages = ({ actions }) => { + const { createPage } = actions + return new Promise(resolve => { + const JSONDoc = require("./content/data/json/index.json") + JSONDoc.forEach(element => { + createPage({ + path: element.path, + component: require.resolve("./src/templates/basicTemplate.js"), + context: { + pageContent: element.content, + links: element.links, + }, + }) + }) + resolve() + }) +} +``` + +What the above code is doing: + +- Loading the contents of the JSON file into a `const`. +- Iterating over the contents, to create a page based on a template. +- Inside every page created the [pageContext](https://www.gatsbyjs.org/docs/behind-the-scenes-terminology/#pagecontext) is used to inject some data that will be presented in the page and also some navigation between the pages. + +Once that is done, create the file `./src/templates/basicTemplate.js` with the following contents: + +```javascript +import React from "react" +import uuid from "uuid" +import Layout from "../components/layout" +import SEO from "../components/seo" +import { Link } from "gatsby" +const basicTemplate = props => { + const { pageContext } = props + const { pageContent, links } = pageContext + + return ( + + +
+ {pageContent.map(data => ( +
{data.item}
+ ))} +
+
+ {links.map(item => ( +
+ {item.to} +
+ ))} +
+
+ ) +} +export default basicTemplate +``` + +The above code is a plain React presentational component that recieves some data via the `pageContext` prop and shows it. + +Once all is done, issuing `gatsby develop` and opening your favourite browser of choice and navigating into: +`http://localhost:8000/page1` for instance will what was done here. + +Now onto using a YAML file. + +### Using YAML as a source for building a site + +In order the same approach as the one documented above, but this time with a YAML file, is similar, in this particular case copy the YAML file located [here](https://github.com/gatsbyjs/gatsby/tree/master/examples/sourcing-from-JSON-or-Yaml/content/data/yaml/) to the `yaml` folder created earlier. + +Now change the `gatsby-node.js` to the following: + +```javascript +const fs = require("fs") +const yaml = require("js-yaml") // the yaml parser being imported to be used. +exports.createPages = ({ actions }) => { + const { createPage } = actions + return new Promise(resolve => { + //yaml file loaded here + const ymlDoc = yaml.safeLoad( + fs.readFileSync("./content/data/yaml/index.yaml", "utf-8") + ) + // + ymlDoc.forEach(element => { + createPage({ + path: element.path, + component: require.resolve("./src/templates/basicTemplate.js"), + context: { + pageContent: element.content, + links: element.links, + }, + }) + }) + resolve() + }) +} +``` + +The code above is somewhat similar to the code described above. + +The only diference here is the way how the data is loaded, here is where the `js-yaml` package installed earlier comes into play. It will load the contents of the file and create the website structure and some contents. + +### Using JSON as a content provider a page + +Now we'll go back to JSON, to be used as a source for content to a particular gatsby page. + +Now you'll see the reason of the `static` folder. +Copy this [file](https://github.com/gatsbyjs/gatsby/tree/master/examples/sourcing-from-JSON-or-Yaml/static/second.json) inside the newly created folder. + +Create a new file inside the `pages` folder, for this example with will be named `jsononclient.js`, but whatever name you decide is fine. + +Inside that file add the following: + +```javascript +import React, { Component } from "react" +import axios from "axios" +import Layout from "../components/layout" +import SEO from "../components/seo" + +class ClientJSON extends Component { + state = { + jsonData: {}, + } + async componentDidMount() { + const JSONRequest = await axios.get("./second.json") + this.setState({ jsonData: JSONRequest.data }) + } + render() { + const { jsonData } = this.state + if (!jsonData.title) { + return

fetching data! give it a moment

+ } + return ( + + +
+ {jsonData.content.map(data => { + return
{data.item}
+ })} +
+
+ ) + } +} + +export default ClientJSON +``` + +What the above code is doing is perfoming a GET request, using [Axios](https://github.com/axios/axios), the url when resolved, will load the contents of that particular static asset and update the component state in order to be used. + +**Be advised** that this block of code and the one bellow will function while developing your site. Some changes are required before issuing a production build. + +### Using YAML as a content provider a page + +Finally the same approach can be used for a YAML file, the process is somewhat similar to the above, instead of the file being copied to the static folder being the .json one, now is the .yaml one. + +Create file inside the `pages` folder, for this example it will be named `ymlonclient.js`, but like above, the name is entirely to the reader. + +Inside the newly create file, add the following contents: + +```javascript +import React, { Component } from "react" +import Layout from "../components/layout" +import SEO from "../components/seo" +import axios from "axios" +import yaml from "js-yaml" +class ClientYAML extends Component { + state = { + yamlData: {}, + } + async componentDidMount() { + const ymlfile = await axios.get("./second.yaml") + const data = yaml.safeLoad(ymlfile.data) + this.setState({ yamlData: data }) + } + render() { + const { yamlData } = this.state + if (!yamlData.title) { + return

fetching data! give it a moment

+ } + return ( + + +
+ {yamlData.content.map(data => { + return
{data.item}
+ })} +
+
+ ) + } +} +export default ClientYAML +``` + +What the following code will do, is in fact similar to the one used for example mentioned above. The only diference is the way we handle the loading of the contents originating from the file. +Once again taking advantage of the `js-yaml` package added earlier so that loading either contents can be achieved on the client side. + +## Last words + +Gatsby offers a way achieve almost the same result, by using the appropriate plugins and graphql. +But that's the matter for another tutorial. + +With this document, it was presented in a rather extensive way, how to use these simple structures to handle data, to be used with Gatsby site. + +Now go make something great. diff --git a/examples/using-JSON-YAML-source/.gitignore b/examples/using-JSON-YAML-source/.gitignore new file mode 100644 index 0000000000000..6d8a52ae0d104 --- /dev/null +++ b/examples/using-JSON-YAML-source/.gitignore @@ -0,0 +1,71 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Typescript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# dotenv environment variables file +.env + +# gatsby files +.cache/ +public + +# Mac files +.DS_Store + +# Yarn +yarn-error.log +.pnp/ +.pnp.js +# Yarn Integrity file +.yarn-integrity + +sourcing-from-JSON-or-Yaml.md \ No newline at end of file diff --git a/examples/using-JSON-YAML-source/.prettierrc b/examples/using-JSON-YAML-source/.prettierrc new file mode 100644 index 0000000000000..36301bc5cff6c --- /dev/null +++ b/examples/using-JSON-YAML-source/.prettierrc @@ -0,0 +1,5 @@ +{ + "semi": false, + "singleQuote": true, + "trailingComma": "es5" +} diff --git a/examples/using-JSON-YAML-source/LICENSE b/examples/using-JSON-YAML-source/LICENSE new file mode 100644 index 0000000000000..5169a5e4135e9 --- /dev/null +++ b/examples/using-JSON-YAML-source/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 gatsbyjs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/examples/using-JSON-YAML-source/README.md b/examples/using-JSON-YAML-source/README.md new file mode 100644 index 0000000000000..d8a6c2b354c31 --- /dev/null +++ b/examples/using-JSON-YAML-source/README.md @@ -0,0 +1,19 @@ +# Sourcing from YAML and JSON files + +Gatsby example that uses JSON files and YAML files as a means of sourcing data. + +## Live Version + +https://hungry-edison-90c8ac.netlify.com/ + +## Routes + +Bellow are listed the routes generated via GATSBY API + +- /page1 +- /page2 +- /page3 +- /page4 +- /page5 + +The route `/jsononclient` and `/ymlonclient` will show some JSON or YAML content loaded on the client side. diff --git a/examples/using-JSON-YAML-source/content/data/json/index.json b/examples/using-JSON-YAML-source/content/data/json/index.json new file mode 100644 index 0000000000000..b961622bf5261 --- /dev/null +++ b/examples/using-JSON-YAML-source/content/data/json/index.json @@ -0,0 +1,78 @@ +[ + { + "path": "/page1", + "content": [ + { + "item":"one item" + }, + { + "item": "two items" + }, + { + "item":"three items" + } + ], + "links": [ + { + "to": "/page2" + }, + { + "to": "/page5" + } + ] + }, + { + "path": "/page2", + "content": [ + { + "item":"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." + } + ], + "links": [ + { + "to": "/page1" + } + ] + }, + { + "path": "/page3", + "content": [ + { + "item":"Hodor. Hodor hodor, hodor. Hodor hodor hodor hodor hodor. Hodor. Hodor! Hodor hodor, hodor; hodor hodor hodor. Hodor. Hodor hodor; hodor hodor - hodor, hodor, hodor hodor. Hodor, hodor. Hodor. Hodor, hodor hodor hodor; hodor hodor; hodor hodor hodor! Hodor hodor HODOR! Hodor hodor... Hodor hodor hodor..." + } + ], + "links": [] + }, + { + "path": "/page4", + "content": [ + { + "item":"Lorem ipsum dolor amet mustache knausgaard +1, blue bottle waistcoat tbh semiotics artisan synth stumptown gastropub cornhole celiac swag. Brunch raclette vexillologist post-ironic glossier ennui XOXO mlkshk godard pour-over blog tumblr humblebrag. Blue bottle put a bird on it twee prism biodiesel brooklyn. Blue bottle ennui tbh succulents." + } + ], + "links": [ + { + "to": "/page5" + }, + { + "to":"/page1" + } + ] + }, + { + "path": "/page5", + "content": [ + { + "item":"Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro. De carne lumbering animata corpora quaeritis. Summus brains sit​​, morbo vel maleficia? De apocalypsi gorger omero undead survivor dictum mauris. Hi mindless mortuis soulless creaturas, imo evil stalking monstra adventus resi dentevil vultus comedat cerebella viventium." + }, + { + "item":"Bacon ipsum dolor amet short ribs brisket venison rump drumstick pig sausage prosciutto chicken spare ribs salami picanha doner. Kevin capicola sausage, buffalo bresaola venison turkey shoulder picanha ham pork tri-tip meatball meatloaf ribeye. Doner spare ribs andouille bacon sausage. Ground round jerky brisket pastrami shank." + } + ], + "links": [ + { + "to": "/page1" + } + ] + } + ] \ No newline at end of file diff --git a/examples/using-JSON-YAML-source/content/data/yaml/index.yaml b/examples/using-JSON-YAML-source/content/data/yaml/index.yaml new file mode 100644 index 0000000000000..eb905be3b9c47 --- /dev/null +++ b/examples/using-JSON-YAML-source/content/data/yaml/index.yaml @@ -0,0 +1,50 @@ +--- +- path: "/page1" + content: + - item: one item + - item: two items + - item: three items + links: + - to: "/page2" + - to: "/page5" +- path: "/page2" + content: + - item: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore + eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt + in culpa qui officia deserunt mollit anim id est laborum. + links: + - to: "/page1" +- path: "/page3" + content: + - item: Hodor. Hodor hodor, hodor. Hodor hodor hodor hodor hodor. Hodor. Hodor! + Hodor hodor, hodor; hodor hodor hodor. Hodor. Hodor hodor; hodor hodor - hodor, + hodor, hodor hodor. Hodor, hodor. Hodor. Hodor, hodor hodor hodor; hodor hodor; + hodor hodor hodor! Hodor hodor HODOR! Hodor hodor... Hodor hodor hodor... + links: [] +- path: "/page4" + content: + - item: Lorem ipsum dolor amet mustache knausgaard +1, blue bottle waistcoat tbh + semiotics artisan synth stumptown gastropub cornhole celiac swag. Brunch raclette + vexillologist post-ironic glossier ennui XOXO mlkshk godard pour-over blog tumblr + humblebrag. Blue bottle put a bird on it twee prism biodiesel brooklyn. Blue + bottle ennui tbh succulents. + links: + - to: "/page5" + - to: "/page1" +- path: "/page5" + content: + - item: Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro. De + carne lumbering animata corpora quaeritis. Summus brains sit​​, morbo vel maleficia? + De apocalypsi gorger omero undead survivor dictum mauris. Hi mindless mortuis + soulless creaturas, imo evil stalking monstra adventus resi dentevil vultus + comedat cerebella viventium. + - item: Bacon ipsum dolor amet short ribs brisket venison rump drumstick pig sausage + prosciutto chicken spare ribs salami picanha doner. Kevin capicola sausage, + buffalo bresaola venison turkey shoulder picanha ham pork tri-tip meatball meatloaf + ribeye. Doner spare ribs andouille bacon sausage. Ground round jerky brisket + pastrami shank. + links: + - to: "/page1" diff --git a/examples/using-JSON-YAML-source/gatsby-config.js b/examples/using-JSON-YAML-source/gatsby-config.js new file mode 100644 index 0000000000000..765ebb90203dd --- /dev/null +++ b/examples/using-JSON-YAML-source/gatsby-config.js @@ -0,0 +1,34 @@ +module.exports = { + siteMetadata: { + title: `Gatsby Default Starter`, + description: `Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`, + author: `@gatsbyjs`, + }, + plugins: [ + `gatsby-plugin-react-helmet`, + { + resolve: `gatsby-source-filesystem`, + options: { + name: `images`, + path: `${__dirname}/src/images`, + }, + }, + `gatsby-transformer-sharp`, + `gatsby-plugin-sharp`, + { + resolve: `gatsby-plugin-manifest`, + options: { + name: `gatsby-starter-default`, + short_name: `starter`, + start_url: `/`, + background_color: `#663399`, + theme_color: `#663399`, + display: `minimal-ui`, + icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site. + }, + }, + // this (optional) plugin enables Progressive Web App + Offline functionality + // To learn more, visit: https://gatsby.app/offline + // 'gatsby-plugin-offline', + ], +} diff --git a/examples/using-JSON-YAML-source/gatsby-node.js b/examples/using-JSON-YAML-source/gatsby-node.js new file mode 100644 index 0000000000000..3cfaf47a5f1d9 --- /dev/null +++ b/examples/using-JSON-YAML-source/gatsby-node.js @@ -0,0 +1,40 @@ +/** + * Implement Gatsby's Node APIs in this file. + * + * See: https://www.gatsbyjs.org/docs/node-apis/ + */ + +// You can delete this file if you're not using it +const fs = require('fs'); +const yaml = require('js-yaml') +exports.createPages=({actions})=>{ + const {createPage}= actions + return new Promise((resolve)=>{ + /* const JSONDoc= require('./content/data/json/index.json') + JSONDoc.forEach(element => { + createPage({ + path:element.path, + component:require.resolve('./src/templates/basicTemplate.js'), + context:{ + pageContent:element.content, + links:element.links + } + }) + }); */ + + //yaml + const ymlDoc= yaml.safeLoad(fs.readFileSync('./content/data/yaml/index.yaml','utf-8')) + // + ymlDoc.forEach(element=>{ + createPage({ + path:element.path, + component:require.resolve('./src/templates/basicTemplate.js'), + context:{ + pageContent:element.content, + links:element.links + } + }) + }) + resolve() + }) +} \ No newline at end of file diff --git a/examples/using-JSON-YAML-source/package.json b/examples/using-JSON-YAML-source/package.json new file mode 100644 index 0000000000000..752be5f2b0660 --- /dev/null +++ b/examples/using-JSON-YAML-source/package.json @@ -0,0 +1,47 @@ +{ + "name": "gatsby-starter-default", + "private": true, + "description": "A simple starter to get up and developing quickly with Gatsby", + "version": "0.1.0", + "author": "Kyle Mathews ", + "dependencies": { + "axios": "^0.18.0", + "gatsby": "^2.0.76", + "gatsby-image": "^2.0.20", + "gatsby-plugin-manifest": "^2.0.9", + "gatsby-plugin-offline": "^2.0.16", + "gatsby-plugin-react-helmet": "^3.0.2", + "gatsby-plugin-sharp": "^2.0.14", + "gatsby-source-filesystem": "^2.0.8", + "gatsby-transformer-sharp": "^2.1.8", + "js-yaml": "^3.12.1", + "prop-types": "^15.6.2", + "react": "^16.6.3", + "react-dom": "^16.6.3", + "react-helmet": "^5.2.0", + "rimraf": "^2.6.3", + "uuid": "^3.3.2" + }, + "keywords": [ + "gatsby" + ], + "license": "MIT", + "scripts": { + "build": "gatsby build", + "develop": "gatsby develop", + "start": "npm run develop", + "clear": "rimraf ./public && rimraf .cache", + "format": "prettier --write \"src/**/*.js\"", + "test": "echo \"Write tests! -> https://gatsby.app/unit-testing\"" + }, + "devDependencies": { + "prettier": "^1.15.2" + }, + "repository": { + "type": "git", + "url": "https://github.com/gatsbyjs/gatsby-starter-default" + }, + "bugs": { + "url": "https://github.com/gatsbyjs/gatsby/issues" + } +} diff --git a/examples/using-JSON-YAML-source/src/components/header.js b/examples/using-JSON-YAML-source/src/components/header.js new file mode 100644 index 0000000000000..235f8834818a3 --- /dev/null +++ b/examples/using-JSON-YAML-source/src/components/header.js @@ -0,0 +1,42 @@ +import { Link } from 'gatsby' +import PropTypes from 'prop-types' +import React from 'react' + +const Header = ({ siteTitle }) => ( +
+
+

+ + {siteTitle} + +

+
+
+) + +Header.propTypes = { + siteTitle: PropTypes.string, +} + +Header.defaultProps = { + siteTitle: ``, +} + +export default Header diff --git a/examples/using-JSON-YAML-source/src/components/image.js b/examples/using-JSON-YAML-source/src/components/image.js new file mode 100644 index 0000000000000..9ed27ee238349 --- /dev/null +++ b/examples/using-JSON-YAML-source/src/components/image.js @@ -0,0 +1,32 @@ +import React from 'react' +import { StaticQuery, graphql } from 'gatsby' +import Img from 'gatsby-image' + +/* + * This component is built using `gatsby-image` to automatically serve optimized + * images with lazy loading and reduced file sizes. The image is loaded using a + * `StaticQuery`, which allows us to load the image from directly within this + * component, rather than having to pass the image data down from pages. + * + * For more information, see the docs: + * - `gatsby-image`: https://gatsby.app/gatsby-image + * - `StaticQuery`: https://gatsby.app/staticquery + */ + +const Image = () => ( + } + /> +) +export default Image diff --git a/examples/using-JSON-YAML-source/src/components/layout.css b/examples/using-JSON-YAML-source/src/components/layout.css new file mode 100644 index 0000000000000..6ca5b70d7a97f --- /dev/null +++ b/examples/using-JSON-YAML-source/src/components/layout.css @@ -0,0 +1,620 @@ +html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +main, +menu, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; +} +audio:not([controls]) { + display: none; + height: 0; +} +progress { + vertical-align: baseline; +} +[hidden], +template { + display: none; +} +a { + background-color: transparent; + -webkit-text-decoration-skip: objects; +} +a:active, +a:hover { + outline-width: 0; +} +abbr[title] { + border-bottom: none; + text-decoration: underline; + text-decoration: underline dotted; +} +b, +strong { + font-weight: inherit; + font-weight: bolder; +} +dfn { + font-style: italic; +} +h1 { + font-size: 2em; + margin: 0.67em 0; +} +mark { + background-color: #ff0; + color: #000; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sub { + bottom: -0.25em; +} +sup { + top: -0.5em; +} +img { + border-style: none; +} +svg:not(:root) { + overflow: hidden; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +figure { + margin: 1em 40px; +} +hr { + box-sizing: content-box; + height: 0; + overflow: visible; +} +button, +input, +optgroup, +select, +textarea { + font: inherit; + margin: 0; +} +optgroup { + font-weight: 700; +} +button, +input { + overflow: visible; +} +button, +select { + text-transform: none; +} +[type='reset'], +[type='submit'], +button, +html [type='button'] { + -webkit-appearance: button; +} +[type='button']::-moz-focus-inner, +[type='reset']::-moz-focus-inner, +[type='submit']::-moz-focus-inner, +button::-moz-focus-inner { + border-style: none; + padding: 0; +} +[type='button']:-moz-focusring, +[type='reset']:-moz-focusring, +[type='submit']:-moz-focusring, +button:-moz-focusring { + outline: 1px dotted ButtonText; +} +fieldset { + border: 1px solid silver; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} +legend { + box-sizing: border-box; + color: inherit; + display: table; + max-width: 100%; + padding: 0; + white-space: normal; +} +textarea { + overflow: auto; +} +[type='checkbox'], +[type='radio'] { + box-sizing: border-box; + padding: 0; +} +[type='number']::-webkit-inner-spin-button, +[type='number']::-webkit-outer-spin-button { + height: auto; +} +[type='search'] { + -webkit-appearance: textfield; + outline-offset: -2px; +} +[type='search']::-webkit-search-cancel-button, +[type='search']::-webkit-search-decoration { + -webkit-appearance: none; +} +::-webkit-input-placeholder { + color: inherit; + opacity: 0.54; +} +::-webkit-file-upload-button { + -webkit-appearance: button; + font: inherit; +} +html { + font: 112.5%/1.45em georgia, serif; + box-sizing: border-box; + overflow-y: scroll; +} +* { + box-sizing: inherit; +} +*:before { + box-sizing: inherit; +} +*:after { + box-sizing: inherit; +} +body { + color: hsla(0, 0%, 0%, 0.8); + font-family: georgia, serif; + font-weight: normal; + word-wrap: break-word; + font-kerning: normal; + -moz-font-feature-settings: 'kern', 'liga', 'clig', 'calt'; + -ms-font-feature-settings: 'kern', 'liga', 'clig', 'calt'; + -webkit-font-feature-settings: 'kern', 'liga', 'clig', 'calt'; + font-feature-settings: 'kern', 'liga', 'clig', 'calt'; +} +img { + max-width: 100%; + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +h1 { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; + color: inherit; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, + Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; + font-weight: bold; + text-rendering: optimizeLegibility; + font-size: 2.25rem; + line-height: 1.1; +} +h2 { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; + color: inherit; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, + Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; + font-weight: bold; + text-rendering: optimizeLegibility; + font-size: 1.62671rem; + line-height: 1.1; +} +h3 { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; + color: inherit; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, + Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; + font-weight: bold; + text-rendering: optimizeLegibility; + font-size: 1.38316rem; + line-height: 1.1; +} +h4 { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; + color: inherit; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, + Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; + font-weight: bold; + text-rendering: optimizeLegibility; + font-size: 1rem; + line-height: 1.1; +} +h5 { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; + color: inherit; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, + Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; + font-weight: bold; + text-rendering: optimizeLegibility; + font-size: 0.85028rem; + line-height: 1.1; +} +h6 { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; + color: inherit; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, + Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; + font-weight: bold; + text-rendering: optimizeLegibility; + font-size: 0.78405rem; + line-height: 1.1; +} +hgroup { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +ul { + margin-left: 1.45rem; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; + list-style-position: outside; + list-style-image: none; +} +ol { + margin-left: 1.45rem; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; + list-style-position: outside; + list-style-image: none; +} +dl { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +dd { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +p { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +figure { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +pre { + margin-left: 0; + margin-right: 0; + margin-top: 0; + margin-bottom: 1.45rem; + font-size: 0.85rem; + line-height: 1.42; + background: hsla(0, 0%, 0%, 0.04); + border-radius: 3px; + overflow: auto; + word-wrap: normal; + padding: 1.45rem; +} +table { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; + font-size: 1rem; + line-height: 1.45rem; + border-collapse: collapse; + width: 100%; +} +fieldset { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +blockquote { + margin-left: 1.45rem; + margin-right: 1.45rem; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +form { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +noscript { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +iframe { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +hr { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: calc(1.45rem - 1px); + background: hsla(0, 0%, 0%, 0.2); + border: none; + height: 1px; +} +address { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +b { + font-weight: bold; +} +strong { + font-weight: bold; +} +dt { + font-weight: bold; +} +th { + font-weight: bold; +} +li { + margin-bottom: calc(1.45rem / 2); +} +ol li { + padding-left: 0; +} +ul li { + padding-left: 0; +} +li > ol { + margin-left: 1.45rem; + margin-bottom: calc(1.45rem / 2); + margin-top: calc(1.45rem / 2); +} +li > ul { + margin-left: 1.45rem; + margin-bottom: calc(1.45rem / 2); + margin-top: calc(1.45rem / 2); +} +blockquote *:last-child { + margin-bottom: 0; +} +li *:last-child { + margin-bottom: 0; +} +p *:last-child { + margin-bottom: 0; +} +li > p { + margin-bottom: calc(1.45rem / 2); +} +code { + font-size: 0.85rem; + line-height: 1.45rem; +} +kbd { + font-size: 0.85rem; + line-height: 1.45rem; +} +samp { + font-size: 0.85rem; + line-height: 1.45rem; +} +abbr { + border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); + cursor: help; +} +acronym { + border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); + cursor: help; +} +abbr[title] { + border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); + cursor: help; + text-decoration: none; +} +thead { + text-align: left; +} +td, +th { + text-align: left; + border-bottom: 1px solid hsla(0, 0%, 0%, 0.12); + font-feature-settings: 'tnum'; + -moz-font-feature-settings: 'tnum'; + -ms-font-feature-settings: 'tnum'; + -webkit-font-feature-settings: 'tnum'; + padding-left: 0.96667rem; + padding-right: 0.96667rem; + padding-top: 0.725rem; + padding-bottom: calc(0.725rem - 1px); +} +th:first-child, +td:first-child { + padding-left: 0; +} +th:last-child, +td:last-child { + padding-right: 0; +} +tt, +code { + background-color: hsla(0, 0%, 0%, 0.04); + border-radius: 3px; + font-family: 'SFMono-Regular', Consolas, 'Roboto Mono', 'Droid Sans Mono', + 'Liberation Mono', Menlo, Courier, monospace; + padding: 0; + padding-top: 0.2em; + padding-bottom: 0.2em; +} +pre code { + background: none; + line-height: 1.42; +} +code:before, +code:after, +tt:before, +tt:after { + letter-spacing: -0.2em; + content: ' '; +} +pre code:before, +pre code:after, +pre tt:before, +pre tt:after { + content: ''; +} +@media only screen and (max-width: 480px) { + html { + font-size: 100%; + } +} diff --git a/examples/using-JSON-YAML-source/src/components/layout.js b/examples/using-JSON-YAML-source/src/components/layout.js new file mode 100644 index 0000000000000..dfc924fd8ca99 --- /dev/null +++ b/examples/using-JSON-YAML-source/src/components/layout.js @@ -0,0 +1,48 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { StaticQuery, graphql } from 'gatsby' + +import Header from './header' +import './layout.css' + +const Layout = ({ children }) => ( + ( + /* eslint-disable */ + <> +
+
+ {children} +
+ © {new Date().getFullYear()}, Built with + {` `} + Gatsby +
+
+ + /* eslint-enable */ + )} + /> +) + +Layout.propTypes = { + children: PropTypes.node.isRequired, +} + +export default Layout diff --git a/examples/using-JSON-YAML-source/src/components/seo.js b/examples/using-JSON-YAML-source/src/components/seo.js new file mode 100644 index 0000000000000..f639bd883cdf1 --- /dev/null +++ b/examples/using-JSON-YAML-source/src/components/seo.js @@ -0,0 +1,96 @@ +import React from 'react' +import PropTypes from 'prop-types' +import Helmet from 'react-helmet' +import { StaticQuery, graphql } from 'gatsby' + +function SEO({ description, lang, meta, keywords, title }) { + return ( + { + const metaDescription = + description || data.site.siteMetadata.description + return ( + 0 + ? { + name: `keywords`, + content: keywords.join(`, `), + } + : [] + ) + .concat(meta)} + /> + ) + }} + /> + ) +} + +SEO.defaultProps = { + lang: `en`, + meta: [], + keywords: [], +} + +SEO.propTypes = { + description: PropTypes.string, + lang: PropTypes.string, + meta: PropTypes.array, + keywords: PropTypes.arrayOf(PropTypes.string), + title: PropTypes.string.isRequired, +} + +export default SEO + +const detailsQuery = graphql` + query DefaultSEOQuery { + site { + siteMetadata { + title + description + author + } + } + } +` diff --git a/examples/using-JSON-YAML-source/src/images/gatsby-astronaut.png b/examples/using-JSON-YAML-source/src/images/gatsby-astronaut.png new file mode 100644 index 0000000000000..da58ece0a8c5b Binary files /dev/null and b/examples/using-JSON-YAML-source/src/images/gatsby-astronaut.png differ diff --git a/examples/using-JSON-YAML-source/src/images/gatsby-icon.png b/examples/using-JSON-YAML-source/src/images/gatsby-icon.png new file mode 100644 index 0000000000000..908bc78a7f559 Binary files /dev/null and b/examples/using-JSON-YAML-source/src/images/gatsby-icon.png differ diff --git a/examples/using-JSON-YAML-source/src/pages/404.js b/examples/using-JSON-YAML-source/src/pages/404.js new file mode 100644 index 0000000000000..77a691f9da56d --- /dev/null +++ b/examples/using-JSON-YAML-source/src/pages/404.js @@ -0,0 +1,14 @@ +import React from 'react' + +import Layout from '../components/layout' +import SEO from '../components/seo' + +const NotFoundPage = () => ( + + +

NOT FOUND

+

You just hit a route that doesn't exist... the sadness.

+
+) + +export default NotFoundPage diff --git a/examples/using-JSON-YAML-source/src/pages/index.js b/examples/using-JSON-YAML-source/src/pages/index.js new file mode 100644 index 0000000000000..e90144a57ba92 --- /dev/null +++ b/examples/using-JSON-YAML-source/src/pages/index.js @@ -0,0 +1,18 @@ +import React from 'react' +import Layout from '../components/layout' +import Image from '../components/image' +import SEO from '../components/seo' + +const IndexPage = () => ( + + +

Hi people

+

Welcome to your new Gatsby site.

+

Now go build something great.

+
+ +
+
+) + +export default IndexPage diff --git a/examples/using-JSON-YAML-source/src/pages/jsononclient.js b/examples/using-JSON-YAML-source/src/pages/jsononclient.js new file mode 100644 index 0000000000000..de42e0808e58b --- /dev/null +++ b/examples/using-JSON-YAML-source/src/pages/jsononclient.js @@ -0,0 +1,49 @@ +import React, { Component } from 'react' +import axios from 'axios' +import Layout from '../components/layout' +import SEO from '../components/seo' +import uuid from 'uuid' +class ClientJSON extends Component { + state = { + isError: false, + errorMessage: ``, + jsonData: {}, + } + async componentDidMount() { + try { + const JSONRequest = await axios.get(`./second.json`) + this.setState({ jsonData: JSONRequest.data }) + } catch (error) { + this.setState({ isError: true, errorMessage: error }) + console.log(`====================================`) + console.log(`ERROR ON LOAD DATA:\n${error}`) + console.log(`====================================`) + } + } + render() { + const { jsonData, isError, errorMessage } = this.state + if (isError) { + return ( +
+

Something went bad

+

{errorMessage}

+
+ ) + } + if (!jsonData.title) { + return

fetching data! give it a moment

+ } + return ( + + +
+ {jsonData.content.map(data => ( +
{data.item}
+ ))} +
+
+ ) + } +} + +export default ClientJSON diff --git a/examples/using-JSON-YAML-source/src/pages/ymlonclient.js b/examples/using-JSON-YAML-source/src/pages/ymlonclient.js new file mode 100644 index 0000000000000..1c2efb86bce25 --- /dev/null +++ b/examples/using-JSON-YAML-source/src/pages/ymlonclient.js @@ -0,0 +1,50 @@ +import React, { Component } from 'react' +import Layout from '../components/layout' +import SEO from '../components/seo' +import axios from 'axios' +import yaml from 'js-yaml' +import uuid from 'uuid' +class ClientYAML extends Component { + state = { + isError: false, + errorMessage: ``, + yamlData: {}, + } + async componentDidMount() { + try { + const ymlfile = await axios.get(`./second.yaml`) + const data = yaml.safeLoad(ymlfile.data) + this.setState({ yamlData: data }) + } catch (error) { + this.setState({ isError: true, errorMessage: error }) + console.log(`====================================`) + console.log(`ERROR ON LOAD DATA:\n${error}`) + console.log(`====================================`) + } + } + render() { + const { yamlData, isError, errorMessage } = this.state + if (isError) { + return ( +
+

Something went bad

+

{errorMessage}

+
+ ) + } + if (!yamlData.title) { + return

fetching data! give it a moment

+ } + return ( + + +
+ {yamlData.content.map(data => ( +
{data.item}
+ ))} +
+
+ ) + } +} +export default ClientYAML diff --git a/examples/using-JSON-YAML-source/src/templates/basicTemplate.js b/examples/using-JSON-YAML-source/src/templates/basicTemplate.js new file mode 100644 index 0000000000000..aed394c643b86 --- /dev/null +++ b/examples/using-JSON-YAML-source/src/templates/basicTemplate.js @@ -0,0 +1,31 @@ +import React from 'react' +import uuid from 'uuid' +import Layout from '../components/layout' +import SEO from '../components/seo' +import { Link } from 'gatsby' +const basicTemplate = props => { + const { pageContext } = props + const { pageContent, links } = pageContext + + return ( + + +
+ {pageContent.map(data => ( +
{data.item}
+ ))} +
+
+ {links.map(item => ( +
+ {item.to} +
+ ))} +
+
+ ) +} +export default basicTemplate diff --git a/examples/using-JSON-YAML-source/static/second.json b/examples/using-JSON-YAML-source/static/second.json new file mode 100644 index 0000000000000..4afdef25d2467 --- /dev/null +++ b/examples/using-JSON-YAML-source/static/second.json @@ -0,0 +1,17 @@ +{ + "title":"JSON used in the client with React and Gatsby", + "content":[ + { + "item":"Cupcake ipsum dolor. Sit amet marshmallow topping cheesecake muffin. Halvah croissant candy canes bonbon candy. Apple pie jelly beans topping carrot cake danish tart cake cheesecake. Muffin danish chocolate soufflé pastry icing bonbon oat cake. Powder cake jujubes oat cake. Lemon drops tootsie roll marshmallow halvah carrot cake." + }, + { + "item":"Just say anything, George, say what ever's natural, the first thing that comes to your mind. Take that you mutated son-of-a-bitch. My pine, why you. You space bastard, you killed a pine. You do? Yeah, it's 8:00. Hey, McFly, I thought I told you never to come in here. Well it's gonna cost you. How much money you got on you?" + }, + { + "item":192.33 + }, + { + "item":111111 + } + ] +} \ No newline at end of file diff --git a/examples/using-JSON-YAML-source/static/second.yaml b/examples/using-JSON-YAML-source/static/second.yaml new file mode 100644 index 0000000000000..22f60595cf8b2 --- /dev/null +++ b/examples/using-JSON-YAML-source/static/second.yaml @@ -0,0 +1,16 @@ +title: JSON used in the client with React and Gatsby +content: + - item: + Cupcake ipsum dolor. Sit amet marshmallow topping cheesecake muffin. Halvah + croissant candy canes bonbon candy. Apple pie jelly beans topping carrot cake + danish tart cake cheesecake. Muffin danish chocolate soufflé pastry icing bonbon + oat cake. Powder cake jujubes oat cake. Lemon drops tootsie roll marshmallow halvah + carrot cake. + - item: + Just say anything, George, say what ever's natural, the first thing that comes + to your mind. Take that you mutated son-of-a-bitch. My pine, why you. You space + bastard, you killed a pine. You do? Yeah, it's 8:00. Hey, McFly, I thought I told + you never to come in here. Well it's gonna cost you. How much money you got on + you? + - item: 192.33 + - item: 111111 diff --git a/examples/using-js-search/.gitignore b/examples/using-js-search/.gitignore new file mode 100644 index 0000000000000..e86fe25559ba0 --- /dev/null +++ b/examples/using-js-search/.gitignore @@ -0,0 +1,69 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Typescript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# dotenv environment variables file +.env + +# gatsby files +.cache/ +public + +# Mac files +.DS_Store + +# Yarn +yarn-error.log +.pnp/ +.pnp.js +# Yarn Integrity file +.yarn-integrity diff --git a/examples/using-js-search/.prettierrc b/examples/using-js-search/.prettierrc new file mode 100644 index 0000000000000..36301bc5cff6c --- /dev/null +++ b/examples/using-js-search/.prettierrc @@ -0,0 +1,5 @@ +{ + "semi": false, + "singleQuote": true, + "trailingComma": "es5" +} diff --git a/examples/using-js-search/LICENSE b/examples/using-js-search/LICENSE new file mode 100644 index 0000000000000..5169a5e4135e9 --- /dev/null +++ b/examples/using-js-search/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 gatsbyjs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/examples/using-js-search/README.md b/examples/using-js-search/README.md new file mode 100644 index 0000000000000..d32b2e4514d90 --- /dev/null +++ b/examples/using-js-search/README.md @@ -0,0 +1,7 @@ + +## Adding client search using Js Search + +The code in this folder is the full implementation for the documentation on how to add client search with js-search. + +A live version of this example is located [here](https://confident-morse-a366e4.netlify.com/) + diff --git a/examples/using-js-search/gatsby-config.js b/examples/using-js-search/gatsby-config.js new file mode 100644 index 0000000000000..765ebb90203dd --- /dev/null +++ b/examples/using-js-search/gatsby-config.js @@ -0,0 +1,34 @@ +module.exports = { + siteMetadata: { + title: `Gatsby Default Starter`, + description: `Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`, + author: `@gatsbyjs`, + }, + plugins: [ + `gatsby-plugin-react-helmet`, + { + resolve: `gatsby-source-filesystem`, + options: { + name: `images`, + path: `${__dirname}/src/images`, + }, + }, + `gatsby-transformer-sharp`, + `gatsby-plugin-sharp`, + { + resolve: `gatsby-plugin-manifest`, + options: { + name: `gatsby-starter-default`, + short_name: `starter`, + start_url: `/`, + background_color: `#663399`, + theme_color: `#663399`, + display: `minimal-ui`, + icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site. + }, + }, + // this (optional) plugin enables Progressive Web App + Offline functionality + // To learn more, visit: https://gatsby.app/offline + // 'gatsby-plugin-offline', + ], +} diff --git a/examples/using-js-search/gatsby-node.js b/examples/using-js-search/gatsby-node.js new file mode 100644 index 0000000000000..ee10906e5d4f7 --- /dev/null +++ b/examples/using-js-search/gatsby-node.js @@ -0,0 +1,37 @@ +const path = require(`path`) +const axios = require(`axios`) + +exports.createPages = ({ actions }) => { + const { createPage } = actions + return new Promise((resolve, reject) => { + axios + .get(`https://bvaughn.github.io/js-search/books.json`) + .then(result => { + const { data } = result + + createPage({ + path: `/search`, + component: path.resolve(`./src/templates/ClientSearchTemplate.js`), + context: { + bookData: { + allBooks: data.books, + options: { + indexStrategy: `Prefix match`, + searchSanitizer: `Lower Case`, + TitleIndex: true, + AuthorIndex: true, + SearchByTerm: true, + }, + }, + }, + }) + resolve() + }) + .catch(err => { + console.log(`====================================`) + console.log(`error creating Page:${err}`) + console.log(`====================================`) + reject(new Error(`error on page creation:\n${err}`)) + }) + }) +} diff --git a/examples/using-js-search/package.json b/examples/using-js-search/package.json new file mode 100644 index 0000000000000..9ba3224e2fc57 --- /dev/null +++ b/examples/using-js-search/package.json @@ -0,0 +1,47 @@ +{ + "name": "gatsby-starter-default", + "private": true, + "description": "A simple starter to get up and developing quickly with Gatsby", + "version": "0.1.0", + "author": "Kyle Mathews ", + "dependencies": { + "axios": "^0.18.0", + "gatsby": "^2.0.76", + "gatsby-image": "^2.0.20", + "gatsby-plugin-manifest": "^2.0.9", + "gatsby-plugin-offline": "^2.0.16", + "gatsby-plugin-react-helmet": "^3.0.2", + "gatsby-plugin-sharp": "^2.0.14", + "gatsby-source-filesystem": "^2.0.8", + "gatsby-transformer-sharp": "^2.1.8", + "js-search": "^1.4.2", + "lodash": "^4.17.11", + "prop-types": "^15.6.2", + "react": "^16.6.3", + "react-dom": "^16.6.3", + "react-helmet": "^5.2.0" + }, + "keywords": [ + "gatsby" + ], + "license": "MIT", + "scripts": { + "build": "gatsby build", + "develop": "gatsby develop", + "start": "npm run develop", + "clean": "rimraf ./public && rimraf .cache", + "format": "prettier --write \"src/**/*.js\"", + "test": "echo \"Write tests! -> https://gatsby.app/unit-testing\"" + }, + "devDependencies": { + "prettier": "^1.15.2", + "rimraf": "^2.6.3" + }, + "repository": { + "type": "git", + "url": "https://github.com/gatsbyjs/gatsby-starter-default" + }, + "bugs": { + "url": "https://github.com/gatsbyjs/gatsby/issues" + } +} diff --git a/examples/using-js-search/src/components/ClientSearch.js b/examples/using-js-search/src/components/ClientSearch.js new file mode 100644 index 0000000000000..1e91ba1fe9e25 --- /dev/null +++ b/examples/using-js-search/src/components/ClientSearch.js @@ -0,0 +1,224 @@ +import React, { Component } from 'react' +import * as JsSearch from 'js-search' +import DataTable from './DataTable' + +class ClientSearch extends Component { + state = { + isLoading: true, + searchResults: [], + search: null, + isError: false, + indexByTitle: false, + indexByAuthor: false, + termFrequency: true, + removeStopWords: false, + searchQuery: ``, + selectedStrategy: ``, + selectedSanitizer: ``, + } + + static getDerivedStateFromProps(nextProps, prevState) { + if (prevState.search === null) { + const { engine } = nextProps + return { + indexByTitle: engine.TitleIndex, + indexByAuthor: engine.AuthorIndex, + termFrequency: engine.SearchByTerm, + selectedSanitizer: engine.searchSanitizer, + selectedStrategy: engine.indexStrategy, + } + } + return null + } + async componentDidMount() { + this.rebuildIndex() + } + /* eslint-disable */ + onChangeIndexTitle = () => { + this.setState(prevstate => ({ + indexByTitle: !prevstate.indexByTitle, + })) + } + onChangeIndexAuthor = () => { + this.setState(prevstate => ({ + indexByAuthor: !prevstate.indexByAuthor, + })) + this.rebuildIndex() + } + + onChangeStopWords = () => { + this.setState(prevstate => ({ + removeStopWords: !prevstate.removeStopWords, + })) + this.rebuildIndex() + } + /* eslint-enable */ + onChangeStrategy = e => { + this.setState({ selectedStrategy: e.target.value }) + this.rebuildIndex() + } + onChangeSanitizer = e => { + this.setState({ selectedSanitizer: e.target.value }) + this.rebuildIndex() + } + rebuildIndex = () => { + const { + selectedStrategy, + selectedSanitizer, + removeStopWords, + termFrequency, + indexByTitle, + indexByAuthor, + } = this.state + const { books } = this.props + + const dataToSearch = new JsSearch.Search(`isbn`) + if (removeStopWords) { + dataToSearch.tokenizer = new JsSearch.StopWordsTokenizer( + dataToSearch.tokenizer + ) + } + if (selectedStrategy === `All`) { + dataToSearch.indexStrategy = new JsSearch.AllSubstringsIndexStrategy() + } + if (selectedStrategy === `Exact match`) { + dataToSearch.indexStrategy = new JsSearch.ExactWordIndexStrategy() + } + if (selectedStrategy === `Prefix match`) { + dataToSearch.indexStrategy = new JsSearch.PrefixIndexStrategy() + } + selectedSanitizer === `Case Sensitive` + ? (dataToSearch.sanitizer = new JsSearch.CaseSensitiveSanitizer()) + : (dataToSearch.sanitizer = new JsSearch.LowerCaseSanitizer()) + termFrequency === true + ? (dataToSearch.searchIndex = new JsSearch.TfIdfSearchIndex(`isbn`)) + : (dataToSearch.searchIndex = new JsSearch.UnorderedSearchIndex()) + + if (indexByTitle) { + dataToSearch.addIndex(`title`) + } + if (indexByAuthor) { + dataToSearch.addIndex(`author`) + } + dataToSearch.addDocuments(books) + this.setState({ search: dataToSearch, isLoading: false }) + } + searchData = e => { + const { search } = this.state + const queryResult = search.search(e.target.value) + this.setState({ searchQuery: e.target.value, searchResults: queryResult }) + } + handleSubmit = e => { + e.preventDefault() + } + render() { + const { + isLoading, + isError, + searchResults, + searchQuery, + indexByAuthor, + indexByTitle, + removeStopWords, + selectedStrategy, + selectedSanitizer, + } = this.state + const { books } = this.props + if (isLoading) { + return ( +
+

Getting the search all setup

+

+ Getting the search all setup +

+
+ ) + } + if (isError) { + return ( +
+

Ohh no!!!!!

+

+ Something really bad happened +

+
+ ) + } + return ( +
+
+
+
+ + +
+
+ + + +
+
+ + + +
+
+
+ Number of items: + {searchQuery === `` ? books.length : searchResults.length} + +
+
+
+ ) + } +} +export default ClientSearch diff --git a/examples/using-js-search/src/components/DataTable.js b/examples/using-js-search/src/components/DataTable.js new file mode 100644 index 0000000000000..3fabaf1ca91b5 --- /dev/null +++ b/examples/using-js-search/src/components/DataTable.js @@ -0,0 +1,24 @@ +import React from 'react' +import './search.css' +const DataTable = props => ( + + + + + + + + + + {props.data.map(item => ( + + + + + + ))} + +
Book ISBNBook TitleBook Author
{item.isbn}{item.title}{item.author}
+) + +export default DataTable diff --git a/examples/using-js-search/src/components/SearchContainer.js b/examples/using-js-search/src/components/SearchContainer.js new file mode 100644 index 0000000000000..2d6a02e63bec4 --- /dev/null +++ b/examples/using-js-search/src/components/SearchContainer.js @@ -0,0 +1,246 @@ +import React, { Component } from 'react' +import Axios from 'axios' +import * as JsSearch from 'js-search' +import DataTable from './DataTable' +import './search.css' +class Search extends Component { + state = { + bookList: [], + search: [], + searchResults: [], + isLoading: true, + isError: false, + indexByTitle: true, + indexByAuthor: true, + termFrequency: true, + removeStopWords: false, + searchQuery: ``, + selectedStrategy: `Prefix match`, + selectedSanitizer: `Lower Case`, + } + /** + * React lifecycle method to fetch the data + */ + async componentDidMount() { + Axios.get(`https://bvaughn.github.io/js-search/books.json`) + .then(result => { + const bookData = result.data + this.setState({ bookList: bookData.books }) + this.rebuildIndex() + }) + .catch(err => { + this.setState({ isError: true }) + console.log(`====================================`) + console.log(`Something bad happened while fetching the data\n${err}`) + console.log(`====================================`) + }) + } + + /* eslint-disable */ + onChangeIndexTitle = () => { + this.setState(prevstate => ({ + indexByTitle: !prevstate.indexByTitle, + })) + this.rebuildIndex() + } + + onChangeIndexAuthor = () => { + this.setState(prevstate => ({ + indexByAuthor: !prevstate.indexByAuthor, + })) + this.rebuildIndex() + } + + onChangeStopWords = () => { + this.setState(prevstate => ({ + removeStopWords: !prevstate.removeStopWords, + })) + this.rebuildIndex() + } + /* eslint-enable */ + onChangeStrategy = e => { + this.setState({ selectedStrategy: e.target.value }) + this.rebuildIndex() + } + onChangeSanitizer = e => { + this.setState({ selectedSanitizer: e.target.value }) + this.rebuildIndex() + } + + rebuildIndex = () => { + const { + bookList, + selectedStrategy, + selectedSanitizer, + removeStopWords, + termFrequency, + indexByTitle, + indexByAuthor, + } = this.state + + const dataToSearch = new JsSearch.Search(`isbn`) + + if (removeStopWords) { + dataToSearch.tokenizer = new JsSearch.StopWordsTokenizer( + dataToSearch.tokenizer + ) + } + /** + * defines a indexing strategy for the data + * more more about it in here https://github.com/bvaughn/js-search#configuring-the-index-strategy + */ + if (selectedStrategy === `All`) { + dataToSearch.indexStrategy = new JsSearch.AllSubstringsIndexStrategy() + } + if (selectedStrategy === `Exact match`) { + dataToSearch.indexStrategy = new JsSearch.ExactWordIndexStrategy() + } + if (selectedStrategy === `Prefix match`) { + dataToSearch.indexStrategy = new JsSearch.PrefixIndexStrategy() + } + /** + * defines the sanitizer for the search + * to prevent some of the words from being excluded + * + */ + selectedSanitizer === `Case Sensitive` + ? (dataToSearch.sanitizer = new JsSearch.CaseSensitiveSanitizer()) + : (dataToSearch.sanitizer = new JsSearch.LowerCaseSanitizer()) + + /** + * defines the search index + * read more in here https://github.com/bvaughn/js-search#configuring-the-search-index + */ + termFrequency === true + ? (dataToSearch.searchIndex = new JsSearch.TfIdfSearchIndex(`isbn`)) + : (dataToSearch.searchIndex = new JsSearch.UnorderedSearchIndex()) + + if (indexByTitle) { + dataToSearch.addIndex(`title`) // defines the index attribute for the data + } + if (indexByAuthor) { + dataToSearch.addIndex(`author`) // defines the index attribute for the data + } + dataToSearch.addDocuments(bookList) // adds the data to be searched + this.setState({ search: dataToSearch, isLoading: false }) + } + searchData = e => { + const { search } = this.state + const queryResult = search.search(e.target.value) + this.setState({ searchQuery: e.target.value, searchResults: queryResult }) + } + handleSubmit = e => { + e.preventDefault() + } + render() { + const { + isError, + isLoading, + bookList, + searchResults, + searchQuery, + indexByAuthor, + indexByTitle, + removeStopWords, + selectedStrategy, + selectedSanitizer, + } = this.state + if (isLoading) { + return ( +
+

Getting the search all setup

+

+ Getting the search all setup +

+
+ ) + } + if (isError) { + return ( +
+

Ohh no!!!!!

+

+ Something really bad happened +

+
+ ) + } + return ( +
+
+
+
+ + +
+
+ + + +
+
+ + + +
+
+
+ Number of items: + {searchQuery === `` ? bookList.length : searchResults.length} + +
+
+
+ ) + } +} + +export default Search diff --git a/examples/using-js-search/src/components/header.js b/examples/using-js-search/src/components/header.js new file mode 100644 index 0000000000000..235f8834818a3 --- /dev/null +++ b/examples/using-js-search/src/components/header.js @@ -0,0 +1,42 @@ +import { Link } from 'gatsby' +import PropTypes from 'prop-types' +import React from 'react' + +const Header = ({ siteTitle }) => ( +
+
+

+ + {siteTitle} + +

+
+
+) + +Header.propTypes = { + siteTitle: PropTypes.string, +} + +Header.defaultProps = { + siteTitle: ``, +} + +export default Header diff --git a/examples/using-js-search/src/components/layout.css b/examples/using-js-search/src/components/layout.css new file mode 100644 index 0000000000000..68aa9337485f7 --- /dev/null +++ b/examples/using-js-search/src/components/layout.css @@ -0,0 +1,624 @@ +html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +main, +menu, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; +} +audio:not([controls]) { + display: none; + height: 0; +} +progress { + vertical-align: baseline; +} +[hidden], +template { + display: none; +} +a { + background-color: transparent; + -webkit-text-decoration-skip: objects; +} +a:active, +a:hover { + outline-width: 0; +} +abbr[title] { + border-bottom: none; + text-decoration: underline; + text-decoration: underline dotted; +} +b, +strong { + font-weight: inherit; + font-weight: bolder; +} +dfn { + font-style: italic; +} +h1 { + font-size: 2em; + margin: 0.67em 0; +} +mark { + background-color: #ff0; + color: #000; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sub { + bottom: -0.25em; +} +sup { + top: -0.5em; +} +img { + border-style: none; +} +svg:not(:root) { + overflow: hidden; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +figure { + margin: 1em 40px; +} +hr { + box-sizing: content-box; + height: 0; + overflow: visible; +} +button, +input, +optgroup, +select, +textarea { + font: inherit; + margin: 0; +} +optgroup { + font-weight: 700; +} +button, +input { + overflow: visible; +} +button, +select { + text-transform: none; +} +[type='reset'], +[type='submit'], +button, +html [type='button'] { + -webkit-appearance: button; +} +[type='button']::-moz-focus-inner, +[type='reset']::-moz-focus-inner, +[type='submit']::-moz-focus-inner, +button::-moz-focus-inner { + border-style: none; + padding: 0; +} +[type='button']:-moz-focusring, +[type='reset']:-moz-focusring, +[type='submit']:-moz-focusring, +button:-moz-focusring { + outline: 1px dotted ButtonText; +} +fieldset { + border: 1px solid silver; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} +legend { + box-sizing: border-box; + color: inherit; + display: table; + max-width: 100%; + padding: 0; + white-space: normal; +} +textarea { + overflow: auto; +} +[type='checkbox'], +[type='radio'] { + box-sizing: border-box; + padding: 0; +} +[type='number']::-webkit-inner-spin-button, +[type='number']::-webkit-outer-spin-button { + height: auto; +} +[type='search'] { + -webkit-appearance: textfield; + outline-offset: -2px; +} +[type='search']::-webkit-search-cancel-button, +[type='search']::-webkit-search-decoration { + -webkit-appearance: none; +} +::-webkit-input-placeholder { + color: inherit; + opacity: 0.54; +} +::-webkit-file-upload-button { + -webkit-appearance: button; + font: inherit; +} +html { + font: 112.5%/1.45em georgia, serif; + box-sizing: border-box; + overflow-y: scroll; +} +* { + box-sizing: inherit; +} +*:before { + box-sizing: inherit; +} +*:after { + box-sizing: inherit; +} +body { + color: hsla(0, 0%, 0%, 0.8); + font-family: georgia, serif; + font-weight: normal; + word-wrap: break-word; + font-kerning: normal; + -moz-font-feature-settings: 'kern', 'liga', 'clig', 'calt'; + -ms-font-feature-settings: 'kern', 'liga', 'clig', 'calt'; + -webkit-font-feature-settings: 'kern', 'liga', 'clig', 'calt'; + font-feature-settings: 'kern', 'liga', 'clig', 'calt'; +} +img { + max-width: 100%; + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +h1 { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; + color: inherit; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, + Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; + font-weight: bold; + text-rendering: optimizeLegibility; + font-size: 2.25rem; + line-height: 1.1; +} +h2 { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; + color: inherit; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, + Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; + font-weight: bold; + text-rendering: optimizeLegibility; + font-size: 1.62671rem; + line-height: 1.1; +} +h3 { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; + color: inherit; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, + Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; + font-weight: bold; + text-rendering: optimizeLegibility; + font-size: 1.38316rem; + line-height: 1.1; +} +h4 { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; + color: inherit; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, + Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; + font-weight: bold; + text-rendering: optimizeLegibility; + font-size: 1rem; + line-height: 1.1; +} +h5 { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; + color: inherit; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, + Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; + font-weight: bold; + text-rendering: optimizeLegibility; + font-size: 0.85028rem; + line-height: 1.1; +} +h6 { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; + color: inherit; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, + Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; + font-weight: bold; + text-rendering: optimizeLegibility; + font-size: 0.78405rem; + line-height: 1.1; +} +hgroup { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +ul { + margin-left: 1.45rem; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; + list-style-position: outside; + list-style-image: none; +} +ol { + margin-left: 1.45rem; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; + list-style-position: outside; + list-style-image: none; +} +dl { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +dd { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +p { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +figure { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +pre { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; + font-size: 0.85rem; + line-height: 1.42; + background: hsla(0, 0%, 0%, 0.04); + border-radius: 3px; + overflow: auto; + word-wrap: normal; + padding: 1.45rem; +} +table { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; + font-size: 1rem; + line-height: 1.45rem; + border-collapse: collapse; + width: 100%; +} +fieldset { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +blockquote { + margin-left: 1.45rem; + margin-right: 1.45rem; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +form { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +noscript { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +iframe { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +hr { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: calc(1.45rem - 1px); + background: hsla(0, 0%, 0%, 0.2); + border: none; + height: 1px; +} +address { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: 0; + margin-bottom: 1.45rem; +} +b { + font-weight: bold; +} +strong { + font-weight: bold; +} +dt { + font-weight: bold; +} +th { + font-weight: bold; +} +li { + margin-bottom: calc(1.45rem / 2); +} +ol li { + padding-left: 0; +} +ul li { + padding-left: 0; +} +li > ol { + margin-left: 1.45rem; + margin-bottom: calc(1.45rem / 2); + margin-top: calc(1.45rem / 2); +} +li > ul { + margin-left: 1.45rem; + margin-bottom: calc(1.45rem / 2); + margin-top: calc(1.45rem / 2); +} +blockquote *:last-child { + margin-bottom: 0; +} +li *:last-child { + margin-bottom: 0; +} +p *:last-child { + margin-bottom: 0; +} +li > p { + margin-bottom: calc(1.45rem / 2); +} +code { + font-size: 0.85rem; + line-height: 1.45rem; +} +kbd { + font-size: 0.85rem; + line-height: 1.45rem; +} +samp { + font-size: 0.85rem; + line-height: 1.45rem; +} +abbr { + border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); + cursor: help; +} +acronym { + border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); + cursor: help; +} +abbr[title] { + border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); + cursor: help; + text-decoration: none; +} +thead { + text-align: left; +} +td, +th { + text-align: left; + border-bottom: 1px solid hsla(0, 0%, 0%, 0.12); + font-feature-settings: 'tnum'; + -moz-font-feature-settings: 'tnum'; + -ms-font-feature-settings: 'tnum'; + -webkit-font-feature-settings: 'tnum'; + padding-left: 0.96667rem; + padding-right: 0.96667rem; + padding-top: 0.725rem; + padding-bottom: calc(0.725rem - 1px); +} +th:first-child, +td:first-child { + padding-left: 0; +} +th:last-child, +td:last-child { + padding-right: 0; +} +tt, +code { + background-color: hsla(0, 0%, 0%, 0.04); + border-radius: 3px; + font-family: 'SFMono-Regular', Consolas, 'Roboto Mono', 'Droid Sans Mono', + 'Liberation Mono', Menlo, Courier, monospace; + padding: 0; + padding-top: 0.2em; + padding-bottom: 0.2em; +} +pre code { + background: none; + line-height: 1.42; +} +code:before, +code:after, +tt:before, +tt:after { + letter-spacing: -0.2em; + content: ' '; +} +pre code:before, +pre code:after, +pre tt:before, +pre tt:after { + content: ''; +} +@media only screen and (max-width: 480px) { + html { + font-size: 100%; + } +} diff --git a/examples/using-js-search/src/components/layout.js b/examples/using-js-search/src/components/layout.js new file mode 100644 index 0000000000000..ca89ed4578b3d --- /dev/null +++ b/examples/using-js-search/src/components/layout.js @@ -0,0 +1,86 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { StaticQuery, graphql } from 'gatsby' +import Helmet from 'react-helmet' +import Header from './header' +import './layout.css' + +const Layout = ({ children }) => ( + ( + <> + +
+
+ {children} +
+ © {new Date().getFullYear()}, Built with + {` `} + Gatsby +
+
+ + )} + /> +) + +Layout.propTypes = { + children: PropTypes.node.isRequired, +} + +export default Layout diff --git a/examples/using-js-search/src/components/search.css b/examples/using-js-search/src/components/search.css new file mode 100644 index 0000000000000..f55d863acc4ce --- /dev/null +++ b/examples/using-js-search/src/components/search.css @@ -0,0 +1,43 @@ +table { + width: 100%; + border-collapse: collapse; + border-radius: 4px; + border: 1px solid lightgray; + background-color: white; +} + +thead { + border-bottom: 1px solid gray; +} + +th { + text-align: left; + padding: 5px; + font-size: 14px; + font-weight: 600; + border-bottom: 2px solid lightgray; + cursor: pointer; +} + +tr:nth-child(even) { + background-color: #dddddd; +} +label{ + padding-right:10px; +} + +input{ + margin-left: 10px; +} +.searchQuery{ + margin: 0 auto; + width: 400px; +} +.form-group{ + margin: 1.2rem 1rem 1.2rem 1rem; +} +td { + font-size: 14px; + border: 1px solid lightgray; + padding: 5px; +} diff --git a/examples/using-js-search/src/components/seo.js b/examples/using-js-search/src/components/seo.js new file mode 100644 index 0000000000000..f143908a2bb92 --- /dev/null +++ b/examples/using-js-search/src/components/seo.js @@ -0,0 +1,103 @@ +import React from 'react' +import PropTypes from 'prop-types' +import Helmet from 'react-helmet' +import { StaticQuery, graphql } from 'gatsby' + +function SEO({ description, lang, meta, keywords, title }) { + return ( + { + const metaDescription = + description || data.site.siteMetadata.description + return ( + 0 + ? { + name: `keywords`, + content: keywords.join(`, `), + } + : [] + ) + .concat(meta)} + /> + ) + }} + /> + ) +} + +SEO.defaultProps = { + lang: `en`, + meta: [], + keywords: [], +} + +SEO.propTypes = { + description: PropTypes.string, + lang: PropTypes.string, + meta: PropTypes.array, + keywords: PropTypes.arrayOf(PropTypes.string), + title: PropTypes.string.isRequired, +} + +export default SEO + +const detailsQuery = graphql` + query DefaultSEOQuery { + site { + siteMetadata { + title + description + author + } + } + } +` diff --git a/examples/using-js-search/src/images/gatsby-icon.png b/examples/using-js-search/src/images/gatsby-icon.png new file mode 100644 index 0000000000000..908bc78a7f559 Binary files /dev/null and b/examples/using-js-search/src/images/gatsby-icon.png differ diff --git a/examples/using-js-search/src/pages/404.js b/examples/using-js-search/src/pages/404.js new file mode 100644 index 0000000000000..77a691f9da56d --- /dev/null +++ b/examples/using-js-search/src/pages/404.js @@ -0,0 +1,14 @@ +import React from 'react' + +import Layout from '../components/layout' +import SEO from '../components/seo' + +const NotFoundPage = () => ( + + +

NOT FOUND

+

You just hit a route that doesn't exist... the sadness.

+
+) + +export default NotFoundPage diff --git a/examples/using-js-search/src/pages/index.js b/examples/using-js-search/src/pages/index.js new file mode 100644 index 0000000000000..b6a7b440674d1 --- /dev/null +++ b/examples/using-js-search/src/pages/index.js @@ -0,0 +1,19 @@ +import React from 'react' +import Layout from '../components/layout' +import Search from '../components/SearchContainer' + +const IndexPage = () => ( + +

+ Search data using JS Search +

+

+ Books Indexed by: +

+
+ +
+
+) + +export default IndexPage diff --git a/examples/using-js-search/src/templates/ClientSearchTemplate.js b/examples/using-js-search/src/templates/ClientSearchTemplate.js new file mode 100644 index 0000000000000..a99eec8aa1044 --- /dev/null +++ b/examples/using-js-search/src/templates/ClientSearchTemplate.js @@ -0,0 +1,25 @@ +import React from 'react' +import Layout from '../components/layout' +import ClientSearch from '../components/ClientSearch' + +const SearchTemplate = props => { + const { pageContext } = props + const { bookData } = pageContext + const { allBooks, options } = bookData + return ( + +

+ Search data using JS Search using Gatsby Api +

+

+ Books Indexed by: +

+ +
+ +
+
+ ) +} + +export default SearchTemplate diff --git a/www/src/data/sidebars/doc-links.yaml b/www/src/data/sidebars/doc-links.yaml index a3e4bc27a87df..80eb3e23e8d90 100644 --- a/www/src/data/sidebars/doc-links.yaml +++ b/www/src/data/sidebars/doc-links.yaml @@ -198,7 +198,7 @@ link: /docs/adding-search-with-algolia/ - title: Adding search with elasticlunr* link: /docs/adding-search-with-elasticlunr/ - - title: Adding search with js-search* + - title: Adding search with js-search/ link: /docs/adding-search-with-js-search/ - title: Adding analytics link: /docs/adding-analytics/ diff --git a/www/src/data/sidebars/tutorial-links.yaml b/www/src/data/sidebars/tutorial-links.yaml index 5838ee0c029a3..873b54d214cff 100644 --- a/www/src/data/sidebars/tutorial-links.yaml +++ b/www/src/data/sidebars/tutorial-links.yaml @@ -110,3 +110,6 @@ link: /tutorial/part-eight/#add-page-metadata - title: Keep making it better link: /tutorial/part-eight/#keep-making-it-better + - title: Appendix. Sourcing from JSON or YAML + link: /tutorial/appendix/source-JSON-YAML + ui: steps