├── .cache ├── redirects.json ├── match-paths.json ├── pages.json ├── __tests__ │ ├── .babelrc │ ├── __snapshots__ │ │ ├── dev-loader.js.snap │ │ ├── loader.js.snap │ │ └── static-entry.js.snap │ ├── minimal-config.js │ ├── strip-prefix.js │ ├── ensure-resources.tsx │ ├── error-overlay-handler.js │ ├── find-path.js │ └── static-entry.js ├── react-lifecycles-compat.js ├── commonjs │ ├── react-lifecycles-compat.js │ ├── create-react-context.js │ ├── emitter.js │ ├── public-page-renderer.js │ ├── normalize-page-path.js │ ├── api-runner-browser-plugins.js │ ├── strip-prefix.js │ ├── route-announcer-props.js │ ├── public-page-renderer-prod.js │ ├── public-page-renderer-dev.js │ ├── api-runner-ssr.js │ ├── dev-loader.js │ ├── default-html.js │ ├── page-renderer.js │ ├── api-runner-browser.js │ ├── prefetch.js │ ├── error-overlay-handler.js │ ├── app.js │ ├── register-service-worker.js │ ├── find-path.js │ ├── ensure-resources.js │ ├── develop-static-entry.js │ ├── socketIo.js │ ├── gatsby-browser-entry.js │ ├── query-result-store.js │ ├── root.js │ ├── production-app.js │ ├── navigation.js │ └── api-ssr-docs.js ├── create-react-context.js ├── emitter.js ├── redux │ ├── redux.rest.state │ └── redux.node.state_0 ├── .eslintrc.json ├── normalize-page-path.js ├── public-page-renderer.js ├── strip-prefix.js ├── api-runner-browser-plugins.js ├── route-announcer-props.js ├── public-page-renderer-dev.js ├── public-page-renderer-prod.js ├── async-requires.js ├── sync-requires.js ├── test-require-error.js ├── default-html.js ├── caches │ └── gatsby-transformer-sharp │ │ └── diskstore-66c1da6000f7fd2228748e1552fc342e.json ├── page-renderer.js ├── dev-loader.js ├── api-runner-ssr.js ├── api-runner-browser.js ├── prefetch.js ├── app.js ├── error-overlay-handler.js ├── find-path.js ├── ensure-resources.js ├── register-service-worker.js ├── gatsby-browser-entry.js ├── develop-static-entry.js ├── query-result-store.js ├── socketIo.js ├── root.js ├── babelState.json ├── production-app.js ├── dev-404-page.js ├── navigation.js ├── api-ssr-docs.js └── static-entry.js ├── .gitignore ├── public ├── robots.txt ├── favicon.ico └── index.html ├── Boilerplate.png ├── src ├── assets │ └── tailwind.css ├── pages │ ├── Home.js │ └── sections │ │ └── HomeMainSection.js ├── setupTests.js ├── App.test.js ├── App.js ├── index.js ├── App.css └── serviceWorker.js ├── tailwind.config.js ├── postcss.config.js ├── README.md └── package.json /.cache/redirects.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /.cache/match-paths.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /.cache/pages.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.cache/__tests__/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["babel-preset-gatsby"]] 3 | } 4 | -------------------------------------------------------------------------------- /.cache/react-lifecycles-compat.js: -------------------------------------------------------------------------------- 1 | exports.polyfill = Component => Component 2 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /.cache/commonjs/react-lifecycles-compat.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | exports.polyfill = Component => Component; -------------------------------------------------------------------------------- /.cache/create-react-context.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | export default React.createContext 4 | -------------------------------------------------------------------------------- /.cache/emitter.js: -------------------------------------------------------------------------------- 1 | import mitt from "mitt" 2 | 3 | const emitter = mitt() 4 | export default emitter 5 | -------------------------------------------------------------------------------- /Boilerplate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zStorm-Development/react-tailwind-ui-starter-plate/master/Boilerplate.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zStorm-Development/react-tailwind-ui-starter-plate/master/public/favicon.ico -------------------------------------------------------------------------------- /src/assets/tailwind.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | 3 | @tailwind components; 4 | 5 | @tailwind utilities; 6 | 7 | @tailwind css/ui; 8 | -------------------------------------------------------------------------------- /.cache/redux/redux.rest.state: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zStorm-Development/react-tailwind-ui-starter-plate/master/.cache/redux/redux.rest.state -------------------------------------------------------------------------------- /.cache/redux/redux.node.state_0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zStorm-Development/react-tailwind-ui-starter-plate/master/.cache/redux/redux.node.state_0 -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require("tailwindcss"), 4 | require("autoprefixer"), 5 | require("@tailwindcss/ui"), 6 | ], 7 | }; 8 | -------------------------------------------------------------------------------- /.cache/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true 4 | }, 5 | "globals": { 6 | "__PATH_PREFIX__": false, 7 | "___emitter": false 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/pages/Home.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import HomeMainSection from "./sections/HomeMainSection"; 3 | 4 | export default function Home() { 5 | return ( 6 |
7 | 8 |
9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /.cache/normalize-page-path.js: -------------------------------------------------------------------------------- 1 | export default path => { 2 | if (path === undefined) { 3 | return path 4 | } 5 | if (path === `/`) { 6 | return `/` 7 | } 8 | if (path.charAt(path.length - 1) === `/`) { 9 | return path.slice(0, -1) 10 | } 11 | return path 12 | } 13 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /.cache/commonjs/create-react-context.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 | 5 | exports.__esModule = true; 6 | exports.default = void 0; 7 | 8 | var _react = _interopRequireDefault(require("react")); 9 | 10 | var _default = _react.default.createContext; 11 | exports.default = _default; -------------------------------------------------------------------------------- /.cache/commonjs/emitter.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 | 5 | exports.__esModule = true; 6 | exports.default = void 0; 7 | 8 | var _mitt = _interopRequireDefault(require("mitt")); 9 | 10 | const emitter = (0, _mitt.default)(); 11 | var _default = emitter; 12 | exports.default = _default; -------------------------------------------------------------------------------- /.cache/public-page-renderer.js: -------------------------------------------------------------------------------- 1 | const preferDefault = m => (m && m.default) || m 2 | 3 | if (process.env.BUILD_STAGE === `develop`) { 4 | module.exports = preferDefault(require(`./public-page-renderer-dev`)) 5 | } else if (process.env.BUILD_STAGE === `build-javascript`) { 6 | module.exports = preferDefault(require(`./public-page-renderer-prod`)) 7 | } else { 8 | module.exports = () => null 9 | } 10 | -------------------------------------------------------------------------------- /.cache/strip-prefix.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Remove a prefix from a string. Return the input string if the given prefix 3 | * isn't found. 4 | */ 5 | 6 | export default (str, prefix = ``) => { 7 | if (!prefix) { 8 | return str 9 | } 10 | 11 | prefix += `/` 12 | 13 | if (str.substr(0, prefix.length) === prefix) { 14 | return str.slice(prefix.length - 1) 15 | } 16 | 17 | return str 18 | } 19 | -------------------------------------------------------------------------------- /.cache/commonjs/public-page-renderer.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const preferDefault = m => m && m.default || m; 4 | 5 | if (process.env.BUILD_STAGE === `develop`) { 6 | module.exports = preferDefault(require(`./public-page-renderer-dev`)); 7 | } else if (process.env.BUILD_STAGE === `build-javascript`) { 8 | module.exports = preferDefault(require(`./public-page-renderer-prod`)); 9 | } else { 10 | module.exports = () => null; 11 | } -------------------------------------------------------------------------------- /.cache/commonjs/normalize-page-path.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | exports.__esModule = true; 4 | exports.default = void 0; 5 | 6 | var _default = path => { 7 | if (path === undefined) { 8 | return path; 9 | } 10 | 11 | if (path === `/`) { 12 | return `/`; 13 | } 14 | 15 | if (path.charAt(path.length - 1) === `/`) { 16 | return path.slice(0, -1); 17 | } 18 | 19 | return path; 20 | }; 21 | 22 | exports.default = _default; -------------------------------------------------------------------------------- /.cache/commonjs/api-runner-browser-plugins.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // During bootstrap, we write requires at top of this file which looks 4 | // basically like: 5 | // module.exports = [ 6 | // { 7 | // plugin: require("/path/to/plugin1/gatsby-browser.js"), 8 | // options: { ... }, 9 | // }, 10 | // { 11 | // plugin: require("/path/to/plugin2/gatsby-browser.js"), 12 | // options: { ... }, 13 | // }, 14 | // ] 15 | module.exports = []; -------------------------------------------------------------------------------- /.cache/api-runner-browser-plugins.js: -------------------------------------------------------------------------------- 1 | module.exports = [{ 2 | plugin: require('../node_modules/gatsby-plugin-manifest/gatsby-browser.js'), 3 | options: {"plugins":[],"name":"gatsby-starter-default","short_name":"starter","start_url":"/","background_color":"#663399","theme_color":"#663399","display":"minimal-ui","icon":"src/images/gatsby-icon.png"}, 4 | },{ 5 | plugin: require('../gatsby-browser.js'), 6 | options: {"plugins":[]}, 7 | }] 8 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { BrowserRouter, Route, Switch } from "react-router-dom"; 3 | import "./assets/main.css"; 4 | import Home from "./pages/Home"; 5 | 6 | function App() { 7 | return ( 8 |
9 | 10 |
11 | 12 | 13 | 14 |
15 |
16 |
17 | ); 18 | } 19 | 20 | export default App; 21 | -------------------------------------------------------------------------------- /.cache/__tests__/__snapshots__/dev-loader.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Dev loader loadPage should be successful when component can be loaded 1`] = ` 4 | Object { 5 | "component": "instance", 6 | "json": Object { 7 | "pageContext": "something something", 8 | }, 9 | "page": Object { 10 | "componentChunkName": "chunk", 11 | "matchPath": undefined, 12 | "path": "/mypage/", 13 | "webpackCompilationHash": "123", 14 | }, 15 | } 16 | `; 17 | -------------------------------------------------------------------------------- /.cache/__tests__/__snapshots__/loader.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Production loader loadPage should be successful when component can be loaded 1`] = ` 4 | Object { 5 | "component": "instance", 6 | "json": Object { 7 | "pageContext": "something something", 8 | }, 9 | "page": Object { 10 | "componentChunkName": "chunk", 11 | "matchPath": undefined, 12 | "path": "/mypage/", 13 | "webpackCompilationHash": "123", 14 | }, 15 | } 16 | `; 17 | -------------------------------------------------------------------------------- /.cache/route-announcer-props.js: -------------------------------------------------------------------------------- 1 | // This is extracted to separate module because it's shared 2 | // between browser and SSR code 3 | export const RouteAnnouncerProps = { 4 | id: `gatsby-announcer`, 5 | style: { 6 | position: `absolute`, 7 | top: 0, 8 | width: 1, 9 | height: 1, 10 | padding: 0, 11 | overflow: `hidden`, 12 | clip: `rect(0, 0, 0, 0)`, 13 | whiteSpace: `nowrap`, 14 | border: 0, 15 | }, 16 | "aria-live": `assertive`, 17 | "aria-atomic": `true`, 18 | } 19 | -------------------------------------------------------------------------------- /.cache/commonjs/strip-prefix.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | exports.__esModule = true; 4 | exports.default = void 0; 5 | 6 | /** 7 | * Remove a prefix from a string. Return the input string if the given prefix 8 | * isn't found. 9 | */ 10 | var _default = (str, prefix = ``) => { 11 | if (!prefix) { 12 | return str; 13 | } 14 | 15 | prefix += `/`; 16 | 17 | if (str.substr(0, prefix.length) === prefix) { 18 | return str.slice(prefix.length - 1); 19 | } 20 | 21 | return str; 22 | }; 23 | 24 | exports.default = _default; -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import App from "./App"; 4 | import * as serviceWorker from "./serviceWorker"; 5 | 6 | ReactDOM.render( 7 | 8 | 9 | , 10 | document.getElementById("root") 11 | ); 12 | 13 | // If you want your app to work offline and load faster, you can change 14 | // unregister() to register() below. Note this comes with some pitfalls. 15 | // Learn more about service workers: https://bit.ly/CRA-PWA 16 | serviceWorker.unregister(); 17 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | // postcss.config.js 2 | const purgecss = require("@fullhuman/postcss-purgecss")({ 3 | // Specify the paths to all of the template files in your project 4 | content: [ 5 | "./src/**/*.html", 6 | "./src/**/*.vue", 7 | "./src/**/*.jsx", 8 | // etc. 9 | ], 10 | 11 | // Include any special characters you're using in this regular expression 12 | }); 13 | 14 | module.exports = { 15 | plugins: [ 16 | require("tailwindcss"), 17 | require("autoprefixer"), 18 | ...(process.env.NODE_ENV == "production" ? [purgecss] : []), 19 | ], 20 | }; 21 | -------------------------------------------------------------------------------- /.cache/public-page-renderer-dev.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | 4 | import loader from "./loader" 5 | import { PageQueryStore } from "./query-result-store" 6 | 7 | const DevPageRenderer = ({ location }) => { 8 | const pageResources = loader.loadPageSync(location.pathname) 9 | return React.createElement(PageQueryStore, { 10 | location, 11 | pageResources, 12 | }) 13 | } 14 | 15 | DevPageRenderer.propTypes = { 16 | location: PropTypes.shape({ 17 | pathname: PropTypes.string.isRequired, 18 | }).isRequired, 19 | } 20 | 21 | export default DevPageRenderer 22 | -------------------------------------------------------------------------------- /.cache/public-page-renderer-prod.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | 4 | import InternalPageRenderer from "./page-renderer" 5 | 6 | const ProdPageRenderer = ({ location, pageResources }) => { 7 | if (!pageResources) { 8 | return null 9 | } 10 | return React.createElement(InternalPageRenderer, { 11 | location, 12 | pageResources, 13 | ...pageResources.json, 14 | }) 15 | } 16 | 17 | ProdPageRenderer.propTypes = { 18 | location: PropTypes.shape({ 19 | pathname: PropTypes.string.isRequired, 20 | }).isRequired, 21 | } 22 | 23 | export default ProdPageRenderer 24 | -------------------------------------------------------------------------------- /.cache/commonjs/route-announcer-props.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | exports.__esModule = true; 4 | exports.RouteAnnouncerProps = void 0; 5 | // This is extracted to separate module because it's shared 6 | // between browser and SSR code 7 | const RouteAnnouncerProps = { 8 | id: `gatsby-announcer`, 9 | style: { 10 | position: `absolute`, 11 | top: 0, 12 | width: 1, 13 | height: 1, 14 | padding: 0, 15 | overflow: `hidden`, 16 | clip: `rect(0, 0, 0, 0)`, 17 | whiteSpace: `nowrap`, 18 | border: 0 19 | }, 20 | "aria-live": `assertive`, 21 | "aria-atomic": `true` 22 | }; 23 | exports.RouteAnnouncerProps = RouteAnnouncerProps; -------------------------------------------------------------------------------- /.cache/async-requires.js: -------------------------------------------------------------------------------- 1 | // prefer default export if available 2 | const preferDefault = m => m && m.default || m 3 | 4 | exports.components = { 5 | "component---cache-dev-404-page-js": () => import("./dev-404-page.js" /* webpackChunkName: "component---cache-dev-404-page-js" */), 6 | "component---src-pages-404-js": () => import("./../src/pages/404.js" /* webpackChunkName: "component---src-pages-404-js" */), 7 | "component---src-pages-index-js": () => import("./../src/pages/index.js" /* webpackChunkName: "component---src-pages-index-js" */), 8 | "component---src-pages-page-2-tsx": () => import("./../src/pages/page-2.tsx" /* webpackChunkName: "component---src-pages-page-2-tsx" */) 9 | } 10 | 11 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React + TailWindCss + TailWindUI 2 | ![Image of Boilerplate](https://github.com/zStorm-Development/react-tailwind-ui-starter-plate/blob/master/Boilerplate.png) 3 | 4 | ## Simple to get started 5 | - Clone Repo 6 | - Npm i 7 | - Npm Start 8 | 9 | ### Resources 10 | 11 | - Article/Guide 12 | - https://medium.com/@steven_creates/reactjs-tailwindui-and-tailwindcss-boilerplate-65143fc49489 13 | 14 | - Tailwind UI 15 | - https://tailwindui.com/components 16 | 17 | - Tailwind CSS Docs 18 | - https://tailwindcss.com/docs/installation 19 | 20 | ### Find Me 21 | - LinkedIn: https://www.linkedin.com/in/steven-hofheins/ 22 | - Medium: https://medium.com/@steven_creates 23 | - GitHub: https://github.com/StevenCreates 24 | 25 | 26 | **If you end up cloning this more than once please star it** 27 | -------------------------------------------------------------------------------- /.cache/__tests__/minimal-config.js: -------------------------------------------------------------------------------- 1 | const path = require(`path`) 2 | const child = require(`child_process`) 3 | 4 | it(`Builds cache-dir with minimal config`, done => { 5 | const args = [ 6 | require.resolve(`@babel/cli/bin/babel.js`), 7 | path.join(__dirname, `..`), 8 | `--config-file`, 9 | path.join(__dirname, `.babelrc`), 10 | `--ignore`, 11 | `**/__tests__`, 12 | ] 13 | 14 | const spawn = child.spawn(process.execPath, args) 15 | 16 | let stderr = `` 17 | let stdout = `` 18 | 19 | spawn.stderr.on(`data`, function (chunk) { 20 | stderr += chunk 21 | }) 22 | 23 | spawn.stdout.on(`data`, function (chunk) { 24 | stdout += chunk 25 | }) 26 | 27 | spawn.on(`close`, function () { 28 | expect(stderr).toEqual(``) 29 | expect(stdout).not.toEqual(``) 30 | done() 31 | }) 32 | }, 30000) 33 | -------------------------------------------------------------------------------- /.cache/sync-requires.js: -------------------------------------------------------------------------------- 1 | const { hot } = require("react-hot-loader/root") 2 | 3 | // prefer default export if available 4 | const preferDefault = m => m && m.default || m 5 | 6 | 7 | exports.components = { 8 | "component---cache-dev-404-page-js": hot(preferDefault(require("/Users/hofheins/Desktop/Stevens Things/zorg/react-tailwind-starter-plate/.cache/dev-404-page.js"))), 9 | "component---src-pages-404-js": hot(preferDefault(require("/Users/hofheins/Desktop/Stevens Things/zorg/react-tailwind-starter-plate/src/pages/404.js"))), 10 | "component---src-pages-index-js": hot(preferDefault(require("/Users/hofheins/Desktop/Stevens Things/zorg/react-tailwind-starter-plate/src/pages/index.js"))), 11 | "component---src-pages-page-2-tsx": hot(preferDefault(require("/Users/hofheins/Desktop/Stevens Things/zorg/react-tailwind-starter-plate/src/pages/page-2.tsx"))) 12 | } 13 | 14 | -------------------------------------------------------------------------------- /.cache/__tests__/strip-prefix.js: -------------------------------------------------------------------------------- 1 | const stripPrefix = require(`../strip-prefix`).default 2 | 3 | describe(`strip-prefix`, () => { 4 | it(`strips a prefix`, () => { 5 | expect(stripPrefix(`/foo/bar/`, `/foo`)).toBe(`/bar/`) 6 | }) 7 | 8 | it(`strips first instance only`, () => { 9 | expect(stripPrefix(`/foo/foo/bar/`, `/foo`)).toBe(`/foo/bar/`) 10 | }) 11 | 12 | it(`strips full instance only`, () => { 13 | expect(stripPrefix(`/footest/`, `/foo`)).toBe(`/footest/`) 14 | }) 15 | 16 | it(`ignores prefix appearing elsewhere in the string`, () => { 17 | expect(stripPrefix(`/foo/bar/`, `bar`)).toBe(`/foo/bar/`) 18 | }) 19 | 20 | it(`ignores a non-existent prefix`, () => { 21 | expect(stripPrefix(`/bar`, `/foo`)).toBe(`/bar`) 22 | }) 23 | 24 | it(`returns input str if no prefix is provided`, () => { 25 | expect(stripPrefix(`/bar`)).toBe(`/bar`) 26 | }) 27 | }) 28 | -------------------------------------------------------------------------------- /.cache/test-require-error.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | exports.__esModule = true; 4 | exports.testRequireError = void 0; 5 | 6 | // This module is also copied into the .cache directory some modules copied there 7 | // from cache-dir can also use this module. 8 | const testRequireError = (moduleName, err) => { 9 | // PnP will return the following code when a require is allowed per the 10 | // dependency tree rules but the requested file doesn't exist 11 | if (err.code === `QUALIFIED_PATH_RESOLUTION_FAILED` || err.pnpCode === `QUALIFIED_PATH_RESOLUTION_FAILED`) { 12 | return true; 13 | } 14 | 15 | const regex = new RegExp(`Error:\\s(\\S+\\s)?[Cc]annot find module\\s.${moduleName.replace(/[-/\\^$*+?.()|[\]{}]/g, `\\$&`)}`); 16 | const firstLine = err.toString().split(`\n`)[0]; 17 | return regex.test(firstLine); 18 | }; 19 | 20 | exports.testRequireError = testRequireError; 21 | //# sourceMappingURL=test-require-error.js.map -------------------------------------------------------------------------------- /.cache/commonjs/public-page-renderer-prod.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 | 5 | exports.__esModule = true; 6 | exports.default = void 0; 7 | 8 | var _react = _interopRequireDefault(require("react")); 9 | 10 | var _propTypes = _interopRequireDefault(require("prop-types")); 11 | 12 | var _pageRenderer = _interopRequireDefault(require("./page-renderer")); 13 | 14 | const ProdPageRenderer = ({ 15 | location, 16 | pageResources 17 | }) => { 18 | if (!pageResources) { 19 | return null; 20 | } 21 | 22 | return _react.default.createElement(_pageRenderer.default, { 23 | location, 24 | pageResources, 25 | ...pageResources.json 26 | }); 27 | }; 28 | 29 | ProdPageRenderer.propTypes = { 30 | location: _propTypes.default.shape({ 31 | pathname: _propTypes.default.string.isRequired 32 | }).isRequired 33 | }; 34 | var _default = ProdPageRenderer; 35 | exports.default = _default; -------------------------------------------------------------------------------- /.cache/commonjs/public-page-renderer-dev.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 | 5 | exports.__esModule = true; 6 | exports.default = void 0; 7 | 8 | var _react = _interopRequireDefault(require("react")); 9 | 10 | var _propTypes = _interopRequireDefault(require("prop-types")); 11 | 12 | var _loader = _interopRequireDefault(require("./loader")); 13 | 14 | var _queryResultStore = require("./query-result-store"); 15 | 16 | const DevPageRenderer = ({ 17 | location 18 | }) => { 19 | const pageResources = _loader.default.loadPageSync(location.pathname); 20 | 21 | return _react.default.createElement(_queryResultStore.PageQueryStore, { 22 | location, 23 | pageResources 24 | }); 25 | }; 26 | 27 | DevPageRenderer.propTypes = { 28 | location: _propTypes.default.shape({ 29 | pathname: _propTypes.default.string.isRequired 30 | }).isRequired 31 | }; 32 | var _default = DevPageRenderer; 33 | exports.default = _default; -------------------------------------------------------------------------------- /.cache/__tests__/ensure-resources.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import EnsureResources from "../ensure-resources" 3 | import { render, getNodeText, cleanup } from "@testing-library/react" 4 | 5 | jest.mock(`../loader`, () => { 6 | return { 7 | loadPageSync(path: string): { loadPageSync: boolean; path: string } { 8 | return { loadPageSync: true, path } 9 | }, 10 | loadPage(path: string): Promise<{ loadPage: boolean; path: string }> { 11 | return Promise.resolve({ loadPage: true, path }) 12 | }, 13 | } 14 | }) 15 | 16 | afterAll(cleanup) 17 | 18 | describe(`EnsureResources`, () => { 19 | it(`loads pages synchronously`, () => { 20 | const location = { 21 | pathname: `/`, 22 | } 23 | const { container } = render( 24 | 25 | {(data: any): string => JSON.stringify(data.pageResources)} 26 | 27 | ) 28 | 29 | expect(getNodeText(container)).toMatchInlineSnapshot( 30 | `"{\\"loadPageSync\\":true,\\"path\\":\\"/\\"}"` 31 | ) 32 | }) 33 | }) 34 | -------------------------------------------------------------------------------- /.cache/default-html.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | 4 | export default function HTML(props) { 5 | return ( 6 | 7 | 8 | 9 | 10 | 14 | {props.headComponents} 15 | 16 | 17 | {props.preBodyComponents} 18 |
23 | {props.postBodyComponents} 24 | 25 | 26 | ) 27 | } 28 | 29 | HTML.propTypes = { 30 | htmlAttributes: PropTypes.object, 31 | headComponents: PropTypes.array, 32 | bodyAttributes: PropTypes.object, 33 | preBodyComponents: PropTypes.array, 34 | body: PropTypes.string, 35 | postBodyComponents: PropTypes.array, 36 | } 37 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@tailwindcss/ui": "^0.3.0", 7 | "@testing-library/jest-dom": "^4.2.4", 8 | "@testing-library/react": "^9.3.2", 9 | "@testing-library/user-event": "^7.1.2", 10 | "react": "^16.13.1", 11 | "react-dom": "^16.13.1", 12 | "react-router-dom": "^5.2.0", 13 | "react-scripts": "3.4.1" 14 | }, 15 | "scripts": { 16 | "start": "npm run watch:css && react-scripts start", 17 | "build": "npm run build:css && react-scripts build", 18 | "test": "react-scripts test", 19 | "eject": "react-scripts eject", 20 | "build:css": "postcss src/assets/tailwind.css -o src/assets/main.css", 21 | "watch:css": "postcss src/assets/tailwind.css -o src/assets/main.css" 22 | }, 23 | "eslintConfig": { 24 | "extends": "react-app" 25 | }, 26 | "browserslist": { 27 | "production": [ 28 | ">0.2%", 29 | "not dead", 30 | "not op_mini all" 31 | ], 32 | "development": [ 33 | "last 1 chrome version", 34 | "last 1 firefox version", 35 | "last 1 safari version" 36 | ] 37 | }, 38 | "devDependencies": { 39 | "autoprefixer": "^9.7.6", 40 | "postcss-cli": "^7.1.1", 41 | "tailwindcss": "^1.4.6" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /.cache/caches/gatsby-transformer-sharp/diskstore-66c1da6000f7fd2228748e1552fc342e.json: -------------------------------------------------------------------------------- 1 | {"expireTime":9007200844311005000,"key":"b3a515ff-c444-5fb3-b233-d963bda7871e{\"duotone\":false,\"grayscale\":false,\"rotate\":0,\"trim\":false,\"toFormat\":\"png\",\"toFormatBase64\":\"\",\"cropFocus\":17,\"fit\":\"cover\",\"width\":20,\"height\":20}","val":{"src":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAAsSAAALEgHS3X78AAACYklEQVQ4y42Uy28SQRjA+dM8efDmwYN6qF6qiSY+Y/WgQRMibY00TaWNBSRSCraYQtHl/bR0KyxQWCgWWAqU8izl/Sq7rLNsRHlVJpvJtzPfb77nDIOcZHSoqZSrp4+KtXIziubaLRysMCZiCYqOoVnhjNEi8RcztdxxeTzc6VBfT+5O2Vhpb+vw4wMdZ0ppWvP9xzLeJoDNThf2W+Nz1+XzNxQubSToSKKW+BDc+WOnkshhSVgeCiGpViZMEg1oxc26Knt+ae3bEtJTZwzE1kXLccG0+sOOlrcvZXvsczPkITfsa20vwIKnhsh+BnjUarT74Gb13CY7KBVJMv3z4N1NszQYsMWM62HNrCis/GxXn0iYls23uz5LPBcv0bH8hUH2XRoM85ySXv7JBtO87jMIvWq+H5GoYIHCLA1ZxD6Qap3Ak8IKfW7TJ50lK6uP9E6RgndHaODtCJ6Z5RyHfnE7j6gRbcKlCYNSt+rtETHTpUGgEP8FYmdNqd/Mo7aiVWTfuH2L9xASvfxxlqr01EYkrJszvNkgW9bH0OuFr+99m+y9IOeyU6zIp/Hubp/yMEztlzFPwOhdvq+nIoS1JNn4t2sugCmVsDvPe2KKolnZLCxhOcAKQRDDXTQaVi46lqYhIBwHTrl3oWqhMRDtaJge37lOBMKo4tfbqhVX0J7snTsWps8uZWuoOQY6CcjpSIF55UvmqNgr5wUwtV1IVdnXtnSfPEB2qjDNqnvczRl0m+j6Jn5lXb6nAQJqinmN0ZEBj03YLzghY8PnTRz80o/GRJZpOLCb0PM9BN7pvUEjx28V00WUg9jIVwAAAABJRU5ErkJggg==","width":20,"height":20,"aspectRatio":1,"originalName":"gatsby-astronaut.png"}} -------------------------------------------------------------------------------- /.cache/page-renderer.js: -------------------------------------------------------------------------------- 1 | import React, { createElement } from "react" 2 | import PropTypes from "prop-types" 3 | import { publicLoader } from "./loader" 4 | import { apiRunner } from "./api-runner-browser" 5 | 6 | // Renders page 7 | class PageRenderer extends React.Component { 8 | render() { 9 | const props = { 10 | ...this.props, 11 | pathContext: this.props.pageContext, 12 | } 13 | 14 | const [replacementElement] = apiRunner(`replaceComponentRenderer`, { 15 | props: this.props, 16 | loader: publicLoader, 17 | }) 18 | 19 | const pageElement = 20 | replacementElement || 21 | createElement(this.props.pageResources.component, { 22 | ...props, 23 | key: this.props.path || this.props.pageResources.page.path, 24 | }) 25 | 26 | const wrappedPage = apiRunner( 27 | `wrapPageElement`, 28 | { element: pageElement, props }, 29 | pageElement, 30 | ({ result }) => { 31 | return { element: result, props } 32 | } 33 | ).pop() 34 | 35 | return wrappedPage 36 | } 37 | } 38 | 39 | PageRenderer.propTypes = { 40 | location: PropTypes.object.isRequired, 41 | pageResources: PropTypes.object.isRequired, 42 | data: PropTypes.object, 43 | pageContext: PropTypes.object.isRequired, 44 | } 45 | 46 | export default PageRenderer 47 | -------------------------------------------------------------------------------- /.cache/commonjs/api-runner-ssr.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // During bootstrap, we write requires at top of this file which looks like: 4 | // var plugins = [ 5 | // { 6 | // plugin: require("/path/to/plugin1/gatsby-ssr.js"), 7 | // options: { ... }, 8 | // }, 9 | // { 10 | // plugin: require("/path/to/plugin2/gatsby-ssr.js"), 11 | // options: { ... }, 12 | // }, 13 | // ] 14 | const apis = require(`./api-ssr-docs`); // Run the specified API in any plugins that have implemented it 15 | 16 | 17 | module.exports = (api, args, defaultReturn, argTransform) => { 18 | if (!apis[api]) { 19 | console.log(`This API doesn't exist`, api); 20 | } // Run each plugin in series. 21 | // eslint-disable-next-line no-undef 22 | 23 | 24 | let results = plugins.map(plugin => { 25 | if (!plugin.plugin[api]) { 26 | return undefined; 27 | } 28 | 29 | const result = plugin.plugin[api](args, plugin.options); 30 | 31 | if (result && argTransform) { 32 | args = argTransform({ 33 | args, 34 | result 35 | }); 36 | } 37 | 38 | return result; 39 | }); // Filter out undefined results. 40 | 41 | results = results.filter(result => typeof result !== `undefined`); 42 | 43 | if (results.length > 0) { 44 | return results; 45 | } else { 46 | return [defaultReturn]; 47 | } 48 | }; -------------------------------------------------------------------------------- /.cache/dev-loader.js: -------------------------------------------------------------------------------- 1 | import { BaseLoader, PageResourceStatus } from "./loader" 2 | import { findPath } from "./find-path" 3 | 4 | class DevLoader extends BaseLoader { 5 | constructor(syncRequires, matchPaths) { 6 | const loadComponent = chunkName => 7 | Promise.resolve(syncRequires.components[chunkName]) 8 | super(loadComponent, matchPaths) 9 | } 10 | 11 | loadPage(pagePath) { 12 | const realPath = findPath(pagePath) 13 | return super.loadPage(realPath).then(result => 14 | require(`./socketIo`) 15 | .getPageData(realPath) 16 | .then(() => result) 17 | ) 18 | } 19 | 20 | loadPageDataJson(rawPath) { 21 | return super.loadPageDataJson(rawPath).then(data => { 22 | // when we can't find a proper 404.html we fallback to dev-404-page 23 | // we need to make sure to mark it as not found. 24 | if ( 25 | data.status === PageResourceStatus.Error && 26 | rawPath !== `/dev-404-page/` 27 | ) { 28 | console.error( 29 | `404 page could not be found. Checkout https://www.gatsbyjs.org/docs/add-404-page/` 30 | ) 31 | return this.loadPageDataJson(`/dev-404-page/`).then(result => 32 | Object.assign({}, data, result) 33 | ) 34 | } 35 | 36 | return data 37 | }) 38 | } 39 | 40 | doPrefetch(pagePath) { 41 | return Promise.resolve(require(`./socketIo`).getPageData(pagePath)) 42 | } 43 | } 44 | 45 | export default DevLoader 46 | -------------------------------------------------------------------------------- /.cache/commonjs/dev-loader.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | exports.__esModule = true; 4 | exports.default = void 0; 5 | 6 | var _loader = require("./loader"); 7 | 8 | var _findPath = require("./find-path"); 9 | 10 | class DevLoader extends _loader.BaseLoader { 11 | constructor(syncRequires, matchPaths) { 12 | const loadComponent = chunkName => Promise.resolve(syncRequires.components[chunkName]); 13 | 14 | super(loadComponent, matchPaths); 15 | } 16 | 17 | loadPage(pagePath) { 18 | const realPath = (0, _findPath.findPath)(pagePath); 19 | return super.loadPage(realPath).then(result => require(`./socketIo`).getPageData(realPath).then(() => result)); 20 | } 21 | 22 | loadPageDataJson(rawPath) { 23 | return super.loadPageDataJson(rawPath).then(data => { 24 | // when we can't find a proper 404.html we fallback to dev-404-page 25 | // we need to make sure to mark it as not found. 26 | if (data.status === _loader.PageResourceStatus.Error && rawPath !== `/dev-404-page/`) { 27 | console.error(`404 page could not be found. Checkout https://www.gatsbyjs.org/docs/add-404-page/`); 28 | return this.loadPageDataJson(`/dev-404-page/`).then(result => Object.assign({}, data, result)); 29 | } 30 | 31 | return data; 32 | }); 33 | } 34 | 35 | doPrefetch(pagePath) { 36 | return Promise.resolve(require(`./socketIo`).getPageData(pagePath)); 37 | } 38 | 39 | } 40 | 41 | var _default = DevLoader; 42 | exports.default = _default; -------------------------------------------------------------------------------- /.cache/commonjs/default-html.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 | 5 | exports.__esModule = true; 6 | exports.default = HTML; 7 | 8 | var _react = _interopRequireDefault(require("react")); 9 | 10 | var _propTypes = _interopRequireDefault(require("prop-types")); 11 | 12 | function HTML(props) { 13 | return (/*#__PURE__*/_react.default.createElement("html", props.htmlAttributes, /*#__PURE__*/_react.default.createElement("head", null, /*#__PURE__*/_react.default.createElement("meta", { 14 | charSet: "utf-8" 15 | }), /*#__PURE__*/_react.default.createElement("meta", { 16 | httpEquiv: "x-ua-compatible", 17 | content: "ie=edge" 18 | }), /*#__PURE__*/_react.default.createElement("meta", { 19 | name: "viewport", 20 | content: "width=device-width, initial-scale=1, shrink-to-fit=no" 21 | }), props.headComponents), /*#__PURE__*/_react.default.createElement("body", props.bodyAttributes, props.preBodyComponents, /*#__PURE__*/_react.default.createElement("div", { 22 | key: `body`, 23 | id: "___gatsby", 24 | dangerouslySetInnerHTML: { 25 | __html: props.body 26 | } 27 | }), props.postBodyComponents)) 28 | ); 29 | } 30 | 31 | HTML.propTypes = { 32 | htmlAttributes: _propTypes.default.object, 33 | headComponents: _propTypes.default.array, 34 | bodyAttributes: _propTypes.default.object, 35 | preBodyComponents: _propTypes.default.array, 36 | body: _propTypes.default.string, 37 | postBodyComponents: _propTypes.default.array 38 | }; -------------------------------------------------------------------------------- /.cache/commonjs/page-renderer.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 | 5 | var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); 6 | 7 | exports.__esModule = true; 8 | exports.default = void 0; 9 | 10 | var _react = _interopRequireWildcard(require("react")); 11 | 12 | var _propTypes = _interopRequireDefault(require("prop-types")); 13 | 14 | var _loader = require("./loader"); 15 | 16 | var _apiRunnerBrowser = require("./api-runner-browser"); 17 | 18 | // Renders page 19 | class PageRenderer extends _react.default.Component { 20 | render() { 21 | const props = { ...this.props, 22 | pathContext: this.props.pageContext 23 | }; 24 | const [replacementElement] = (0, _apiRunnerBrowser.apiRunner)(`replaceComponentRenderer`, { 25 | props: this.props, 26 | loader: _loader.publicLoader 27 | }); 28 | const pageElement = replacementElement || (0, _react.createElement)(this.props.pageResources.component, { ...props, 29 | key: this.props.path || this.props.pageResources.page.path 30 | }); 31 | const wrappedPage = (0, _apiRunnerBrowser.apiRunner)(`wrapPageElement`, { 32 | element: pageElement, 33 | props 34 | }, pageElement, ({ 35 | result 36 | }) => { 37 | return { 38 | element: result, 39 | props 40 | }; 41 | }).pop(); 42 | return wrappedPage; 43 | } 44 | 45 | } 46 | 47 | PageRenderer.propTypes = { 48 | location: _propTypes.default.object.isRequired, 49 | pageResources: _propTypes.default.object.isRequired, 50 | data: _propTypes.default.object, 51 | pageContext: _propTypes.default.object.isRequired 52 | }; 53 | var _default = PageRenderer; 54 | exports.default = _default; -------------------------------------------------------------------------------- /.cache/api-runner-ssr.js: -------------------------------------------------------------------------------- 1 | var plugins = [{ 2 | plugin: require('/Users/hofheins/Desktop/Stevens Things/zorg/react-tailwind-starter-plate/node_modules/gatsby-plugin-react-helmet/gatsby-ssr'), 3 | options: {"plugins":[]}, 4 | },{ 5 | plugin: require('/Users/hofheins/Desktop/Stevens Things/zorg/react-tailwind-starter-plate/node_modules/gatsby-plugin-manifest/gatsby-ssr'), 6 | options: {"plugins":[],"name":"gatsby-starter-default","short_name":"starter","start_url":"/","background_color":"#663399","theme_color":"#663399","display":"minimal-ui","icon":"src/images/gatsby-icon.png"}, 7 | }] 8 | // During bootstrap, we write requires at top of this file which looks like: 9 | // var plugins = [ 10 | // { 11 | // plugin: require("/path/to/plugin1/gatsby-ssr.js"), 12 | // options: { ... }, 13 | // }, 14 | // { 15 | // plugin: require("/path/to/plugin2/gatsby-ssr.js"), 16 | // options: { ... }, 17 | // }, 18 | // ] 19 | 20 | const apis = require(`./api-ssr-docs`) 21 | 22 | // Run the specified API in any plugins that have implemented it 23 | module.exports = (api, args, defaultReturn, argTransform) => { 24 | if (!apis[api]) { 25 | console.log(`This API doesn't exist`, api) 26 | } 27 | 28 | // Run each plugin in series. 29 | // eslint-disable-next-line no-undef 30 | let results = plugins.map(plugin => { 31 | if (!plugin.plugin[api]) { 32 | return undefined 33 | } 34 | const result = plugin.plugin[api](args, plugin.options) 35 | if (result && argTransform) { 36 | args = argTransform({ args, result }) 37 | } 38 | return result 39 | }) 40 | 41 | // Filter out undefined results. 42 | results = results.filter(result => typeof result !== `undefined`) 43 | 44 | if (results.length > 0) { 45 | return results 46 | } else { 47 | return [defaultReturn] 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /.cache/__tests__/error-overlay-handler.js: -------------------------------------------------------------------------------- 1 | const { 2 | reportError, 3 | clearError, 4 | errorMap, 5 | } = require(`../error-overlay-handler`) 6 | 7 | import * as ErrorOverlay from "react-error-overlay" 8 | 9 | jest.mock(`react-error-overlay`, () => { 10 | return { 11 | reportBuildError: jest.fn(), 12 | dismissBuildError: jest.fn(), 13 | startReportingRuntimeErrors: jest.fn(), 14 | setEditorHandler: jest.fn(), 15 | } 16 | }) 17 | 18 | beforeEach(() => { 19 | ErrorOverlay.reportBuildError.mockClear() 20 | ErrorOverlay.dismissBuildError.mockClear() 21 | }) 22 | 23 | describe(`errorOverlayHandler`, () => { 24 | describe(`clearError()`, () => { 25 | beforeEach(() => { 26 | reportError(`foo`, `error`) 27 | reportError(`bar`, `error`) 28 | }) 29 | afterAll(() => { 30 | clearError(`foo`) 31 | clearError(`bar`) 32 | }) 33 | it(`should clear specific error type`, () => { 34 | expect(Object.keys(errorMap)).toHaveLength(2) 35 | clearError(`foo`) 36 | expect(Object.keys(errorMap)).toHaveLength(1) 37 | expect(ErrorOverlay.dismissBuildError).not.toHaveBeenCalled() 38 | }) 39 | 40 | it(`should call ErrorOverlay to dismiss build errors`, () => { 41 | clearError(`foo`) 42 | clearError(`bar`) 43 | expect(ErrorOverlay.dismissBuildError).toHaveBeenCalled() 44 | }) 45 | }) 46 | describe(`reportErrorOverlay()`, () => { 47 | it(`should not add error if it's empty and not call ErrorOverlay`, () => { 48 | reportError(`foo`, null) 49 | expect(Object.keys(errorMap)).toHaveLength(0) 50 | expect(ErrorOverlay.reportBuildError).not.toHaveBeenCalled() 51 | }) 52 | it(`should add error if it has a truthy value and call ErrorOverlay`, () => { 53 | reportError(`foo`, `bar`) 54 | expect(Object.keys(errorMap)).toHaveLength(1) 55 | expect(ErrorOverlay.reportBuildError).toHaveBeenCalled() 56 | }) 57 | }) 58 | }) 59 | -------------------------------------------------------------------------------- /.cache/api-runner-browser.js: -------------------------------------------------------------------------------- 1 | const plugins = require(`./api-runner-browser-plugins`) 2 | const { 3 | getResourcesForPathname, 4 | getResourcesForPathnameSync, 5 | getResourceURLsForPathname, 6 | loadPage, 7 | loadPageSync, 8 | } = require(`./loader`).publicLoader 9 | 10 | exports.apiRunner = (api, args = {}, defaultReturn, argTransform) => { 11 | // Hooks for gatsby-cypress's API handler 12 | if (process.env.CYPRESS_SUPPORT) { 13 | if (window.___apiHandler) { 14 | window.___apiHandler(api) 15 | } else if (window.___resolvedAPIs) { 16 | window.___resolvedAPIs.push(api) 17 | } else { 18 | window.___resolvedAPIs = [api] 19 | } 20 | } 21 | 22 | let results = plugins.map(plugin => { 23 | if (!plugin.plugin[api]) { 24 | return undefined 25 | } 26 | 27 | // Deprecated April 2019. Use `loadPageSync` instead 28 | args.getResourcesForPathnameSync = getResourcesForPathnameSync 29 | // Deprecated April 2019. Use `loadPage` instead 30 | args.getResourcesForPathname = getResourcesForPathname 31 | args.getResourceURLsForPathname = getResourceURLsForPathname 32 | args.loadPage = loadPage 33 | args.loadPageSync = loadPageSync 34 | 35 | const result = plugin.plugin[api](args, plugin.options) 36 | if (result && argTransform) { 37 | args = argTransform({ args, result, plugin }) 38 | } 39 | return result 40 | }) 41 | 42 | // Filter out undefined results. 43 | results = results.filter(result => typeof result !== `undefined`) 44 | 45 | if (results.length > 0) { 46 | return results 47 | } else if (defaultReturn) { 48 | return [defaultReturn] 49 | } else { 50 | return [] 51 | } 52 | } 53 | 54 | exports.apiRunnerAsync = (api, args, defaultReturn) => 55 | plugins.reduce( 56 | (previous, next) => 57 | next.plugin[api] 58 | ? previous.then(() => next.plugin[api](args, next.options)) 59 | : previous, 60 | Promise.resolve() 61 | ) 62 | -------------------------------------------------------------------------------- /.cache/commonjs/api-runner-browser.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const plugins = require(`./api-runner-browser-plugins`); 4 | 5 | const { 6 | getResourcesForPathname, 7 | getResourcesForPathnameSync, 8 | getResourceURLsForPathname, 9 | loadPage, 10 | loadPageSync 11 | } = require(`./loader`).publicLoader; 12 | 13 | exports.apiRunner = (api, args = {}, defaultReturn, argTransform) => { 14 | // Hooks for gatsby-cypress's API handler 15 | if (process.env.CYPRESS_SUPPORT) { 16 | if (window.___apiHandler) { 17 | window.___apiHandler(api); 18 | } else if (window.___resolvedAPIs) { 19 | window.___resolvedAPIs.push(api); 20 | } else { 21 | window.___resolvedAPIs = [api]; 22 | } 23 | } 24 | 25 | let results = plugins.map(plugin => { 26 | if (!plugin.plugin[api]) { 27 | return undefined; 28 | } // Deprecated April 2019. Use `loadPageSync` instead 29 | 30 | 31 | args.getResourcesForPathnameSync = getResourcesForPathnameSync; // Deprecated April 2019. Use `loadPage` instead 32 | 33 | args.getResourcesForPathname = getResourcesForPathname; 34 | args.getResourceURLsForPathname = getResourceURLsForPathname; 35 | args.loadPage = loadPage; 36 | args.loadPageSync = loadPageSync; 37 | const result = plugin.plugin[api](args, plugin.options); 38 | 39 | if (result && argTransform) { 40 | args = argTransform({ 41 | args, 42 | result, 43 | plugin 44 | }); 45 | } 46 | 47 | return result; 48 | }); // Filter out undefined results. 49 | 50 | results = results.filter(result => typeof result !== `undefined`); 51 | 52 | if (results.length > 0) { 53 | return results; 54 | } else if (defaultReturn) { 55 | return [defaultReturn]; 56 | } else { 57 | return []; 58 | } 59 | }; 60 | 61 | exports.apiRunnerAsync = (api, args, defaultReturn) => plugins.reduce((previous, next) => next.plugin[api] ? previous.then(() => next.plugin[api](args, next.options)) : previous, Promise.resolve()); -------------------------------------------------------------------------------- /.cache/prefetch.js: -------------------------------------------------------------------------------- 1 | const support = function (feature) { 2 | if (typeof document === `undefined`) { 3 | return false 4 | } 5 | const fakeLink = document.createElement(`link`) 6 | try { 7 | if (fakeLink.relList && typeof fakeLink.relList.supports === `function`) { 8 | return fakeLink.relList.supports(feature) 9 | } 10 | } catch (err) { 11 | return false 12 | } 13 | return false 14 | } 15 | 16 | const linkPrefetchStrategy = function (url, options) { 17 | return new Promise((resolve, reject) => { 18 | if (typeof document === `undefined`) { 19 | reject() 20 | return 21 | } 22 | 23 | const link = document.createElement(`link`) 24 | link.setAttribute(`rel`, `prefetch`) 25 | link.setAttribute(`href`, url) 26 | 27 | Object.keys(options).forEach(key => { 28 | link.setAttribute(key, options[key]) 29 | }) 30 | 31 | link.onload = resolve 32 | link.onerror = reject 33 | 34 | const parentElement = 35 | document.getElementsByTagName(`head`)[0] || 36 | document.getElementsByName(`script`)[0].parentNode 37 | parentElement.appendChild(link) 38 | }) 39 | } 40 | 41 | const xhrPrefetchStrategy = function (url) { 42 | return new Promise((resolve, reject) => { 43 | const req = new XMLHttpRequest() 44 | req.open(`GET`, url, true) 45 | 46 | req.onload = () => { 47 | if (req.status === 200) { 48 | resolve() 49 | } else { 50 | reject() 51 | } 52 | } 53 | 54 | req.send(null) 55 | }) 56 | } 57 | 58 | const supportedPrefetchStrategy = support(`prefetch`) 59 | ? linkPrefetchStrategy 60 | : xhrPrefetchStrategy 61 | 62 | const preFetched = {} 63 | 64 | const prefetch = function (url, options) { 65 | return new Promise(resolve => { 66 | if (preFetched[url]) { 67 | resolve() 68 | return 69 | } 70 | 71 | supportedPrefetchStrategy(url, options) 72 | .then(() => { 73 | resolve() 74 | preFetched[url] = true 75 | }) 76 | .catch(() => {}) // 404s are logged to the console anyway 77 | }) 78 | } 79 | 80 | export default prefetch 81 | -------------------------------------------------------------------------------- /.cache/commonjs/prefetch.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | exports.__esModule = true; 4 | exports.default = void 0; 5 | 6 | const support = function (feature) { 7 | if (typeof document === `undefined`) { 8 | return false; 9 | } 10 | 11 | const fakeLink = document.createElement(`link`); 12 | 13 | try { 14 | if (fakeLink.relList && typeof fakeLink.relList.supports === `function`) { 15 | return fakeLink.relList.supports(feature); 16 | } 17 | } catch (err) { 18 | return false; 19 | } 20 | 21 | return false; 22 | }; 23 | 24 | const linkPrefetchStrategy = function (url, options) { 25 | return new Promise((resolve, reject) => { 26 | if (typeof document === `undefined`) { 27 | reject(); 28 | return; 29 | } 30 | 31 | const link = document.createElement(`link`); 32 | link.setAttribute(`rel`, `prefetch`); 33 | link.setAttribute(`href`, url); 34 | Object.keys(options).forEach(key => { 35 | link.setAttribute(key, options[key]); 36 | }); 37 | link.onload = resolve; 38 | link.onerror = reject; 39 | const parentElement = document.getElementsByTagName(`head`)[0] || document.getElementsByName(`script`)[0].parentNode; 40 | parentElement.appendChild(link); 41 | }); 42 | }; 43 | 44 | const xhrPrefetchStrategy = function (url) { 45 | return new Promise((resolve, reject) => { 46 | const req = new XMLHttpRequest(); 47 | req.open(`GET`, url, true); 48 | 49 | req.onload = () => { 50 | if (req.status === 200) { 51 | resolve(); 52 | } else { 53 | reject(); 54 | } 55 | }; 56 | 57 | req.send(null); 58 | }); 59 | }; 60 | 61 | const supportedPrefetchStrategy = support(`prefetch`) ? linkPrefetchStrategy : xhrPrefetchStrategy; 62 | const preFetched = {}; 63 | 64 | const prefetch = function (url, options) { 65 | return new Promise(resolve => { 66 | if (preFetched[url]) { 67 | resolve(); 68 | return; 69 | } 70 | 71 | supportedPrefetchStrategy(url, options).then(() => { 72 | resolve(); 73 | preFetched[url] = true; 74 | }).catch(() => {}); // 404s are logged to the console anyway 75 | }); 76 | }; 77 | 78 | var _default = prefetch; 79 | exports.default = _default; -------------------------------------------------------------------------------- /.cache/app.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import ReactDOM from "react-dom" 3 | import domReady from "@mikaelkristiansson/domready" 4 | 5 | import socketIo from "./socketIo" 6 | import emitter from "./emitter" 7 | import { apiRunner, apiRunnerAsync } from "./api-runner-browser" 8 | import { setLoader, publicLoader } from "./loader" 9 | import DevLoader from "./dev-loader" 10 | import syncRequires from "./sync-requires" 11 | // Generated during bootstrap 12 | import matchPaths from "./match-paths.json" 13 | 14 | window.___emitter = emitter 15 | 16 | const loader = new DevLoader(syncRequires, matchPaths) 17 | setLoader(loader) 18 | loader.setApiRunner(apiRunner) 19 | 20 | window.___loader = publicLoader 21 | 22 | // Let the site/plugins run code very early. 23 | apiRunnerAsync(`onClientEntry`).then(() => { 24 | // Hook up the client to socket.io on server 25 | const socket = socketIo() 26 | if (socket) { 27 | socket.on(`reload`, () => { 28 | window.location.reload() 29 | }) 30 | } 31 | 32 | /** 33 | * Service Workers are persistent by nature. They stick around, 34 | * serving a cached version of the site if they aren't removed. 35 | * This is especially frustrating when you need to test the 36 | * production build on your local machine. 37 | * 38 | * Let's warn if we find service workers in development. 39 | */ 40 | if (`serviceWorker` in navigator) { 41 | navigator.serviceWorker.getRegistrations().then(registrations => { 42 | if (registrations.length > 0) 43 | console.warn( 44 | `Warning: found one or more service workers present.`, 45 | `If your site isn't behaving as expected, you might want to remove these.`, 46 | registrations 47 | ) 48 | }) 49 | } 50 | 51 | const rootElement = document.getElementById(`___gatsby`) 52 | 53 | const renderer = apiRunner( 54 | `replaceHydrateFunction`, 55 | undefined, 56 | ReactDOM.render 57 | )[0] 58 | 59 | Promise.all([ 60 | loader.loadPage(`/dev-404-page/`), 61 | loader.loadPage(`/404.html`), 62 | loader.loadPage(window.location.pathname), 63 | ]).then(() => { 64 | const preferDefault = m => (m && m.default) || m 65 | let Root = preferDefault(require(`./root`)) 66 | domReady(() => { 67 | renderer(, rootElement, () => { 68 | apiRunner(`onInitialClientRender`) 69 | }) 70 | }) 71 | }) 72 | }) 73 | -------------------------------------------------------------------------------- /.cache/error-overlay-handler.js: -------------------------------------------------------------------------------- 1 | import * as ReactRefreshErrorOverlay from "@pmmmwh/react-refresh-webpack-plugin/src/overlay" 2 | import * as ReactErrorOverlay from "react-error-overlay" 3 | 4 | const ErrorOverlay = { 5 | showCompileError: 6 | process.env.GATSBY_HOT_LOADER !== `fast-refresh` 7 | ? ReactErrorOverlay.reportBuildError 8 | : ReactRefreshErrorOverlay.showCompileError, 9 | clearCompileError: 10 | process.env.GATSBY_HOT_LOADER !== `fast-refresh` 11 | ? ReactErrorOverlay.dismissBuildError 12 | : ReactRefreshErrorOverlay.clearCompileError, 13 | } 14 | 15 | if (process.env.GATSBY_HOT_LOADER !== `fast-refresh`) { 16 | // Report runtime errors 17 | ReactErrorOverlay.startReportingRuntimeErrors({ 18 | onError: () => {}, 19 | filename: `/commons.js`, 20 | }) 21 | ReactErrorOverlay.setEditorHandler(errorLocation => 22 | window.fetch( 23 | `/__open-stack-frame-in-editor?fileName=` + 24 | window.encodeURIComponent(errorLocation.fileName) + 25 | `&lineNumber=` + 26 | window.encodeURIComponent(errorLocation.lineNumber || 1) 27 | ) 28 | ) 29 | } 30 | 31 | const errorMap = {} 32 | 33 | function flat(arr) { 34 | return Array.prototype.flat ? arr.flat() : [].concat(...arr) 35 | } 36 | 37 | const handleErrorOverlay = () => { 38 | const errors = Object.values(errorMap) 39 | let errorStringsToDisplay = [] 40 | if (errors.length > 0) { 41 | errorStringsToDisplay = flat(errors) 42 | .map(error => { 43 | if (typeof error === `string`) { 44 | return error 45 | } else if (typeof error === `object`) { 46 | const errorStrBuilder = [error.text] 47 | 48 | if (error.filePath) { 49 | errorStrBuilder.push(`File: ${error.filePath}`) 50 | } 51 | 52 | return errorStrBuilder.join(`\n\n`) 53 | } 54 | 55 | return null 56 | }) 57 | .filter(Boolean) 58 | } 59 | 60 | if (errorStringsToDisplay.length > 0) { 61 | ErrorOverlay.showCompileError(errorStringsToDisplay.join(`\n\n`)) 62 | } else { 63 | ErrorOverlay.clearCompileError() 64 | } 65 | } 66 | 67 | export const clearError = errorID => { 68 | delete errorMap[errorID] 69 | handleErrorOverlay() 70 | } 71 | 72 | export const reportError = (errorID, error) => { 73 | if (error) { 74 | errorMap[errorID] = error 75 | } 76 | handleErrorOverlay() 77 | } 78 | 79 | export { errorMap } 80 | -------------------------------------------------------------------------------- /.cache/commonjs/error-overlay-handler.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); 4 | 5 | exports.__esModule = true; 6 | exports.errorMap = exports.reportError = exports.clearError = void 0; 7 | 8 | var ReactRefreshErrorOverlay = _interopRequireWildcard(require("@pmmmwh/react-refresh-webpack-plugin/src/overlay")); 9 | 10 | var ReactErrorOverlay = _interopRequireWildcard(require("react-error-overlay")); 11 | 12 | const ErrorOverlay = { 13 | showCompileError: process.env.GATSBY_HOT_LOADER !== `fast-refresh` ? ReactErrorOverlay.reportBuildError : ReactRefreshErrorOverlay.showCompileError, 14 | clearCompileError: process.env.GATSBY_HOT_LOADER !== `fast-refresh` ? ReactErrorOverlay.dismissBuildError : ReactRefreshErrorOverlay.clearCompileError 15 | }; 16 | 17 | if (process.env.GATSBY_HOT_LOADER !== `fast-refresh`) { 18 | // Report runtime errors 19 | ReactErrorOverlay.startReportingRuntimeErrors({ 20 | onError: () => {}, 21 | filename: `/commons.js` 22 | }); 23 | ReactErrorOverlay.setEditorHandler(errorLocation => window.fetch(`/__open-stack-frame-in-editor?fileName=` + window.encodeURIComponent(errorLocation.fileName) + `&lineNumber=` + window.encodeURIComponent(errorLocation.lineNumber || 1))); 24 | } 25 | 26 | const errorMap = {}; 27 | exports.errorMap = errorMap; 28 | 29 | function flat(arr) { 30 | return Array.prototype.flat ? arr.flat() : [].concat(...arr); 31 | } 32 | 33 | const handleErrorOverlay = () => { 34 | const errors = Object.values(errorMap); 35 | let errorStringsToDisplay = []; 36 | 37 | if (errors.length > 0) { 38 | errorStringsToDisplay = flat(errors).map(error => { 39 | if (typeof error === `string`) { 40 | return error; 41 | } else if (typeof error === `object`) { 42 | const errorStrBuilder = [error.text]; 43 | 44 | if (error.filePath) { 45 | errorStrBuilder.push(`File: ${error.filePath}`); 46 | } 47 | 48 | return errorStrBuilder.join(`\n\n`); 49 | } 50 | 51 | return null; 52 | }).filter(Boolean); 53 | } 54 | 55 | if (errorStringsToDisplay.length > 0) { 56 | ErrorOverlay.showCompileError(errorStringsToDisplay.join(`\n\n`)); 57 | } else { 58 | ErrorOverlay.clearCompileError(); 59 | } 60 | }; 61 | 62 | const clearError = errorID => { 63 | delete errorMap[errorID]; 64 | handleErrorOverlay(); 65 | }; 66 | 67 | exports.clearError = clearError; 68 | 69 | const reportError = (errorID, error) => { 70 | if (error) { 71 | errorMap[errorID] = error; 72 | } 73 | 74 | handleErrorOverlay(); 75 | }; 76 | 77 | exports.reportError = reportError; -------------------------------------------------------------------------------- /.cache/find-path.js: -------------------------------------------------------------------------------- 1 | import { match } from "@reach/router/lib/utils" 2 | import stripPrefix from "./strip-prefix" 3 | import normalizePagePath from "./normalize-page-path" 4 | 5 | const pathCache = new Map() 6 | let matchPaths = [] 7 | 8 | const trimPathname = rawPathname => { 9 | const pathname = decodeURIComponent(rawPathname) 10 | // Remove the pathPrefix from the pathname. 11 | const trimmedPathname = stripPrefix(pathname, __BASE_PATH__) 12 | // Remove any hashfragment 13 | .split(`#`)[0] 14 | // Remove search query 15 | .split(`?`)[0] 16 | 17 | return trimmedPathname 18 | } 19 | 20 | /** 21 | * Set list of matchPaths 22 | * 23 | * @param {Array<{path: string, matchPath: string}>} value collection of matchPaths 24 | */ 25 | export const setMatchPaths = value => { 26 | matchPaths = value 27 | } 28 | 29 | /** 30 | * Return a matchpath url 31 | * if `match-paths.json` contains `{ "/foo*": "/page1", ...}`, then 32 | * `/foo?bar=far` => `/page1` 33 | * 34 | * @param {string} rawPathname A raw pathname 35 | * @return {string|null} 36 | */ 37 | export const findMatchPath = rawPathname => { 38 | const trimmedPathname = cleanPath(rawPathname) 39 | 40 | for (const { matchPath, path } of matchPaths) { 41 | if (match(matchPath, trimmedPathname)) { 42 | return normalizePagePath(path) 43 | } 44 | } 45 | 46 | return null 47 | } 48 | 49 | // Given a raw URL path, returns the cleaned version of it (trim off 50 | // `#` and query params), or if it matches an entry in 51 | // `match-paths.json`, its matched path is returned 52 | // 53 | // E.g. `/foo?bar=far` => `/foo` 54 | // 55 | // Or if `match-paths.json` contains `{ "/foo*": "/page1", ...}`, then 56 | // `/foo?bar=far` => `/page1` 57 | export const findPath = rawPathname => { 58 | const trimmedPathname = trimPathname(rawPathname) 59 | 60 | if (pathCache.has(trimmedPathname)) { 61 | return pathCache.get(trimmedPathname) 62 | } 63 | 64 | let foundPath = findMatchPath(trimmedPathname) 65 | 66 | if (!foundPath) { 67 | foundPath = cleanPath(rawPathname) 68 | } 69 | 70 | pathCache.set(trimmedPathname, foundPath) 71 | 72 | return foundPath 73 | } 74 | 75 | /** 76 | * Clean a url and converts /index.html => / 77 | * E.g. `/foo?bar=far` => `/foo` 78 | * 79 | * @param {string} rawPathname A raw pathname 80 | * @return {string} 81 | */ 82 | export const cleanPath = rawPathname => { 83 | const trimmedPathname = trimPathname(rawPathname) 84 | 85 | let foundPath = trimmedPathname 86 | if (foundPath === `/index.html`) { 87 | foundPath = `/` 88 | } 89 | 90 | foundPath = normalizePagePath(foundPath) 91 | 92 | return foundPath 93 | } 94 | -------------------------------------------------------------------------------- /.cache/commonjs/app.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 | 5 | var _react = _interopRequireDefault(require("react")); 6 | 7 | var _reactDom = _interopRequireDefault(require("react-dom")); 8 | 9 | var _domready = _interopRequireDefault(require("@mikaelkristiansson/domready")); 10 | 11 | var _socketIo = _interopRequireDefault(require("./socketIo")); 12 | 13 | var _emitter = _interopRequireDefault(require("./emitter")); 14 | 15 | var _apiRunnerBrowser = require("./api-runner-browser"); 16 | 17 | var _loader = require("./loader"); 18 | 19 | var _devLoader = _interopRequireDefault(require("./dev-loader")); 20 | 21 | var _syncRequires = _interopRequireDefault(require("./sync-requires")); 22 | 23 | var _matchPaths = _interopRequireDefault(require("./match-paths.json")); 24 | 25 | // Generated during bootstrap 26 | window.___emitter = _emitter.default; 27 | const loader = new _devLoader.default(_syncRequires.default, _matchPaths.default); 28 | (0, _loader.setLoader)(loader); 29 | loader.setApiRunner(_apiRunnerBrowser.apiRunner); 30 | window.___loader = _loader.publicLoader; // Let the site/plugins run code very early. 31 | 32 | (0, _apiRunnerBrowser.apiRunnerAsync)(`onClientEntry`).then(() => { 33 | // Hook up the client to socket.io on server 34 | const socket = (0, _socketIo.default)(); 35 | 36 | if (socket) { 37 | socket.on(`reload`, () => { 38 | window.location.reload(); 39 | }); 40 | } 41 | /** 42 | * Service Workers are persistent by nature. They stick around, 43 | * serving a cached version of the site if they aren't removed. 44 | * This is especially frustrating when you need to test the 45 | * production build on your local machine. 46 | * 47 | * Let's warn if we find service workers in development. 48 | */ 49 | 50 | 51 | if (`serviceWorker` in navigator) { 52 | navigator.serviceWorker.getRegistrations().then(registrations => { 53 | if (registrations.length > 0) console.warn(`Warning: found one or more service workers present.`, `If your site isn't behaving as expected, you might want to remove these.`, registrations); 54 | }); 55 | } 56 | 57 | const rootElement = document.getElementById(`___gatsby`); 58 | const renderer = (0, _apiRunnerBrowser.apiRunner)(`replaceHydrateFunction`, undefined, _reactDom.default.render)[0]; 59 | Promise.all([loader.loadPage(`/dev-404-page/`), loader.loadPage(`/404.html`), loader.loadPage(window.location.pathname)]).then(() => { 60 | const preferDefault = m => m && m.default || m; 61 | 62 | let Root = preferDefault(require(`./root`)); 63 | (0, _domready.default)(() => { 64 | renderer( /*#__PURE__*/_react.default.createElement(Root, null), rootElement, () => { 65 | (0, _apiRunnerBrowser.apiRunner)(`onInitialClientRender`); 66 | }); 67 | }); 68 | }); 69 | }); -------------------------------------------------------------------------------- /src/pages/sections/HomeMainSection.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Link } from "react-router-dom"; 3 | 4 | export default function HomeMainSection() { 5 | return ( 6 |
7 |
8 |
9 |
10 |
11 | 12 |
13 |
14 | 15 |
16 |
17 |
18 | 19 |
20 |
21 |

22 | Boiler Plate 23 |
24 | for react and tailwind. 25 |

26 |

27 | Anim aute id magna aliqua ad ad non deserunt sunt. Qui irure qui 28 | lorem cupidatat commodo. Elit sunt amet fugiat veniam occaecat 29 | fugiat aliqua. 30 |

31 |
32 |
33 | 36 | Get started 37 | 38 |
39 |
40 | 43 | View Demo 44 | 45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | ); 53 | } 54 | -------------------------------------------------------------------------------- /.cache/ensure-resources.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import loader, { PageResourceStatus } from "./loader" 3 | import shallowCompare from "shallow-compare" 4 | 5 | class EnsureResources extends React.Component { 6 | constructor(props) { 7 | super() 8 | const { location, pageResources } = props 9 | this.state = { 10 | location: { ...location }, 11 | pageResources: pageResources || loader.loadPageSync(location.pathname), 12 | } 13 | } 14 | 15 | static getDerivedStateFromProps({ location }, prevState) { 16 | if (prevState.location.href !== location.href) { 17 | const pageResources = loader.loadPageSync(location.pathname) 18 | return { 19 | pageResources, 20 | location: { ...location }, 21 | } 22 | } 23 | 24 | return { 25 | location: { ...location }, 26 | } 27 | } 28 | 29 | loadResources(rawPath) { 30 | loader.loadPage(rawPath).then(pageResources => { 31 | if (pageResources && pageResources.status !== PageResourceStatus.Error) { 32 | this.setState({ 33 | location: { ...window.location }, 34 | pageResources, 35 | }) 36 | } else { 37 | window.history.replaceState({}, ``, location.href) 38 | window.location = rawPath 39 | } 40 | }) 41 | } 42 | 43 | shouldComponentUpdate(nextProps, nextState) { 44 | // Always return false if we're missing resources. 45 | if (!nextState.pageResources) { 46 | this.loadResources(nextProps.location.pathname) 47 | return false 48 | } 49 | 50 | // Check if the component or json have changed. 51 | if (this.state.pageResources !== nextState.pageResources) { 52 | return true 53 | } 54 | if ( 55 | this.state.pageResources.component !== nextState.pageResources.component 56 | ) { 57 | return true 58 | } 59 | 60 | if (this.state.pageResources.json !== nextState.pageResources.json) { 61 | return true 62 | } 63 | // Check if location has changed on a page using internal routing 64 | // via matchPath configuration. 65 | if ( 66 | this.state.location.key !== nextState.location.key && 67 | nextState.pageResources.page && 68 | (nextState.pageResources.page.matchPath || 69 | nextState.pageResources.page.path) 70 | ) { 71 | return true 72 | } 73 | return shallowCompare(this, nextProps, nextState) 74 | } 75 | 76 | render() { 77 | if (process.env.NODE_ENV !== `production` && !this.state.pageResources) { 78 | throw new Error( 79 | `EnsureResources was not able to find resources for path: "${this.props.location.pathname}" 80 | This typically means that an issue occurred building components for that path. 81 | Run \`gatsby clean\` to remove any cached elements.` 82 | ) 83 | } 84 | 85 | return this.props.children(this.state) 86 | } 87 | } 88 | 89 | export default EnsureResources 90 | -------------------------------------------------------------------------------- /.cache/register-service-worker.js: -------------------------------------------------------------------------------- 1 | import { apiRunner } from "./api-runner-browser" 2 | 3 | if ( 4 | window.location.protocol !== `https:` && 5 | window.location.hostname !== `localhost` 6 | ) { 7 | console.error( 8 | `Service workers can only be used over HTTPS, or on localhost for development` 9 | ) 10 | } else if (`serviceWorker` in navigator) { 11 | navigator.serviceWorker 12 | .register(`${__BASE_PATH__}/sw.js`) 13 | .then(function (reg) { 14 | reg.addEventListener(`updatefound`, () => { 15 | apiRunner(`onServiceWorkerUpdateFound`, { serviceWorker: reg }) 16 | // The updatefound event implies that reg.installing is set; see 17 | // https://w3c.github.io/ServiceWorker/#service-worker-registration-updatefound-event 18 | const installingWorker = reg.installing 19 | console.log(`installingWorker`, installingWorker) 20 | installingWorker.addEventListener(`statechange`, () => { 21 | switch (installingWorker.state) { 22 | case `installed`: 23 | if (navigator.serviceWorker.controller) { 24 | // At this point, the old content will have been purged and the fresh content will 25 | // have been added to the cache. 26 | 27 | // We set a flag so Gatsby Link knows to refresh the page on next navigation attempt 28 | window.___swUpdated = true 29 | // We call the onServiceWorkerUpdateReady API so users can show update prompts. 30 | apiRunner(`onServiceWorkerUpdateReady`, { serviceWorker: reg }) 31 | 32 | // If resources failed for the current page, reload. 33 | if (window.___failedResources) { 34 | console.log(`resources failed, SW updated - reloading`) 35 | window.location.reload() 36 | } 37 | } else { 38 | // At this point, everything has been precached. 39 | // It's the perfect time to display a "Content is cached for offline use." message. 40 | console.log(`Content is now available offline!`) 41 | 42 | // Post to service worker that install is complete. 43 | // Delay to allow time for the event listener to be added -- 44 | // otherwise fetch is called too soon and resources aren't cached. 45 | apiRunner(`onServiceWorkerInstalled`, { serviceWorker: reg }) 46 | } 47 | break 48 | 49 | case `redundant`: 50 | console.error(`The installing service worker became redundant.`) 51 | apiRunner(`onServiceWorkerRedundant`, { serviceWorker: reg }) 52 | break 53 | 54 | case `activated`: 55 | apiRunner(`onServiceWorkerActive`, { serviceWorker: reg }) 56 | break 57 | } 58 | }) 59 | }) 60 | }) 61 | .catch(function (e) { 62 | console.error(`Error during service worker registration:`, e) 63 | }) 64 | } 65 | -------------------------------------------------------------------------------- /.cache/commonjs/register-service-worker.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _apiRunnerBrowser = require("./api-runner-browser"); 4 | 5 | if (window.location.protocol !== `https:` && window.location.hostname !== `localhost`) { 6 | console.error(`Service workers can only be used over HTTPS, or on localhost for development`); 7 | } else if (`serviceWorker` in navigator) { 8 | navigator.serviceWorker.register(`${__BASE_PATH__}/sw.js`).then(function (reg) { 9 | reg.addEventListener(`updatefound`, () => { 10 | (0, _apiRunnerBrowser.apiRunner)(`onServiceWorkerUpdateFound`, { 11 | serviceWorker: reg 12 | }); // The updatefound event implies that reg.installing is set; see 13 | // https://w3c.github.io/ServiceWorker/#service-worker-registration-updatefound-event 14 | 15 | const installingWorker = reg.installing; 16 | console.log(`installingWorker`, installingWorker); 17 | installingWorker.addEventListener(`statechange`, () => { 18 | switch (installingWorker.state) { 19 | case `installed`: 20 | if (navigator.serviceWorker.controller) { 21 | // At this point, the old content will have been purged and the fresh content will 22 | // have been added to the cache. 23 | // We set a flag so Gatsby Link knows to refresh the page on next navigation attempt 24 | window.___swUpdated = true; // We call the onServiceWorkerUpdateReady API so users can show update prompts. 25 | 26 | (0, _apiRunnerBrowser.apiRunner)(`onServiceWorkerUpdateReady`, { 27 | serviceWorker: reg 28 | }); // If resources failed for the current page, reload. 29 | 30 | if (window.___failedResources) { 31 | console.log(`resources failed, SW updated - reloading`); 32 | window.location.reload(); 33 | } 34 | } else { 35 | // At this point, everything has been precached. 36 | // It's the perfect time to display a "Content is cached for offline use." message. 37 | console.log(`Content is now available offline!`); // Post to service worker that install is complete. 38 | // Delay to allow time for the event listener to be added -- 39 | // otherwise fetch is called too soon and resources aren't cached. 40 | 41 | (0, _apiRunnerBrowser.apiRunner)(`onServiceWorkerInstalled`, { 42 | serviceWorker: reg 43 | }); 44 | } 45 | 46 | break; 47 | 48 | case `redundant`: 49 | console.error(`The installing service worker became redundant.`); 50 | (0, _apiRunnerBrowser.apiRunner)(`onServiceWorkerRedundant`, { 51 | serviceWorker: reg 52 | }); 53 | break; 54 | 55 | case `activated`: 56 | (0, _apiRunnerBrowser.apiRunner)(`onServiceWorkerActive`, { 57 | serviceWorker: reg 58 | }); 59 | break; 60 | } 61 | }); 62 | }); 63 | }).catch(function (e) { 64 | console.error(`Error during service worker registration:`, e); 65 | }); 66 | } -------------------------------------------------------------------------------- /.cache/__tests__/find-path.js: -------------------------------------------------------------------------------- 1 | import { cleanPath, setMatchPaths, findMatchPath, findPath } from "../find-path" 2 | 3 | describe(`find-path`, () => { 4 | describe(`cleanPath`, () => { 5 | beforeEach(() => { 6 | global.__BASE_PATH__ = `` 7 | }) 8 | 9 | it(`should strip out ? & # from a pathname`, () => { 10 | expect(cleanPath(`/mypath#anchor?gatsby=cool`)).toBe(`/mypath`) 11 | }) 12 | 13 | it(`should convert a /index.html to root dir`, () => { 14 | expect(cleanPath(`/index.html`)).toBe(`/`) 15 | }) 16 | 17 | it(`strip out a basePrefix`, () => { 18 | global.__BASE_PATH__ = `/blog` 19 | expect(cleanPath(`/blog/mypath`)).toBe(`/mypath`) 20 | }) 21 | }) 22 | 23 | describe(`findMatchPath`, () => { 24 | beforeEach(() => { 25 | // reset matchPaths 26 | setMatchPaths([]) 27 | global.__BASE_PATH__ = `` 28 | }) 29 | 30 | it(`should find a path when matchPath found`, () => { 31 | setMatchPaths([ 32 | { 33 | matchPath: `/app/*`, 34 | path: `/app`, 35 | }, 36 | ]) 37 | 38 | expect(findMatchPath(`/app/dynamic-page#anchor?gatsby=cool`)).toBe(`/app`) 39 | }) 40 | 41 | it(`should return null when no matchPathFound`, () => { 42 | setMatchPaths([ 43 | { 44 | matchPath: `/app/*`, 45 | path: `/app`, 46 | }, 47 | ]) 48 | 49 | expect(findMatchPath(`/notanapp/dynamic-page`)).toBeNull() 50 | }) 51 | }) 52 | 53 | describe(`findPath`, () => { 54 | beforeEach(() => { 55 | // reset matchPaths 56 | setMatchPaths([]) 57 | global.__BASE_PATH__ = `` 58 | }) 59 | 60 | it(`should use matchPath if found`, () => { 61 | setMatchPaths([ 62 | { 63 | matchPath: `/app/*`, 64 | path: `/app`, 65 | }, 66 | ]) 67 | 68 | expect(findPath(`/app/dynamic-page#anchor?gatsby=cool`)).toBe(`/app`) 69 | }) 70 | 71 | it(`should return the cleaned up path when no matchPathFound`, () => { 72 | setMatchPaths([ 73 | { 74 | matchPath: `/app/*`, 75 | path: `/app`, 76 | }, 77 | ]) 78 | 79 | expect(findPath(`/notanapp/my-page#anchor?gatsby=cool`)).toBe( 80 | `/notanapp/my-page` 81 | ) 82 | }) 83 | 84 | it(`should only process a request once`, () => { 85 | jest.resetModules() 86 | jest.mock(`@reach/router/lib/utils`) 87 | const findPath = require(`../find-path`).findPath 88 | const setMatchPaths = require(`../find-path`).setMatchPaths 89 | const match = require(`@reach/router/lib/utils`).match 90 | 91 | setMatchPaths([ 92 | { 93 | matchPath: `/app/*`, 94 | path: `/app`, 95 | }, 96 | ]) 97 | 98 | expect(findPath(`/notanapp/my-page#anchor?gatsby=cool`)).toBe( 99 | `/notanapp/my-page` 100 | ) 101 | expect(findPath(`/notanapp/my-page#anchor?gatsby=cool`)).toBe( 102 | `/notanapp/my-page` 103 | ) 104 | expect(findPath(`/notanapp/my-page`)).toBe(`/notanapp/my-page`) 105 | 106 | expect(match).toHaveBeenCalledTimes(1) 107 | }) 108 | }) 109 | }) 110 | -------------------------------------------------------------------------------- /.cache/commonjs/find-path.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 | 5 | exports.__esModule = true; 6 | exports.cleanPath = exports.findPath = exports.findMatchPath = exports.setMatchPaths = void 0; 7 | 8 | var _utils = require("@reach/router/lib/utils"); 9 | 10 | var _stripPrefix = _interopRequireDefault(require("./strip-prefix")); 11 | 12 | var _normalizePagePath = _interopRequireDefault(require("./normalize-page-path")); 13 | 14 | const pathCache = new Map(); 15 | let matchPaths = []; 16 | 17 | const trimPathname = rawPathname => { 18 | const pathname = decodeURIComponent(rawPathname); // Remove the pathPrefix from the pathname. 19 | 20 | const trimmedPathname = (0, _stripPrefix.default)(pathname, __BASE_PATH__) // Remove any hashfragment 21 | .split(`#`)[0] // Remove search query 22 | .split(`?`)[0]; 23 | return trimmedPathname; 24 | }; 25 | /** 26 | * Set list of matchPaths 27 | * 28 | * @param {Array<{path: string, matchPath: string}>} value collection of matchPaths 29 | */ 30 | 31 | 32 | const setMatchPaths = value => { 33 | matchPaths = value; 34 | }; 35 | /** 36 | * Return a matchpath url 37 | * if `match-paths.json` contains `{ "/foo*": "/page1", ...}`, then 38 | * `/foo?bar=far` => `/page1` 39 | * 40 | * @param {string} rawPathname A raw pathname 41 | * @return {string|null} 42 | */ 43 | 44 | 45 | exports.setMatchPaths = setMatchPaths; 46 | 47 | const findMatchPath = rawPathname => { 48 | const trimmedPathname = cleanPath(rawPathname); 49 | 50 | for (const { 51 | matchPath, 52 | path 53 | } of matchPaths) { 54 | if ((0, _utils.match)(matchPath, trimmedPathname)) { 55 | return (0, _normalizePagePath.default)(path); 56 | } 57 | } 58 | 59 | return null; 60 | }; // Given a raw URL path, returns the cleaned version of it (trim off 61 | // `#` and query params), or if it matches an entry in 62 | // `match-paths.json`, its matched path is returned 63 | // 64 | // E.g. `/foo?bar=far` => `/foo` 65 | // 66 | // Or if `match-paths.json` contains `{ "/foo*": "/page1", ...}`, then 67 | // `/foo?bar=far` => `/page1` 68 | 69 | 70 | exports.findMatchPath = findMatchPath; 71 | 72 | const findPath = rawPathname => { 73 | const trimmedPathname = trimPathname(rawPathname); 74 | 75 | if (pathCache.has(trimmedPathname)) { 76 | return pathCache.get(trimmedPathname); 77 | } 78 | 79 | let foundPath = findMatchPath(trimmedPathname); 80 | 81 | if (!foundPath) { 82 | foundPath = cleanPath(rawPathname); 83 | } 84 | 85 | pathCache.set(trimmedPathname, foundPath); 86 | return foundPath; 87 | }; 88 | /** 89 | * Clean a url and converts /index.html => / 90 | * E.g. `/foo?bar=far` => `/foo` 91 | * 92 | * @param {string} rawPathname A raw pathname 93 | * @return {string} 94 | */ 95 | 96 | 97 | exports.findPath = findPath; 98 | 99 | const cleanPath = rawPathname => { 100 | const trimmedPathname = trimPathname(rawPathname); 101 | let foundPath = trimmedPathname; 102 | 103 | if (foundPath === `/index.html`) { 104 | foundPath = `/`; 105 | } 106 | 107 | foundPath = (0, _normalizePagePath.default)(foundPath); 108 | return foundPath; 109 | }; 110 | 111 | exports.cleanPath = cleanPath; -------------------------------------------------------------------------------- /.cache/commonjs/ensure-resources.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); 4 | 5 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 6 | 7 | exports.__esModule = true; 8 | exports.default = void 0; 9 | 10 | var _react = _interopRequireDefault(require("react")); 11 | 12 | var _loader = _interopRequireWildcard(require("./loader")); 13 | 14 | var _shallowCompare = _interopRequireDefault(require("shallow-compare")); 15 | 16 | class EnsureResources extends _react.default.Component { 17 | constructor(props) { 18 | super(); 19 | const { 20 | location, 21 | pageResources 22 | } = props; 23 | this.state = { 24 | location: { ...location 25 | }, 26 | pageResources: pageResources || _loader.default.loadPageSync(location.pathname) 27 | }; 28 | } 29 | 30 | static getDerivedStateFromProps({ 31 | location 32 | }, prevState) { 33 | if (prevState.location.href !== location.href) { 34 | const pageResources = _loader.default.loadPageSync(location.pathname); 35 | 36 | return { 37 | pageResources, 38 | location: { ...location 39 | } 40 | }; 41 | } 42 | 43 | return { 44 | location: { ...location 45 | } 46 | }; 47 | } 48 | 49 | loadResources(rawPath) { 50 | _loader.default.loadPage(rawPath).then(pageResources => { 51 | if (pageResources && pageResources.status !== _loader.PageResourceStatus.Error) { 52 | this.setState({ 53 | location: { ...window.location 54 | }, 55 | pageResources 56 | }); 57 | } else { 58 | window.history.replaceState({}, ``, location.href); 59 | window.location = rawPath; 60 | } 61 | }); 62 | } 63 | 64 | shouldComponentUpdate(nextProps, nextState) { 65 | // Always return false if we're missing resources. 66 | if (!nextState.pageResources) { 67 | this.loadResources(nextProps.location.pathname); 68 | return false; 69 | } // Check if the component or json have changed. 70 | 71 | 72 | if (this.state.pageResources !== nextState.pageResources) { 73 | return true; 74 | } 75 | 76 | if (this.state.pageResources.component !== nextState.pageResources.component) { 77 | return true; 78 | } 79 | 80 | if (this.state.pageResources.json !== nextState.pageResources.json) { 81 | return true; 82 | } // Check if location has changed on a page using internal routing 83 | // via matchPath configuration. 84 | 85 | 86 | if (this.state.location.key !== nextState.location.key && nextState.pageResources.page && (nextState.pageResources.page.matchPath || nextState.pageResources.page.path)) { 87 | return true; 88 | } 89 | 90 | return (0, _shallowCompare.default)(this, nextProps, nextState); 91 | } 92 | 93 | render() { 94 | if (process.env.NODE_ENV !== `production` && !this.state.pageResources) { 95 | throw new Error(`EnsureResources was not able to find resources for path: "${this.props.location.pathname}" 96 | This typically means that an issue occurred building components for that path. 97 | Run \`gatsby clean\` to remove any cached elements.`); 98 | } 99 | 100 | return this.props.children(this.state); 101 | } 102 | 103 | } 104 | 105 | var _default = EnsureResources; 106 | exports.default = _default; -------------------------------------------------------------------------------- /.cache/gatsby-browser-entry.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | import Link, { 4 | withPrefix, 5 | withAssetPrefix, 6 | navigate, 7 | push, 8 | replace, 9 | navigateTo, 10 | parsePath, 11 | } from "gatsby-link" 12 | import PageRenderer from "./public-page-renderer" 13 | import loader from "./loader" 14 | 15 | const prefetchPathname = loader.enqueue 16 | 17 | const StaticQueryContext = React.createContext({}) 18 | 19 | function StaticQueryDataRenderer({ staticQueryData, data, query, render }) { 20 | const finalData = data 21 | ? data.data 22 | : staticQueryData[query] && staticQueryData[query].data 23 | 24 | return ( 25 | 26 | {finalData && render(finalData)} 27 | {!finalData &&
Loading (StaticQuery)
} 28 |
29 | ) 30 | } 31 | 32 | const StaticQuery = props => { 33 | const { data, query, render, children } = props 34 | 35 | return ( 36 | 37 | {staticQueryData => ( 38 | 44 | )} 45 | 46 | ) 47 | } 48 | 49 | const useStaticQuery = query => { 50 | if ( 51 | typeof React.useContext !== `function` && 52 | process.env.NODE_ENV === `development` 53 | ) { 54 | throw new Error( 55 | `You're likely using a version of React that doesn't support Hooks\n` + 56 | `Please update React and ReactDOM to 16.8.0 or later to use the useStaticQuery hook.` 57 | ) 58 | } 59 | const context = React.useContext(StaticQueryContext) 60 | 61 | // query is a stringified number like `3303882` when wrapped with graphql, If a user forgets 62 | // to wrap the query in a grqphql, then casting it to a Number results in `NaN` allowing us to 63 | // catch the misuse of the API and give proper direction 64 | if (isNaN(Number(query))) { 65 | throw new Error(`useStaticQuery was called with a string but expects to be called using \`graphql\`. Try this: 66 | 67 | import { useStaticQuery, graphql } from 'gatsby'; 68 | 69 | useStaticQuery(graphql\`${query}\`); 70 | `) 71 | } 72 | 73 | if (context[query] && context[query].data) { 74 | return context[query].data 75 | } else { 76 | throw new Error( 77 | `The result of this StaticQuery could not be fetched.\n\n` + 78 | `This is likely a bug in Gatsby and if refreshing the page does not fix it, ` + 79 | `please open an issue in https://github.com/gatsbyjs/gatsby/issues` 80 | ) 81 | } 82 | } 83 | 84 | StaticQuery.propTypes = { 85 | data: PropTypes.object, 86 | query: PropTypes.string.isRequired, 87 | render: PropTypes.func, 88 | children: PropTypes.func, 89 | } 90 | 91 | function graphql() { 92 | throw new Error( 93 | `It appears like Gatsby is misconfigured. Gatsby related \`graphql\` calls ` + 94 | `are supposed to only be evaluated at compile time, and then compiled away. ` + 95 | `Unfortunately, something went wrong and the query was left in the compiled code.\n\n` + 96 | `Unless your site has a complex or custom babel/Gatsby configuration this is likely a bug in Gatsby.` 97 | ) 98 | } 99 | 100 | export { 101 | Link, 102 | withAssetPrefix, 103 | withPrefix, 104 | graphql, 105 | parsePath, 106 | navigate, 107 | push, // TODO replace for v3 108 | replace, // TODO remove replace for v3 109 | navigateTo, // TODO: remove navigateTo for v3 110 | StaticQueryContext, 111 | StaticQuery, 112 | PageRenderer, 113 | useStaticQuery, 114 | prefetchPathname, 115 | } 116 | -------------------------------------------------------------------------------- /.cache/develop-static-entry.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { renderToStaticMarkup } from "react-dom/server" 3 | import { merge } from "lodash" 4 | import apiRunner from "./api-runner-ssr" 5 | // import testRequireError from "./test-require-error" 6 | // For some extremely mysterious reason, webpack adds the above module *after* 7 | // this module so that when this code runs, testRequireError is undefined. 8 | // So in the meantime, we'll just inline it. 9 | const testRequireError = (moduleName, err) => { 10 | const regex = new RegExp(`Error: Cannot find module\\s.${moduleName}`) 11 | const firstLine = err.toString().split(`\n`)[0] 12 | return regex.test(firstLine) 13 | } 14 | 15 | let Html 16 | try { 17 | Html = require(`../src/html`) 18 | } catch (err) { 19 | if (testRequireError(`../src/html`, err)) { 20 | Html = require(`./default-html`) 21 | } else { 22 | console.log(`There was an error requiring "src/html.js"\n\n`, err, `\n\n`) 23 | process.exit() 24 | } 25 | } 26 | 27 | Html = Html && Html.__esModule ? Html.default : Html 28 | 29 | export default (pagePath, callback) => { 30 | let headComponents = [ 31 | , 32 | ] 33 | let htmlAttributes = {} 34 | let bodyAttributes = {} 35 | let preBodyComponents = [] 36 | let postBodyComponents = [] 37 | let bodyProps = {} 38 | let htmlStr 39 | 40 | const setHeadComponents = components => { 41 | headComponents = headComponents.concat(components) 42 | } 43 | 44 | const setHtmlAttributes = attributes => { 45 | htmlAttributes = merge(htmlAttributes, attributes) 46 | } 47 | 48 | const setBodyAttributes = attributes => { 49 | bodyAttributes = merge(bodyAttributes, attributes) 50 | } 51 | 52 | const setPreBodyComponents = components => { 53 | preBodyComponents = preBodyComponents.concat(components) 54 | } 55 | 56 | const setPostBodyComponents = components => { 57 | postBodyComponents = postBodyComponents.concat(components) 58 | } 59 | 60 | const setBodyProps = props => { 61 | bodyProps = merge({}, bodyProps, props) 62 | } 63 | 64 | const getHeadComponents = () => headComponents 65 | 66 | const replaceHeadComponents = components => { 67 | headComponents = components 68 | } 69 | 70 | const getPreBodyComponents = () => preBodyComponents 71 | 72 | const replacePreBodyComponents = components => { 73 | preBodyComponents = components 74 | } 75 | 76 | const getPostBodyComponents = () => postBodyComponents 77 | 78 | const replacePostBodyComponents = components => { 79 | postBodyComponents = components 80 | } 81 | 82 | apiRunner(`onRenderBody`, { 83 | setHeadComponents, 84 | setHtmlAttributes, 85 | setBodyAttributes, 86 | setPreBodyComponents, 87 | setPostBodyComponents, 88 | setBodyProps, 89 | pathname: pagePath, 90 | }) 91 | 92 | apiRunner(`onPreRenderHTML`, { 93 | getHeadComponents, 94 | replaceHeadComponents, 95 | getPreBodyComponents, 96 | replacePreBodyComponents, 97 | getPostBodyComponents, 98 | replacePostBodyComponents, 99 | pathname: pagePath, 100 | }) 101 | 102 | const htmlElement = React.createElement(Html, { 103 | ...bodyProps, 104 | body: ``, 105 | headComponents: headComponents.concat([ 106 |
"`; 4 | 5 | exports[`develop-static-entry onPreRenderHTML can be used to replace postBodyComponents 1`] = `"
div3
div2
div1
"`; 6 | 7 | exports[`develop-static-entry onPreRenderHTML can be used to replace preBodyComponents 1`] = `"
div3
div2
div1
"`; 8 | 9 | exports[`static-entry onPreRenderHTML can be used to replace headComponents 1`] = `"
"`; 10 | 11 | exports[`static-entry onPreRenderHTML can be used to replace postBodyComponents 1`] = `"
div3
div2
div1
"`; 12 | 13 | exports[`static-entry onPreRenderHTML can be used to replace preBodyComponents 1`] = `"
div3
div2
div1
"`; 14 | -------------------------------------------------------------------------------- /.cache/commonjs/root.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 | 5 | exports.__esModule = true; 6 | exports.default = void 0; 7 | 8 | var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); 9 | 10 | var _react = _interopRequireDefault(require("react")); 11 | 12 | var _router = require("@reach/router"); 13 | 14 | var _gatsbyReactRouterScroll = require("gatsby-react-router-scroll"); 15 | 16 | var _navigation = require("./navigation"); 17 | 18 | var _apiRunnerBrowser = require("./api-runner-browser"); 19 | 20 | var _loader = _interopRequireDefault(require("./loader")); 21 | 22 | var _queryResultStore = require("./query-result-store"); 23 | 24 | var _ensureResources = _interopRequireDefault(require("./ensure-resources")); 25 | 26 | var _errorOverlayHandler = require("./error-overlay-handler"); 27 | 28 | // TODO: Remove entire block when we make fast-refresh the default 29 | // In fast-refresh, this logic is all moved into the `error-overlay-handler` 30 | if (window.__webpack_hot_middleware_reporter__ !== undefined && process.env.GATSBY_HOT_LOADER !== `fast-refresh`) { 31 | const overlayErrorID = `webpack`; // Report build errors 32 | 33 | window.__webpack_hot_middleware_reporter__.useCustomOverlay({ 34 | showProblems(type, obj) { 35 | if (type !== `errors`) { 36 | (0, _errorOverlayHandler.clearError)(overlayErrorID); 37 | return; 38 | } 39 | 40 | (0, _errorOverlayHandler.reportError)(overlayErrorID, obj[0]); 41 | }, 42 | 43 | clear() { 44 | (0, _errorOverlayHandler.clearError)(overlayErrorID); 45 | } 46 | 47 | }); 48 | } 49 | 50 | (0, _navigation.init)(); // In gatsby v2 if Router is used in page using matchPaths 51 | // paths need to contain full path. 52 | // For example: 53 | // - page have `/app/*` matchPath 54 | // - inside template user needs to use `/app/xyz` as path 55 | // Resetting `basepath`/`baseuri` keeps current behaviour 56 | // to not introduce breaking change. 57 | // Remove this in v3 58 | 59 | const RouteHandler = props => /*#__PURE__*/_react.default.createElement(_router.BaseContext.Provider, { 60 | value: { 61 | baseuri: `/`, 62 | basepath: `/` 63 | } 64 | }, /*#__PURE__*/_react.default.createElement(_queryResultStore.PageQueryStore, props)); 65 | 66 | class LocationHandler extends _react.default.Component { 67 | render() { 68 | const { 69 | location 70 | } = this.props; 71 | 72 | if (!_loader.default.isPageNotFound(location.pathname)) { 73 | return (/*#__PURE__*/_react.default.createElement(_ensureResources.default, { 74 | location: location 75 | }, locationAndPageResources => /*#__PURE__*/_react.default.createElement(_navigation.RouteUpdates, { 76 | location: location 77 | }, /*#__PURE__*/_react.default.createElement(_gatsbyReactRouterScroll.ScrollContext, { 78 | location: location, 79 | shouldUpdateScroll: _navigation.shouldUpdateScroll 80 | }, /*#__PURE__*/_react.default.createElement(_router.Router, { 81 | basepath: __BASE_PATH__, 82 | location: location, 83 | id: "gatsby-focus-wrapper" 84 | }, /*#__PURE__*/_react.default.createElement(RouteHandler, (0, _extends2.default)({ 85 | path: encodeURI(locationAndPageResources.pageResources.page.matchPath || locationAndPageResources.pageResources.page.path) 86 | }, this.props, locationAndPageResources)))))) 87 | ); 88 | } 89 | 90 | const dev404PageResources = _loader.default.loadPageSync(`/dev-404-page`); 91 | 92 | const real404PageResources = _loader.default.loadPageSync(`/404.html`); 93 | 94 | let custom404; 95 | 96 | if (real404PageResources) { 97 | custom404 = /*#__PURE__*/_react.default.createElement(_queryResultStore.PageQueryStore, (0, _extends2.default)({}, this.props, { 98 | pageResources: real404PageResources 99 | })); 100 | } 101 | 102 | return (/*#__PURE__*/_react.default.createElement(_navigation.RouteUpdates, { 103 | location: location 104 | }, /*#__PURE__*/_react.default.createElement(_router.Router, { 105 | basepath: __BASE_PATH__, 106 | location: location, 107 | id: "gatsby-focus-wrapper" 108 | }, /*#__PURE__*/_react.default.createElement(RouteHandler, { 109 | path: location.pathname, 110 | location: location, 111 | pageResources: dev404PageResources, 112 | custom404: custom404 113 | }))) 114 | ); 115 | } 116 | 117 | } 118 | 119 | const Root = () => /*#__PURE__*/_react.default.createElement(_router.Location, null, locationContext => /*#__PURE__*/_react.default.createElement(LocationHandler, locationContext)); // Let site, plugins wrap the site e.g. for Redux. 120 | 121 | 122 | const WrappedRoot = (0, _apiRunnerBrowser.apiRunner)(`wrapRootElement`, { 123 | element: /*#__PURE__*/_react.default.createElement(Root, null) 124 | }, /*#__PURE__*/_react.default.createElement(Root, null), ({ 125 | result, 126 | plugin 127 | }) => { 128 | return { 129 | element: result 130 | }; 131 | }).pop(); 132 | 133 | var _default = () => /*#__PURE__*/_react.default.createElement(_queryResultStore.StaticQueryStore, null, WrappedRoot); 134 | 135 | exports.default = _default; -------------------------------------------------------------------------------- /src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read https://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.0/8 are considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | if (installingWorker == null) { 64 | return; 65 | } 66 | installingWorker.onstatechange = () => { 67 | if (installingWorker.state === 'installed') { 68 | if (navigator.serviceWorker.controller) { 69 | // At this point, the updated precached content has been fetched, 70 | // but the previous service worker will still serve the older 71 | // content until all client tabs are closed. 72 | console.log( 73 | 'New content is available and will be used when all ' + 74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 75 | ); 76 | 77 | // Execute callback 78 | if (config && config.onUpdate) { 79 | config.onUpdate(registration); 80 | } 81 | } else { 82 | // At this point, everything has been precached. 83 | // It's the perfect time to display a 84 | // "Content is cached for offline use." message. 85 | console.log('Content is cached for offline use.'); 86 | 87 | // Execute callback 88 | if (config && config.onSuccess) { 89 | config.onSuccess(registration); 90 | } 91 | } 92 | } 93 | }; 94 | }; 95 | }) 96 | .catch(error => { 97 | console.error('Error during service worker registration:', error); 98 | }); 99 | } 100 | 101 | function checkValidServiceWorker(swUrl, config) { 102 | // Check if the service worker can be found. If it can't reload the page. 103 | fetch(swUrl, { 104 | headers: { 'Service-Worker': 'script' }, 105 | }) 106 | .then(response => { 107 | // Ensure service worker exists, and that we really are getting a JS file. 108 | const contentType = response.headers.get('content-type'); 109 | if ( 110 | response.status === 404 || 111 | (contentType != null && contentType.indexOf('javascript') === -1) 112 | ) { 113 | // No service worker found. Probably a different app. Reload the page. 114 | navigator.serviceWorker.ready.then(registration => { 115 | registration.unregister().then(() => { 116 | window.location.reload(); 117 | }); 118 | }); 119 | } else { 120 | // Service worker found. Proceed as normal. 121 | registerValidSW(swUrl, config); 122 | } 123 | }) 124 | .catch(() => { 125 | console.log( 126 | 'No internet connection found. App is running in offline mode.' 127 | ); 128 | }); 129 | } 130 | 131 | export function unregister() { 132 | if ('serviceWorker' in navigator) { 133 | navigator.serviceWorker.ready 134 | .then(registration => { 135 | registration.unregister(); 136 | }) 137 | .catch(error => { 138 | console.error(error.message); 139 | }); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /.cache/production-app.js: -------------------------------------------------------------------------------- 1 | import { apiRunner, apiRunnerAsync } from "./api-runner-browser" 2 | import React from "react" 3 | import ReactDOM from "react-dom" 4 | import { Router, navigate, Location, BaseContext } from "@reach/router" 5 | import { ScrollContext } from "gatsby-react-router-scroll" 6 | import domReady from "@mikaelkristiansson/domready" 7 | import { 8 | shouldUpdateScroll, 9 | init as navigationInit, 10 | RouteUpdates, 11 | } from "./navigation" 12 | import emitter from "./emitter" 13 | import PageRenderer from "./page-renderer" 14 | import asyncRequires from "./async-requires" 15 | import { 16 | setLoader, 17 | ProdLoader, 18 | publicLoader, 19 | PageResourceStatus, 20 | } from "./loader" 21 | import EnsureResources from "./ensure-resources" 22 | import stripPrefix from "./strip-prefix" 23 | 24 | // Generated during bootstrap 25 | import matchPaths from "./match-paths.json" 26 | 27 | const loader = new ProdLoader(asyncRequires, matchPaths) 28 | setLoader(loader) 29 | loader.setApiRunner(apiRunner) 30 | 31 | window.asyncRequires = asyncRequires 32 | window.___emitter = emitter 33 | window.___loader = publicLoader 34 | 35 | navigationInit() 36 | 37 | apiRunnerAsync(`onClientEntry`).then(() => { 38 | // Let plugins register a service worker. The plugin just needs 39 | // to return true. 40 | if (apiRunner(`registerServiceWorker`).length > 0) { 41 | require(`./register-service-worker`) 42 | } 43 | 44 | // In gatsby v2 if Router is used in page using matchPaths 45 | // paths need to contain full path. 46 | // For example: 47 | // - page have `/app/*` matchPath 48 | // - inside template user needs to use `/app/xyz` as path 49 | // Resetting `basepath`/`baseuri` keeps current behaviour 50 | // to not introduce breaking change. 51 | // Remove this in v3 52 | const RouteHandler = props => ( 53 | 59 | 60 | 61 | ) 62 | 63 | class LocationHandler extends React.Component { 64 | render() { 65 | const { location } = this.props 66 | return ( 67 | 68 | {({ pageResources, location }) => ( 69 | 70 | 74 | 79 | 93 | 94 | 95 | 96 | )} 97 | 98 | ) 99 | } 100 | } 101 | 102 | const { pagePath, location: browserLoc } = window 103 | 104 | // Explicitly call navigate if the canonical path (window.pagePath) 105 | // is different to the browser path (window.location.pathname). But 106 | // only if NONE of the following conditions hold: 107 | // 108 | // - The url matches a client side route (page.matchPath) 109 | // - it's a 404 page 110 | // - it's the offline plugin shell (/offline-plugin-app-shell-fallback/) 111 | if ( 112 | pagePath && 113 | __BASE_PATH__ + pagePath !== browserLoc.pathname && 114 | !( 115 | loader.findMatchPath(stripPrefix(browserLoc.pathname, __BASE_PATH__)) || 116 | pagePath === `/404.html` || 117 | pagePath.match(/^\/404\/?$/) || 118 | pagePath.match(/^\/offline-plugin-app-shell-fallback\/?$/) 119 | ) 120 | ) { 121 | navigate(__BASE_PATH__ + pagePath + browserLoc.search + browserLoc.hash, { 122 | replace: true, 123 | }) 124 | } 125 | 126 | publicLoader.loadPage(browserLoc.pathname).then(page => { 127 | if (!page || page.status === PageResourceStatus.Error) { 128 | throw new Error( 129 | `page resources for ${browserLoc.pathname} not found. Not rendering React` 130 | ) 131 | } 132 | 133 | window.___webpackCompilationHash = page.page.webpackCompilationHash 134 | 135 | const Root = () => ( 136 | 137 | {locationContext => } 138 | 139 | ) 140 | 141 | const WrappedRoot = apiRunner( 142 | `wrapRootElement`, 143 | { element: }, 144 | , 145 | ({ result }) => { 146 | return { element: result } 147 | } 148 | ).pop() 149 | 150 | const NewRoot = () => WrappedRoot 151 | 152 | const renderer = apiRunner( 153 | `replaceHydrateFunction`, 154 | undefined, 155 | ReactDOM.hydrate 156 | )[0] 157 | 158 | domReady(() => { 159 | renderer( 160 | , 161 | typeof window !== `undefined` 162 | ? document.getElementById(`___gatsby`) 163 | : void 0, 164 | () => { 165 | apiRunner(`onInitialClientRender`) 166 | } 167 | ) 168 | }) 169 | }) 170 | }) 171 | -------------------------------------------------------------------------------- /.cache/dev-404-page.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | import { graphql, Link, navigate } from "gatsby" 4 | import queryString from "query-string" 5 | 6 | class Dev404Page extends React.Component { 7 | static propTypes = { 8 | data: PropTypes.object, 9 | custom404: PropTypes.element, 10 | location: PropTypes.object, 11 | } 12 | 13 | constructor(props) { 14 | super(props) 15 | const { data, location } = this.props 16 | const pagePaths = data.allSitePage.nodes.map(node => node.path) 17 | const urlState = queryString.parse(location.search) 18 | 19 | const initialPagePathSearchTerms = urlState.filter ? urlState.filter : `` 20 | 21 | this.state = { 22 | showCustom404: false, 23 | initPagePaths: pagePaths, 24 | pagePathSearchTerms: initialPagePathSearchTerms, 25 | pagePaths: this.getFilteredPagePaths( 26 | pagePaths, 27 | initialPagePathSearchTerms 28 | ), 29 | } 30 | this.showCustom404 = this.showCustom404.bind(this) 31 | this.handlePagePathSearch = this.handlePagePathSearch.bind(this) 32 | this.handleSearchTermChange = this.handleSearchTermChange.bind(this) 33 | } 34 | 35 | showCustom404() { 36 | this.setState({ showCustom404: true }) 37 | } 38 | 39 | handleSearchTermChange(event) { 40 | const searchValue = event.target.value 41 | 42 | this.setSearchUrl(searchValue) 43 | 44 | this.setState({ 45 | pagePathSearchTerms: searchValue, 46 | }) 47 | } 48 | 49 | handlePagePathSearch(event) { 50 | event.preventDefault() 51 | const allPagePaths = [...this.state.initPagePaths] 52 | this.setState({ 53 | pagePaths: this.getFilteredPagePaths( 54 | allPagePaths, 55 | this.state.pagePathSearchTerms 56 | ), 57 | }) 58 | } 59 | 60 | getFilteredPagePaths(allPagePaths, pagePathSearchTerms) { 61 | const searchTerm = new RegExp(`${pagePathSearchTerms}`) 62 | return allPagePaths.filter(pagePath => searchTerm.test(pagePath)) 63 | } 64 | 65 | setSearchUrl(searchValue) { 66 | const { 67 | location: { pathname, search }, 68 | } = this.props 69 | 70 | const searchMap = queryString.parse(search) 71 | searchMap.filter = searchValue 72 | 73 | const newSearch = queryString.stringify(searchMap) 74 | 75 | if (search !== `?${newSearch}`) { 76 | navigate(`${pathname}?${newSearch}`, { replace: true }) 77 | } 78 | } 79 | 80 | render() { 81 | const { pathname } = this.props.location 82 | let newFilePath 83 | if (pathname === `/`) { 84 | newFilePath = `src/pages/index.js` 85 | } else if (pathname.slice(-1) === `/`) { 86 | newFilePath = `src/pages${pathname.slice(0, -1)}.js` 87 | } else { 88 | newFilePath = `src/pages${pathname}.js` 89 | } 90 | 91 | return this.state.showCustom404 ? ( 92 | this.props.custom404 93 | ) : ( 94 |
95 |

Gatsby.js development 404 page

96 |

97 | {`There's not a page yet at `} 98 | {pathname} 99 |

100 | {this.props.custom404 ? ( 101 |

102 | 105 |

106 | ) : ( 107 |

108 | {`A custom 404 page wasn't detected - if you would like to add one, create a component in your site directory at `} 109 | src/pages/404.js. 110 |

111 | )} 112 |

113 | Create a React.js component in your site directory at 114 | {` `} 115 | {newFilePath} 116 | {` `} 117 | and this page will automatically refresh to show the new page 118 | component you created. 119 |

120 | {this.state.initPagePaths.length > 0 && ( 121 |
122 |

123 | If you were trying to reach another page, perhaps you can find it 124 | below. 125 |

126 |

127 | Pages ( 128 | {this.state.pagePaths.length != this.state.initPagePaths.length 129 | ? `${this.state.pagePaths.length}/${this.state.initPagePaths.length}` 130 | : this.state.initPagePaths.length} 131 | ) 132 |

133 | 134 |
135 | 145 | 146 |
147 |
    148 | {this.state.pagePaths.map( 149 | (pagePath, index) => 150 | index < 100 && ( 151 |
  • 152 | {pagePath} 153 |
  • 154 | ) 155 | )} 156 | {this.state.pagePaths.length > 100 && ( 157 |

    158 | ... and {this.state.pagePaths.length - 100} more. 159 |

    160 | )} 161 |
162 |
163 | )} 164 |
165 | ) 166 | } 167 | } 168 | 169 | export default Dev404Page 170 | 171 | export const pagesQuery = graphql` 172 | query PagesQuery { 173 | allSitePage(filter: { path: { ne: "/dev-404-page/" } }) { 174 | nodes { 175 | path 176 | } 177 | } 178 | } 179 | ` 180 | -------------------------------------------------------------------------------- /.cache/commonjs/production-app.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 | 5 | var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); 6 | 7 | var _apiRunnerBrowser = require("./api-runner-browser"); 8 | 9 | var _react = _interopRequireDefault(require("react")); 10 | 11 | var _reactDom = _interopRequireDefault(require("react-dom")); 12 | 13 | var _router = require("@reach/router"); 14 | 15 | var _gatsbyReactRouterScroll = require("gatsby-react-router-scroll"); 16 | 17 | var _domready = _interopRequireDefault(require("@mikaelkristiansson/domready")); 18 | 19 | var _navigation = require("./navigation"); 20 | 21 | var _emitter = _interopRequireDefault(require("./emitter")); 22 | 23 | var _pageRenderer = _interopRequireDefault(require("./page-renderer")); 24 | 25 | var _asyncRequires = _interopRequireDefault(require("./async-requires")); 26 | 27 | var _loader = require("./loader"); 28 | 29 | var _ensureResources = _interopRequireDefault(require("./ensure-resources")); 30 | 31 | var _stripPrefix = _interopRequireDefault(require("./strip-prefix")); 32 | 33 | var _matchPaths = _interopRequireDefault(require("./match-paths.json")); 34 | 35 | // Generated during bootstrap 36 | const loader = new _loader.ProdLoader(_asyncRequires.default, _matchPaths.default); 37 | (0, _loader.setLoader)(loader); 38 | loader.setApiRunner(_apiRunnerBrowser.apiRunner); 39 | window.asyncRequires = _asyncRequires.default; 40 | window.___emitter = _emitter.default; 41 | window.___loader = _loader.publicLoader; 42 | (0, _navigation.init)(); 43 | (0, _apiRunnerBrowser.apiRunnerAsync)(`onClientEntry`).then(() => { 44 | // Let plugins register a service worker. The plugin just needs 45 | // to return true. 46 | if ((0, _apiRunnerBrowser.apiRunner)(`registerServiceWorker`).length > 0) { 47 | require(`./register-service-worker`); 48 | } // In gatsby v2 if Router is used in page using matchPaths 49 | // paths need to contain full path. 50 | // For example: 51 | // - page have `/app/*` matchPath 52 | // - inside template user needs to use `/app/xyz` as path 53 | // Resetting `basepath`/`baseuri` keeps current behaviour 54 | // to not introduce breaking change. 55 | // Remove this in v3 56 | 57 | 58 | const RouteHandler = props => /*#__PURE__*/_react.default.createElement(_router.BaseContext.Provider, { 59 | value: { 60 | baseuri: `/`, 61 | basepath: `/` 62 | } 63 | }, /*#__PURE__*/_react.default.createElement(_pageRenderer.default, props)); 64 | 65 | class LocationHandler extends _react.default.Component { 66 | render() { 67 | const { 68 | location 69 | } = this.props; 70 | return (/*#__PURE__*/_react.default.createElement(_ensureResources.default, { 71 | location: location 72 | }, ({ 73 | pageResources, 74 | location 75 | }) => /*#__PURE__*/_react.default.createElement(_navigation.RouteUpdates, { 76 | location: location 77 | }, /*#__PURE__*/_react.default.createElement(_gatsbyReactRouterScroll.ScrollContext, { 78 | location: location, 79 | shouldUpdateScroll: _navigation.shouldUpdateScroll 80 | }, /*#__PURE__*/_react.default.createElement(_router.Router, { 81 | basepath: __BASE_PATH__, 82 | location: location, 83 | id: "gatsby-focus-wrapper" 84 | }, /*#__PURE__*/_react.default.createElement(RouteHandler, (0, _extends2.default)({ 85 | path: pageResources.page.path === `/404.html` ? (0, _stripPrefix.default)(location.pathname, __BASE_PATH__) : encodeURI(pageResources.page.matchPath || pageResources.page.path) 86 | }, this.props, { 87 | location: location, 88 | pageResources: pageResources 89 | }, pageResources.json)))))) 90 | ); 91 | } 92 | 93 | } 94 | 95 | const { 96 | pagePath, 97 | location: browserLoc 98 | } = window; // Explicitly call navigate if the canonical path (window.pagePath) 99 | // is different to the browser path (window.location.pathname). But 100 | // only if NONE of the following conditions hold: 101 | // 102 | // - The url matches a client side route (page.matchPath) 103 | // - it's a 404 page 104 | // - it's the offline plugin shell (/offline-plugin-app-shell-fallback/) 105 | 106 | if (pagePath && __BASE_PATH__ + pagePath !== browserLoc.pathname && !(loader.findMatchPath((0, _stripPrefix.default)(browserLoc.pathname, __BASE_PATH__)) || pagePath === `/404.html` || pagePath.match(/^\/404\/?$/) || pagePath.match(/^\/offline-plugin-app-shell-fallback\/?$/))) { 107 | (0, _router.navigate)(__BASE_PATH__ + pagePath + browserLoc.search + browserLoc.hash, { 108 | replace: true 109 | }); 110 | } 111 | 112 | _loader.publicLoader.loadPage(browserLoc.pathname).then(page => { 113 | if (!page || page.status === _loader.PageResourceStatus.Error) { 114 | throw new Error(`page resources for ${browserLoc.pathname} not found. Not rendering React`); 115 | } 116 | 117 | window.___webpackCompilationHash = page.page.webpackCompilationHash; 118 | 119 | const Root = () => /*#__PURE__*/_react.default.createElement(_router.Location, null, locationContext => /*#__PURE__*/_react.default.createElement(LocationHandler, locationContext)); 120 | 121 | const WrappedRoot = (0, _apiRunnerBrowser.apiRunner)(`wrapRootElement`, { 122 | element: /*#__PURE__*/_react.default.createElement(Root, null) 123 | }, /*#__PURE__*/_react.default.createElement(Root, null), ({ 124 | result 125 | }) => { 126 | return { 127 | element: result 128 | }; 129 | }).pop(); 130 | 131 | const NewRoot = () => WrappedRoot; 132 | 133 | const renderer = (0, _apiRunnerBrowser.apiRunner)(`replaceHydrateFunction`, undefined, _reactDom.default.hydrate)[0]; 134 | (0, _domready.default)(() => { 135 | renderer( /*#__PURE__*/_react.default.createElement(NewRoot, null), typeof window !== `undefined` ? document.getElementById(`___gatsby`) : void 0, () => { 136 | (0, _apiRunnerBrowser.apiRunner)(`onInitialClientRender`); 137 | }); 138 | }); 139 | }); 140 | }); -------------------------------------------------------------------------------- /.cache/navigation.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | import loader, { PageResourceStatus } from "./loader" 4 | import redirects from "./redirects.json" 5 | import { apiRunner } from "./api-runner-browser" 6 | import emitter from "./emitter" 7 | import { RouteAnnouncerProps } from "./route-announcer-props" 8 | import { navigate as reachNavigate } from "@reach/router" 9 | import { globalHistory } from "@reach/router/lib/history" 10 | import { parsePath } from "gatsby-link" 11 | 12 | // Convert to a map for faster lookup in maybeRedirect() 13 | const redirectMap = redirects.reduce((map, redirect) => { 14 | map[redirect.fromPath] = redirect 15 | return map 16 | }, {}) 17 | 18 | function maybeRedirect(pathname) { 19 | const redirect = redirectMap[pathname] 20 | 21 | if (redirect != null) { 22 | if (process.env.NODE_ENV !== `production`) { 23 | if (!loader.isPageNotFound(pathname)) { 24 | console.error( 25 | `The route "${pathname}" matches both a page and a redirect; this is probably not intentional.` 26 | ) 27 | } 28 | } 29 | 30 | window.___replace(redirect.toPath) 31 | return true 32 | } else { 33 | return false 34 | } 35 | } 36 | 37 | const onPreRouteUpdate = (location, prevLocation) => { 38 | if (!maybeRedirect(location.pathname)) { 39 | apiRunner(`onPreRouteUpdate`, { location, prevLocation }) 40 | } 41 | } 42 | 43 | const onRouteUpdate = (location, prevLocation) => { 44 | if (!maybeRedirect(location.pathname)) { 45 | apiRunner(`onRouteUpdate`, { location, prevLocation }) 46 | } 47 | } 48 | 49 | const navigate = (to, options = {}) => { 50 | let { pathname } = parsePath(to) 51 | const redirect = redirectMap[pathname] 52 | 53 | // If we're redirecting, just replace the passed in pathname 54 | // to the one we want to redirect to. 55 | if (redirect) { 56 | to = redirect.toPath 57 | pathname = parsePath(to).pathname 58 | } 59 | 60 | // If we had a service worker update, no matter the path, reload window and 61 | // reset the pathname whitelist 62 | if (window.___swUpdated) { 63 | window.location = pathname 64 | return 65 | } 66 | 67 | // Start a timer to wait for a second before transitioning and showing a 68 | // loader in case resources aren't around yet. 69 | const timeoutId = setTimeout(() => { 70 | emitter.emit(`onDelayedLoadPageResources`, { pathname }) 71 | apiRunner(`onRouteUpdateDelayed`, { 72 | location: window.location, 73 | }) 74 | }, 1000) 75 | 76 | loader.loadPage(pathname).then(pageResources => { 77 | // If no page resources, then refresh the page 78 | // Do this, rather than simply `window.location.reload()`, so that 79 | // pressing the back/forward buttons work - otherwise when pressing 80 | // back, the browser will just change the URL and expect JS to handle 81 | // the change, which won't always work since it might not be a Gatsby 82 | // page. 83 | if (!pageResources || pageResources.status === PageResourceStatus.Error) { 84 | window.history.replaceState({}, ``, location.href) 85 | window.location = pathname 86 | clearTimeout(timeoutId) 87 | return 88 | } 89 | 90 | // If the loaded page has a different compilation hash to the 91 | // window, then a rebuild has occurred on the server. Reload. 92 | if (process.env.NODE_ENV === `production` && pageResources) { 93 | if ( 94 | pageResources.page.webpackCompilationHash !== 95 | window.___webpackCompilationHash 96 | ) { 97 | // Purge plugin-offline cache 98 | if ( 99 | `serviceWorker` in navigator && 100 | navigator.serviceWorker.controller !== null && 101 | navigator.serviceWorker.controller.state === `activated` 102 | ) { 103 | navigator.serviceWorker.controller.postMessage({ 104 | gatsbyApi: `clearPathResources`, 105 | }) 106 | } 107 | 108 | console.log(`Site has changed on server. Reloading browser`) 109 | window.location = pathname 110 | } 111 | } 112 | reachNavigate(to, options) 113 | clearTimeout(timeoutId) 114 | }) 115 | } 116 | 117 | function shouldUpdateScroll(prevRouterProps, { location }) { 118 | const { pathname, hash } = location 119 | const results = apiRunner(`shouldUpdateScroll`, { 120 | prevRouterProps, 121 | // `pathname` for backwards compatibility 122 | pathname, 123 | routerProps: { location }, 124 | getSavedScrollPosition: args => this._stateStorage.read(args), 125 | }) 126 | if (results.length > 0) { 127 | // Use the latest registered shouldUpdateScroll result, this allows users to override plugin's configuration 128 | // @see https://github.com/gatsbyjs/gatsby/issues/12038 129 | return results[results.length - 1] 130 | } 131 | 132 | if (prevRouterProps) { 133 | const { 134 | location: { pathname: oldPathname }, 135 | } = prevRouterProps 136 | if (oldPathname === pathname) { 137 | // Scroll to element if it exists, if it doesn't, or no hash is provided, 138 | // scroll to top. 139 | return hash ? decodeURI(hash.slice(1)) : [0, 0] 140 | } 141 | } 142 | return true 143 | } 144 | 145 | function init() { 146 | // The "scroll-behavior" package expects the "action" to be on the location 147 | // object so let's copy it over. 148 | globalHistory.listen(args => { 149 | args.location.action = args.action 150 | }) 151 | 152 | window.___push = to => navigate(to, { replace: false }) 153 | window.___replace = to => navigate(to, { replace: true }) 154 | window.___navigate = (to, options) => navigate(to, options) 155 | 156 | // Check for initial page-load redirect 157 | maybeRedirect(window.location.pathname) 158 | } 159 | 160 | class RouteAnnouncer extends React.Component { 161 | constructor(props) { 162 | super(props) 163 | this.announcementRef = React.createRef() 164 | } 165 | 166 | componentDidUpdate(prevProps, nextProps) { 167 | requestAnimationFrame(() => { 168 | let pageName = `new page at ${this.props.location.pathname}` 169 | if (document.title) { 170 | pageName = document.title 171 | } 172 | const pageHeadings = document.querySelectorAll(`#gatsby-focus-wrapper h1`) 173 | if (pageHeadings && pageHeadings.length) { 174 | pageName = pageHeadings[0].textContent 175 | } 176 | const newAnnouncement = `Navigated to ${pageName}` 177 | const oldAnnouncement = this.announcementRef.current.innerText 178 | if (oldAnnouncement !== newAnnouncement) { 179 | this.announcementRef.current.innerText = newAnnouncement 180 | } 181 | }) 182 | } 183 | 184 | render() { 185 | return
186 | } 187 | } 188 | 189 | // Fire on(Pre)RouteUpdate APIs 190 | class RouteUpdates extends React.Component { 191 | constructor(props) { 192 | super(props) 193 | onPreRouteUpdate(props.location, null) 194 | } 195 | 196 | componentDidMount() { 197 | onRouteUpdate(this.props.location, null) 198 | } 199 | 200 | componentDidUpdate(prevProps, prevState, shouldFireRouteUpdate) { 201 | if (shouldFireRouteUpdate) { 202 | onRouteUpdate(this.props.location, prevProps.location) 203 | } 204 | } 205 | 206 | getSnapshotBeforeUpdate(prevProps) { 207 | if (this.props.location.pathname !== prevProps.location.pathname) { 208 | onPreRouteUpdate(this.props.location, prevProps.location) 209 | return true 210 | } 211 | 212 | return false 213 | } 214 | 215 | render() { 216 | return ( 217 | 218 | {this.props.children} 219 | 220 | 221 | ) 222 | } 223 | } 224 | 225 | RouteUpdates.propTypes = { 226 | location: PropTypes.object.isRequired, 227 | } 228 | 229 | export { init, shouldUpdateScroll, RouteUpdates } 230 | -------------------------------------------------------------------------------- /.cache/commonjs/navigation.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); 4 | 5 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 6 | 7 | exports.__esModule = true; 8 | exports.init = init; 9 | exports.shouldUpdateScroll = shouldUpdateScroll; 10 | exports.RouteUpdates = void 0; 11 | 12 | var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); 13 | 14 | var _react = _interopRequireDefault(require("react")); 15 | 16 | var _propTypes = _interopRequireDefault(require("prop-types")); 17 | 18 | var _loader = _interopRequireWildcard(require("./loader")); 19 | 20 | var _redirects = _interopRequireDefault(require("./redirects.json")); 21 | 22 | var _apiRunnerBrowser = require("./api-runner-browser"); 23 | 24 | var _emitter = _interopRequireDefault(require("./emitter")); 25 | 26 | var _routeAnnouncerProps = require("./route-announcer-props"); 27 | 28 | var _router = require("@reach/router"); 29 | 30 | var _history = require("@reach/router/lib/history"); 31 | 32 | var _gatsbyLink = require("gatsby-link"); 33 | 34 | // Convert to a map for faster lookup in maybeRedirect() 35 | const redirectMap = _redirects.default.reduce((map, redirect) => { 36 | map[redirect.fromPath] = redirect; 37 | return map; 38 | }, {}); 39 | 40 | function maybeRedirect(pathname) { 41 | const redirect = redirectMap[pathname]; 42 | 43 | if (redirect != null) { 44 | if (process.env.NODE_ENV !== `production`) { 45 | if (!_loader.default.isPageNotFound(pathname)) { 46 | console.error(`The route "${pathname}" matches both a page and a redirect; this is probably not intentional.`); 47 | } 48 | } 49 | 50 | window.___replace(redirect.toPath); 51 | 52 | return true; 53 | } else { 54 | return false; 55 | } 56 | } 57 | 58 | const onPreRouteUpdate = (location, prevLocation) => { 59 | if (!maybeRedirect(location.pathname)) { 60 | (0, _apiRunnerBrowser.apiRunner)(`onPreRouteUpdate`, { 61 | location, 62 | prevLocation 63 | }); 64 | } 65 | }; 66 | 67 | const onRouteUpdate = (location, prevLocation) => { 68 | if (!maybeRedirect(location.pathname)) { 69 | (0, _apiRunnerBrowser.apiRunner)(`onRouteUpdate`, { 70 | location, 71 | prevLocation 72 | }); 73 | } 74 | }; 75 | 76 | const navigate = (to, options = {}) => { 77 | let { 78 | pathname 79 | } = (0, _gatsbyLink.parsePath)(to); 80 | const redirect = redirectMap[pathname]; // If we're redirecting, just replace the passed in pathname 81 | // to the one we want to redirect to. 82 | 83 | if (redirect) { 84 | to = redirect.toPath; 85 | pathname = (0, _gatsbyLink.parsePath)(to).pathname; 86 | } // If we had a service worker update, no matter the path, reload window and 87 | // reset the pathname whitelist 88 | 89 | 90 | if (window.___swUpdated) { 91 | window.location = pathname; 92 | return; 93 | } // Start a timer to wait for a second before transitioning and showing a 94 | // loader in case resources aren't around yet. 95 | 96 | 97 | const timeoutId = setTimeout(() => { 98 | _emitter.default.emit(`onDelayedLoadPageResources`, { 99 | pathname 100 | }); 101 | 102 | (0, _apiRunnerBrowser.apiRunner)(`onRouteUpdateDelayed`, { 103 | location: window.location 104 | }); 105 | }, 1000); 106 | 107 | _loader.default.loadPage(pathname).then(pageResources => { 108 | // If no page resources, then refresh the page 109 | // Do this, rather than simply `window.location.reload()`, so that 110 | // pressing the back/forward buttons work - otherwise when pressing 111 | // back, the browser will just change the URL and expect JS to handle 112 | // the change, which won't always work since it might not be a Gatsby 113 | // page. 114 | if (!pageResources || pageResources.status === _loader.PageResourceStatus.Error) { 115 | window.history.replaceState({}, ``, location.href); 116 | window.location = pathname; 117 | clearTimeout(timeoutId); 118 | return; 119 | } // If the loaded page has a different compilation hash to the 120 | // window, then a rebuild has occurred on the server. Reload. 121 | 122 | 123 | if (process.env.NODE_ENV === `production` && pageResources) { 124 | if (pageResources.page.webpackCompilationHash !== window.___webpackCompilationHash) { 125 | // Purge plugin-offline cache 126 | if (`serviceWorker` in navigator && navigator.serviceWorker.controller !== null && navigator.serviceWorker.controller.state === `activated`) { 127 | navigator.serviceWorker.controller.postMessage({ 128 | gatsbyApi: `clearPathResources` 129 | }); 130 | } 131 | 132 | console.log(`Site has changed on server. Reloading browser`); 133 | window.location = pathname; 134 | } 135 | } 136 | 137 | (0, _router.navigate)(to, options); 138 | clearTimeout(timeoutId); 139 | }); 140 | }; 141 | 142 | function shouldUpdateScroll(prevRouterProps, { 143 | location 144 | }) { 145 | const { 146 | pathname, 147 | hash 148 | } = location; 149 | const results = (0, _apiRunnerBrowser.apiRunner)(`shouldUpdateScroll`, { 150 | prevRouterProps, 151 | // `pathname` for backwards compatibility 152 | pathname, 153 | routerProps: { 154 | location 155 | }, 156 | getSavedScrollPosition: args => this._stateStorage.read(args) 157 | }); 158 | 159 | if (results.length > 0) { 160 | // Use the latest registered shouldUpdateScroll result, this allows users to override plugin's configuration 161 | // @see https://github.com/gatsbyjs/gatsby/issues/12038 162 | return results[results.length - 1]; 163 | } 164 | 165 | if (prevRouterProps) { 166 | const { 167 | location: { 168 | pathname: oldPathname 169 | } 170 | } = prevRouterProps; 171 | 172 | if (oldPathname === pathname) { 173 | // Scroll to element if it exists, if it doesn't, or no hash is provided, 174 | // scroll to top. 175 | return hash ? decodeURI(hash.slice(1)) : [0, 0]; 176 | } 177 | } 178 | 179 | return true; 180 | } 181 | 182 | function init() { 183 | // The "scroll-behavior" package expects the "action" to be on the location 184 | // object so let's copy it over. 185 | _history.globalHistory.listen(args => { 186 | args.location.action = args.action; 187 | }); 188 | 189 | window.___push = to => navigate(to, { 190 | replace: false 191 | }); 192 | 193 | window.___replace = to => navigate(to, { 194 | replace: true 195 | }); 196 | 197 | window.___navigate = (to, options) => navigate(to, options); // Check for initial page-load redirect 198 | 199 | 200 | maybeRedirect(window.location.pathname); 201 | } 202 | 203 | class RouteAnnouncer extends _react.default.Component { 204 | constructor(props) { 205 | super(props); 206 | this.announcementRef = _react.default.createRef(); 207 | } 208 | 209 | componentDidUpdate(prevProps, nextProps) { 210 | requestAnimationFrame(() => { 211 | let pageName = `new page at ${this.props.location.pathname}`; 212 | 213 | if (document.title) { 214 | pageName = document.title; 215 | } 216 | 217 | const pageHeadings = document.querySelectorAll(`#gatsby-focus-wrapper h1`); 218 | 219 | if (pageHeadings && pageHeadings.length) { 220 | pageName = pageHeadings[0].textContent; 221 | } 222 | 223 | const newAnnouncement = `Navigated to ${pageName}`; 224 | const oldAnnouncement = this.announcementRef.current.innerText; 225 | 226 | if (oldAnnouncement !== newAnnouncement) { 227 | this.announcementRef.current.innerText = newAnnouncement; 228 | } 229 | }); 230 | } 231 | 232 | render() { 233 | return (/*#__PURE__*/_react.default.createElement("div", (0, _extends2.default)({}, _routeAnnouncerProps.RouteAnnouncerProps, { 234 | ref: this.announcementRef 235 | })) 236 | ); 237 | } 238 | 239 | } // Fire on(Pre)RouteUpdate APIs 240 | 241 | 242 | class RouteUpdates extends _react.default.Component { 243 | constructor(props) { 244 | super(props); 245 | onPreRouteUpdate(props.location, null); 246 | } 247 | 248 | componentDidMount() { 249 | onRouteUpdate(this.props.location, null); 250 | } 251 | 252 | componentDidUpdate(prevProps, prevState, shouldFireRouteUpdate) { 253 | if (shouldFireRouteUpdate) { 254 | onRouteUpdate(this.props.location, prevProps.location); 255 | } 256 | } 257 | 258 | getSnapshotBeforeUpdate(prevProps) { 259 | if (this.props.location.pathname !== prevProps.location.pathname) { 260 | onPreRouteUpdate(this.props.location, prevProps.location); 261 | return true; 262 | } 263 | 264 | return false; 265 | } 266 | 267 | render() { 268 | return (/*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, this.props.children, /*#__PURE__*/_react.default.createElement(RouteAnnouncer, { 269 | location: location 270 | })) 271 | ); 272 | } 273 | 274 | } 275 | 276 | exports.RouteUpdates = RouteUpdates; 277 | RouteUpdates.propTypes = { 278 | location: _propTypes.default.object.isRequired 279 | }; -------------------------------------------------------------------------------- /.cache/api-ssr-docs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Object containing options defined in `gatsby-config.js` 3 | * @typedef {object} pluginOptions 4 | */ 5 | 6 | /** 7 | * Replace the default server renderer. This is useful for integration with 8 | * Redux, css-in-js libraries, etc. that need custom setups for server 9 | * rendering. 10 | * @param {object} $0 11 | * @param {string} $0.pathname The pathname of the page currently being rendered. 12 | * @param {function} $0.replaceBodyHTMLString Call this with the HTML string 13 | * you render. **WARNING** if multiple plugins implement this API it's the 14 | * last plugin that "wins". TODO implement an automated warning against this. 15 | * @param {function} $0.setHeadComponents Takes an array of components as its 16 | * first argument which are added to the `headComponents` array which is passed 17 | * to the `html.js` component. 18 | * @param {function} $0.setHtmlAttributes Takes an object of props which will 19 | * spread into the `` component. 20 | * @param {function} $0.setBodyAttributes Takes an object of props which will 21 | * spread into the `` component. 22 | * @param {function} $0.setPreBodyComponents Takes an array of components as its 23 | * first argument which are added to the `preBodyComponents` array which is passed 24 | * to the `html.js` component. 25 | * @param {function} $0.setPostBodyComponents Takes an array of components as its 26 | * first argument which are added to the `postBodyComponents` array which is passed 27 | * to the `html.js` component. 28 | * @param {function} $0.setBodyProps Takes an object of data which 29 | * is merged with other body props and passed to `html.js` as `bodyProps`. 30 | * @param {pluginOptions} pluginOptions 31 | * @example 32 | * // From gatsby-plugin-glamor 33 | * const { renderToString } = require("react-dom/server") 34 | * const inline = require("glamor-inline") 35 | * 36 | * exports.replaceRenderer = ({ bodyComponent, replaceBodyHTMLString }) => { 37 | * const bodyHTML = renderToString(bodyComponent) 38 | * const inlinedHTML = inline(bodyHTML) 39 | * 40 | * replaceBodyHTMLString(inlinedHTML) 41 | * } 42 | */ 43 | exports.replaceRenderer = true 44 | 45 | /** 46 | * Called after every page Gatsby server renders while building HTML so you can 47 | * set head and body components to be rendered in your `html.js`. 48 | * 49 | * Gatsby does a two-pass render for HTML. It loops through your pages first 50 | * rendering only the body and then takes the result body HTML string and 51 | * passes it as the `body` prop to your `html.js` to complete the render. 52 | * 53 | * It's often handy to be able to send custom components to your `html.js`. 54 | * For example, it's a very common pattern for React.js libraries that 55 | * support server rendering to pull out data generated during the render to 56 | * add to your HTML. 57 | * 58 | * Using this API over [`replaceRenderer`](#replaceRenderer) is preferable as 59 | * multiple plugins can implement this API where only one plugin can take 60 | * over server rendering. However, if your plugin requires taking over server 61 | * rendering then that's the one to 62 | * use 63 | * @param {object} $0 64 | * @param {string} $0.pathname The pathname of the page currently being rendered. 65 | * @param {function} $0.setHeadComponents Takes an array of components as its 66 | * first argument which are added to the `headComponents` array which is passed 67 | * to the `html.js` component. 68 | * @param {function} $0.setHtmlAttributes Takes an object of props which will 69 | * spread into the `` component. 70 | * @param {function} $0.setBodyAttributes Takes an object of props which will 71 | * spread into the `` component. 72 | * @param {function} $0.setPreBodyComponents Takes an array of components as its 73 | * first argument which are added to the `preBodyComponents` array which is passed 74 | * to the `html.js` component. 75 | * @param {function} $0.setPostBodyComponents Takes an array of components as its 76 | * first argument which are added to the `postBodyComponents` array which is passed 77 | * to the `html.js` component. 78 | * @param {function} $0.setBodyProps Takes an object of data which 79 | * is merged with other body props and passed to `html.js` as `bodyProps`. 80 | * @param {pluginOptions} pluginOptions 81 | * @example 82 | * const { Helmet } = require("react-helmet") 83 | * 84 | * exports.onRenderBody = ( 85 | * { setHeadComponents, setHtmlAttributes, setBodyAttributes }, 86 | * pluginOptions 87 | * ) => { 88 | * const helmet = Helmet.renderStatic() 89 | * setHtmlAttributes(helmet.htmlAttributes.toComponent()) 90 | * setBodyAttributes(helmet.bodyAttributes.toComponent()) 91 | * setHeadComponents([ 92 | * helmet.title.toComponent(), 93 | * helmet.link.toComponent(), 94 | * helmet.meta.toComponent(), 95 | * helmet.noscript.toComponent(), 96 | * helmet.script.toComponent(), 97 | * helmet.style.toComponent(), 98 | * ]) 99 | * } 100 | */ 101 | exports.onRenderBody = true 102 | 103 | /** 104 | * Called after every page Gatsby server renders while building HTML so you can 105 | * replace head components to be rendered in your `html.js`. This is useful if 106 | * you need to reorder scripts or styles added by other plugins. 107 | * @param {object} $0 108 | * @param {string} $0.pathname The pathname of the page currently being rendered. 109 | * @param {Array} $0.getHeadComponents Returns the current `headComponents` array. 110 | * @param {function} $0.replaceHeadComponents Takes an array of components as its 111 | * first argument which replace the `headComponents` array which is passed 112 | * to the `html.js` component. **WARNING** if multiple plugins implement this 113 | * API it's the last plugin that "wins". 114 | * @param {Array} $0.getPreBodyComponents Returns the current `preBodyComponents` array. 115 | * @param {function} $0.replacePreBodyComponents Takes an array of components as its 116 | * first argument which replace the `preBodyComponents` array which is passed 117 | * to the `html.js` component. **WARNING** if multiple plugins implement this 118 | * API it's the last plugin that "wins". 119 | * @param {Array} $0.getPostBodyComponents Returns the current `postBodyComponents` array. 120 | * @param {function} $0.replacePostBodyComponents Takes an array of components as its 121 | * first argument which replace the `postBodyComponents` array which is passed 122 | * to the `html.js` component. **WARNING** if multiple plugins implement this 123 | * API it's the last plugin that "wins". 124 | * @param {pluginOptions} pluginOptions 125 | * @example 126 | * // Move Typography.js styles to the top of the head section so they're loaded first. 127 | * exports.onPreRenderHTML = ({ getHeadComponents, replaceHeadComponents }) => { 128 | * const headComponents = getHeadComponents() 129 | * headComponents.sort((x, y) => { 130 | * if (x.key === 'TypographyStyle') { 131 | * return -1 132 | * } else if (y.key === 'TypographyStyle') { 133 | * return 1 134 | * } 135 | * return 0 136 | * }) 137 | * replaceHeadComponents(headComponents) 138 | * } 139 | */ 140 | exports.onPreRenderHTML = true 141 | 142 | /** 143 | * Allow a plugin to wrap the page element. 144 | * 145 | * This is useful for setting wrapper components around pages that won't get 146 | * unmounted on page changes. For setting Provider components, use [wrapRootElement](#wrapRootElement). 147 | * 148 | * _Note:_ 149 | * There is an equivalent hook in Gatsby's [Browser API](/docs/browser-apis/#wrapPageElement). 150 | * It is recommended to use both APIs together. 151 | * For example usage, check out [Using i18n](https://github.com/gatsbyjs/gatsby/tree/master/examples/using-i18n). 152 | * @param {object} $0 153 | * @param {ReactNode} $0.element The "Page" React Element built by Gatsby. 154 | * @param {object} $0.props Props object used by page. 155 | * @param {pluginOptions} pluginOptions 156 | * @returns {ReactNode} Wrapped element 157 | * @example 158 | * const React = require("react") 159 | * const Layout = require("./src/components/layout").default 160 | * 161 | * exports.wrapPageElement = ({ element, props }) => { 162 | * // props provide same data to Layout as Page element will get 163 | * // including location, data, etc - you don't need to pass it 164 | * return {element} 165 | * } 166 | */ 167 | exports.wrapPageElement = true 168 | 169 | /** 170 | * Allow a plugin to wrap the root element. 171 | * 172 | * This is useful to set up any Provider components that will wrap your application. 173 | * For setting persistent UI elements around pages use [wrapPageElement](#wrapPageElement). 174 | * 175 | * _Note:_ 176 | * There is an equivalent hook in Gatsby's [Browser API](/docs/browser-apis/#wrapRootElement). 177 | * It is recommended to use both APIs together. 178 | * For example usage, check out [Using redux](https://github.com/gatsbyjs/gatsby/tree/master/examples/using-redux). 179 | * @param {object} $0 180 | * @param {ReactNode} $0.element The "Root" React Element built by Gatsby. 181 | * @param {pluginOptions} pluginOptions 182 | * @returns {ReactNode} Wrapped element 183 | * @example 184 | * const React = require("react") 185 | * const { Provider } = require("react-redux") 186 | * 187 | * const createStore = require("./src/state/createStore") 188 | * const store = createStore() 189 | * 190 | * exports.wrapRootElement = ({ element }) => { 191 | * return ( 192 | * 193 | * {element} 194 | * 195 | * ) 196 | * } 197 | */ 198 | exports.wrapRootElement = true 199 | -------------------------------------------------------------------------------- /.cache/commonjs/api-ssr-docs.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | /** 4 | * Object containing options defined in `gatsby-config.js` 5 | * @typedef {object} pluginOptions 6 | */ 7 | 8 | /** 9 | * Replace the default server renderer. This is useful for integration with 10 | * Redux, css-in-js libraries, etc. that need custom setups for server 11 | * rendering. 12 | * @param {object} $0 13 | * @param {string} $0.pathname The pathname of the page currently being rendered. 14 | * @param {function} $0.replaceBodyHTMLString Call this with the HTML string 15 | * you render. **WARNING** if multiple plugins implement this API it's the 16 | * last plugin that "wins". TODO implement an automated warning against this. 17 | * @param {function} $0.setHeadComponents Takes an array of components as its 18 | * first argument which are added to the `headComponents` array which is passed 19 | * to the `html.js` component. 20 | * @param {function} $0.setHtmlAttributes Takes an object of props which will 21 | * spread into the `` component. 22 | * @param {function} $0.setBodyAttributes Takes an object of props which will 23 | * spread into the `` component. 24 | * @param {function} $0.setPreBodyComponents Takes an array of components as its 25 | * first argument which are added to the `preBodyComponents` array which is passed 26 | * to the `html.js` component. 27 | * @param {function} $0.setPostBodyComponents Takes an array of components as its 28 | * first argument which are added to the `postBodyComponents` array which is passed 29 | * to the `html.js` component. 30 | * @param {function} $0.setBodyProps Takes an object of data which 31 | * is merged with other body props and passed to `html.js` as `bodyProps`. 32 | * @param {pluginOptions} pluginOptions 33 | * @example 34 | * // From gatsby-plugin-glamor 35 | * const { renderToString } = require("react-dom/server") 36 | * const inline = require("glamor-inline") 37 | * 38 | * exports.replaceRenderer = ({ bodyComponent, replaceBodyHTMLString }) => { 39 | * const bodyHTML = renderToString(bodyComponent) 40 | * const inlinedHTML = inline(bodyHTML) 41 | * 42 | * replaceBodyHTMLString(inlinedHTML) 43 | * } 44 | */ 45 | exports.replaceRenderer = true; 46 | /** 47 | * Called after every page Gatsby server renders while building HTML so you can 48 | * set head and body components to be rendered in your `html.js`. 49 | * 50 | * Gatsby does a two-pass render for HTML. It loops through your pages first 51 | * rendering only the body and then takes the result body HTML string and 52 | * passes it as the `body` prop to your `html.js` to complete the render. 53 | * 54 | * It's often handy to be able to send custom components to your `html.js`. 55 | * For example, it's a very common pattern for React.js libraries that 56 | * support server rendering to pull out data generated during the render to 57 | * add to your HTML. 58 | * 59 | * Using this API over [`replaceRenderer`](#replaceRenderer) is preferable as 60 | * multiple plugins can implement this API where only one plugin can take 61 | * over server rendering. However, if your plugin requires taking over server 62 | * rendering then that's the one to 63 | * use 64 | * @param {object} $0 65 | * @param {string} $0.pathname The pathname of the page currently being rendered. 66 | * @param {function} $0.setHeadComponents Takes an array of components as its 67 | * first argument which are added to the `headComponents` array which is passed 68 | * to the `html.js` component. 69 | * @param {function} $0.setHtmlAttributes Takes an object of props which will 70 | * spread into the `` component. 71 | * @param {function} $0.setBodyAttributes Takes an object of props which will 72 | * spread into the `` component. 73 | * @param {function} $0.setPreBodyComponents Takes an array of components as its 74 | * first argument which are added to the `preBodyComponents` array which is passed 75 | * to the `html.js` component. 76 | * @param {function} $0.setPostBodyComponents Takes an array of components as its 77 | * first argument which are added to the `postBodyComponents` array which is passed 78 | * to the `html.js` component. 79 | * @param {function} $0.setBodyProps Takes an object of data which 80 | * is merged with other body props and passed to `html.js` as `bodyProps`. 81 | * @param {pluginOptions} pluginOptions 82 | * @example 83 | * const { Helmet } = require("react-helmet") 84 | * 85 | * exports.onRenderBody = ( 86 | * { setHeadComponents, setHtmlAttributes, setBodyAttributes }, 87 | * pluginOptions 88 | * ) => { 89 | * const helmet = Helmet.renderStatic() 90 | * setHtmlAttributes(helmet.htmlAttributes.toComponent()) 91 | * setBodyAttributes(helmet.bodyAttributes.toComponent()) 92 | * setHeadComponents([ 93 | * helmet.title.toComponent(), 94 | * helmet.link.toComponent(), 95 | * helmet.meta.toComponent(), 96 | * helmet.noscript.toComponent(), 97 | * helmet.script.toComponent(), 98 | * helmet.style.toComponent(), 99 | * ]) 100 | * } 101 | */ 102 | 103 | exports.onRenderBody = true; 104 | /** 105 | * Called after every page Gatsby server renders while building HTML so you can 106 | * replace head components to be rendered in your `html.js`. This is useful if 107 | * you need to reorder scripts or styles added by other plugins. 108 | * @param {object} $0 109 | * @param {string} $0.pathname The pathname of the page currently being rendered. 110 | * @param {Array} $0.getHeadComponents Returns the current `headComponents` array. 111 | * @param {function} $0.replaceHeadComponents Takes an array of components as its 112 | * first argument which replace the `headComponents` array which is passed 113 | * to the `html.js` component. **WARNING** if multiple plugins implement this 114 | * API it's the last plugin that "wins". 115 | * @param {Array} $0.getPreBodyComponents Returns the current `preBodyComponents` array. 116 | * @param {function} $0.replacePreBodyComponents Takes an array of components as its 117 | * first argument which replace the `preBodyComponents` array which is passed 118 | * to the `html.js` component. **WARNING** if multiple plugins implement this 119 | * API it's the last plugin that "wins". 120 | * @param {Array} $0.getPostBodyComponents Returns the current `postBodyComponents` array. 121 | * @param {function} $0.replacePostBodyComponents Takes an array of components as its 122 | * first argument which replace the `postBodyComponents` array which is passed 123 | * to the `html.js` component. **WARNING** if multiple plugins implement this 124 | * API it's the last plugin that "wins". 125 | * @param {pluginOptions} pluginOptions 126 | * @example 127 | * // Move Typography.js styles to the top of the head section so they're loaded first. 128 | * exports.onPreRenderHTML = ({ getHeadComponents, replaceHeadComponents }) => { 129 | * const headComponents = getHeadComponents() 130 | * headComponents.sort((x, y) => { 131 | * if (x.key === 'TypographyStyle') { 132 | * return -1 133 | * } else if (y.key === 'TypographyStyle') { 134 | * return 1 135 | * } 136 | * return 0 137 | * }) 138 | * replaceHeadComponents(headComponents) 139 | * } 140 | */ 141 | 142 | exports.onPreRenderHTML = true; 143 | /** 144 | * Allow a plugin to wrap the page element. 145 | * 146 | * This is useful for setting wrapper components around pages that won't get 147 | * unmounted on page changes. For setting Provider components, use [wrapRootElement](#wrapRootElement). 148 | * 149 | * _Note:_ 150 | * There is an equivalent hook in Gatsby's [Browser API](/docs/browser-apis/#wrapPageElement). 151 | * It is recommended to use both APIs together. 152 | * For example usage, check out [Using i18n](https://github.com/gatsbyjs/gatsby/tree/master/examples/using-i18n). 153 | * @param {object} $0 154 | * @param {ReactNode} $0.element The "Page" React Element built by Gatsby. 155 | * @param {object} $0.props Props object used by page. 156 | * @param {pluginOptions} pluginOptions 157 | * @returns {ReactNode} Wrapped element 158 | * @example 159 | * const React = require("react") 160 | * const Layout = require("./src/components/layout").default 161 | * 162 | * exports.wrapPageElement = ({ element, props }) => { 163 | * // props provide same data to Layout as Page element will get 164 | * // including location, data, etc - you don't need to pass it 165 | * return {element} 166 | * } 167 | */ 168 | 169 | exports.wrapPageElement = true; 170 | /** 171 | * Allow a plugin to wrap the root element. 172 | * 173 | * This is useful to set up any Provider components that will wrap your application. 174 | * For setting persistent UI elements around pages use [wrapPageElement](#wrapPageElement). 175 | * 176 | * _Note:_ 177 | * There is an equivalent hook in Gatsby's [Browser API](/docs/browser-apis/#wrapRootElement). 178 | * It is recommended to use both APIs together. 179 | * For example usage, check out [Using redux](https://github.com/gatsbyjs/gatsby/tree/master/examples/using-redux). 180 | * @param {object} $0 181 | * @param {ReactNode} $0.element The "Root" React Element built by Gatsby. 182 | * @param {pluginOptions} pluginOptions 183 | * @returns {ReactNode} Wrapped element 184 | * @example 185 | * const React = require("react") 186 | * const { Provider } = require("react-redux") 187 | * 188 | * const createStore = require("./src/state/createStore") 189 | * const store = createStore() 190 | * 191 | * exports.wrapRootElement = ({ element }) => { 192 | * return ( 193 | * 194 | * {element} 195 | * 196 | * ) 197 | * } 198 | */ 199 | 200 | exports.wrapRootElement = true; -------------------------------------------------------------------------------- /.cache/__tests__/static-entry.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import fs from "fs" 3 | const { join } = require(`path`) 4 | 5 | import DevelopStaticEntry from "../develop-static-entry" 6 | 7 | jest.mock(`fs`, () => { 8 | const fs = jest.requireActual(`fs`) 9 | return { 10 | ...fs, 11 | readFileSync: jest.fn(), 12 | } 13 | }) 14 | jest.mock(`gatsby/package.json`, () => { 15 | return { 16 | version: `2.0.0`, 17 | } 18 | }) 19 | 20 | jest.mock( 21 | `../sync-requires`, 22 | () => { 23 | return { 24 | components: { 25 | "page-component---src-pages-test-js": () => null, 26 | }, 27 | } 28 | }, 29 | { 30 | virtual: true, 31 | } 32 | ) 33 | 34 | const MOCK_FILE_INFO = { 35 | [`${process.cwd()}/public/webpack.stats.json`]: `{}`, 36 | [`${process.cwd()}/public/chunk-map.json`]: `{}`, 37 | [join( 38 | process.cwd(), 39 | `/public/page-data/about/page-data.json` 40 | )]: JSON.stringify({ 41 | componentChunkName: `page-component---src-pages-test-js`, 42 | path: `/about/`, 43 | webpackCompilationHash: `1234567890abcdef1234`, 44 | }), 45 | [join(process.cwd(), `/public/page-data/app-data.json`)]: JSON.stringify({ 46 | webpackCompilationHash: `1234567890abcdef1234`, 47 | }), 48 | } 49 | 50 | let StaticEntry 51 | beforeEach(() => { 52 | fs.readFileSync.mockImplementation(file => MOCK_FILE_INFO[file]) 53 | StaticEntry = require(`../static-entry`).default 54 | }) 55 | 56 | const reverseHeadersPlugin = { 57 | plugin: { 58 | onPreRenderHTML: ({ getHeadComponents, replaceHeadComponents }) => { 59 | const headComponents = getHeadComponents() 60 | headComponents.reverse() 61 | replaceHeadComponents(headComponents) 62 | }, 63 | }, 64 | } 65 | 66 | const injectValuePlugin = (hookName, methodName, value) => { 67 | return { 68 | plugin: { 69 | [hookName]: staticEntry => { 70 | const method = staticEntry[methodName] 71 | method(value) 72 | }, 73 | }, 74 | } 75 | } 76 | 77 | const checkSanitized = components => { 78 | expect(components.includes(null)).toBeFalsy() 79 | expect( 80 | components.find(val => Array.isArray(val) && val.length === 0) 81 | ).toBeFalsy() 82 | expect(components.find(val => Array.isArray(val))).toBeFalsy() 83 | } 84 | 85 | const checkNonEmptyHeadersPlugin = { 86 | plugin: { 87 | onPreRenderHTML: ({ 88 | getHeadComponents, 89 | getPreBodyComponents, 90 | getPostBodyComponents, 91 | }) => { 92 | const headComponents = getHeadComponents() 93 | const preBodyComponents = getPreBodyComponents() 94 | const postBodyComponents = getPostBodyComponents() 95 | checkSanitized(headComponents) 96 | checkSanitized(preBodyComponents) 97 | checkSanitized(postBodyComponents) 98 | }, 99 | }, 100 | } 101 | 102 | const fakeStylesPlugin = { 103 | plugin: { 104 | onRenderBody: ({ setHeadComponents }) => 105 | setHeadComponents([ 106 | , 107 | , 108 | , 109 | ]), 110 | }, 111 | } 112 | 113 | const reverseBodyComponentsPluginFactory = type => { 114 | return { 115 | plugin: { 116 | onPreRenderHTML: props => { 117 | const components = props[`get${type}BodyComponents`]() 118 | components.reverse() 119 | props[`replace${type}BodyComponents`](components) 120 | }, 121 | }, 122 | } 123 | } 124 | 125 | const fakeComponentsPluginFactory = type => { 126 | return { 127 | plugin: { 128 | onRenderBody: props => { 129 | props[`set${type}BodyComponents`]([ 130 |
div1
, 131 |
div2
, 132 |
div3
, 133 | ]) 134 | }, 135 | }, 136 | } 137 | } 138 | 139 | describe(`develop-static-entry`, () => { 140 | test(`onPreRenderHTML can be used to replace headComponents`, done => { 141 | global.plugins = [fakeStylesPlugin, reverseHeadersPlugin] 142 | 143 | DevelopStaticEntry(`/about/`, (_, html) => { 144 | expect(html).toMatchSnapshot() 145 | done() 146 | }) 147 | }) 148 | 149 | test(`onPreRenderHTML can be used to replace postBodyComponents`, done => { 150 | global.plugins = [ 151 | fakeComponentsPluginFactory(`Post`), 152 | reverseBodyComponentsPluginFactory(`Post`), 153 | ] 154 | 155 | DevelopStaticEntry(`/about/`, (_, html) => { 156 | expect(html).toMatchSnapshot() 157 | done() 158 | }) 159 | }) 160 | 161 | test(`onPreRenderHTML can be used to replace preBodyComponents`, done => { 162 | global.plugins = [ 163 | fakeComponentsPluginFactory(`Pre`), 164 | reverseBodyComponentsPluginFactory(`Pre`), 165 | ] 166 | 167 | DevelopStaticEntry(`/about/`, (_, html) => { 168 | expect(html).toMatchSnapshot() 169 | done() 170 | }) 171 | }) 172 | 173 | test(`onPreRenderHTML adds metatag note for development environment`, done => { 174 | DevelopStaticEntry(`/about/`, (_, html) => { 175 | expect(html).toContain( 176 | `` 177 | ) 178 | done() 179 | }) 180 | }) 181 | 182 | test(`onPreRenderHTML adds metatag note for development environment after replaceHeadComponents`, done => { 183 | global.plugins = [reverseHeadersPlugin] 184 | 185 | DevelopStaticEntry(`/about/`, (_, html) => { 186 | expect(html).toContain( 187 | `` 188 | ) 189 | done() 190 | }) 191 | }) 192 | }) 193 | 194 | describe(`static-entry sanity checks`, () => { 195 | beforeEach(() => { 196 | global.__PATH_PREFIX__ = `` 197 | global.__BASE_PATH__ = `` 198 | global.__ASSET_PREFIX__ = `` 199 | }) 200 | 201 | const methodsToCheck = [ 202 | `replaceHeadComponents`, 203 | `replacePreBodyComponents`, 204 | `replacePostBodyComponents`, 205 | ] 206 | 207 | methodsToCheck.forEach(methodName => { 208 | test(`${methodName} can filter out null value`, done => { 209 | const plugin = injectValuePlugin(`onPreRenderHTML`, methodName, null) 210 | global.plugins = [plugin, checkNonEmptyHeadersPlugin] 211 | 212 | StaticEntry(`/about/`, (_, html) => { 213 | done() 214 | }) 215 | }) 216 | 217 | test(`${methodName} can filter out null values`, done => { 218 | const plugin = injectValuePlugin(`onPreRenderHTML`, methodName, [ 219 | null, 220 | null, 221 | ]) 222 | global.plugins = [plugin, checkNonEmptyHeadersPlugin] 223 | 224 | StaticEntry(`/about/`, (_, html) => { 225 | done() 226 | }) 227 | }) 228 | 229 | test(`${methodName} can filter out empty array`, done => { 230 | const plugin = injectValuePlugin(`onPreRenderHTML`, methodName, []) 231 | global.plugins = [plugin, checkNonEmptyHeadersPlugin] 232 | 233 | StaticEntry(`/about/`, (_, html) => { 234 | done() 235 | }) 236 | }) 237 | 238 | test(`${methodName} can filter out empty arrays`, done => { 239 | const plugin = injectValuePlugin(`onPreRenderHTML`, methodName, [[], []]) 240 | global.plugins = [plugin, checkNonEmptyHeadersPlugin] 241 | 242 | StaticEntry(`/about/`, (_, html) => { 243 | done() 244 | }) 245 | }) 246 | 247 | test(`${methodName} can flatten arrays`, done => { 248 | const plugin = injectValuePlugin(`onPreRenderHTML`, methodName, [ 249 | , 250 | , 251 | , 252 | [], 253 | ]) 254 | global.plugins = [plugin, checkNonEmptyHeadersPlugin] 255 | 256 | StaticEntry(`/about/`, (_, html) => { 257 | done() 258 | }) 259 | }) 260 | }) 261 | }) 262 | 263 | describe(`static-entry`, () => { 264 | beforeEach(() => { 265 | global.__PATH_PREFIX__ = `` 266 | global.__BASE_PATH__ = `` 267 | fs.readFileSync.mockImplementation(file => MOCK_FILE_INFO[file]) 268 | }) 269 | 270 | test(`onPreRenderHTML can be used to replace headComponents`, done => { 271 | global.plugins = [fakeStylesPlugin, reverseHeadersPlugin] 272 | 273 | StaticEntry(`/about/`, (_, html) => { 274 | expect(html).toMatchSnapshot() 275 | done() 276 | }) 277 | }) 278 | 279 | test(`onPreRenderHTML can be used to replace postBodyComponents`, done => { 280 | global.plugins = [ 281 | fakeComponentsPluginFactory(`Post`), 282 | reverseBodyComponentsPluginFactory(`Post`), 283 | ] 284 | 285 | StaticEntry(`/about/`, (_, html) => { 286 | expect(html).toMatchSnapshot() 287 | done() 288 | }) 289 | }) 290 | 291 | test(`onPreRenderHTML can be used to replace preBodyComponents`, done => { 292 | global.plugins = [ 293 | fakeComponentsPluginFactory(`Pre`), 294 | reverseBodyComponentsPluginFactory(`Pre`), 295 | ] 296 | 297 | StaticEntry(`/about/`, (_, html) => { 298 | expect(html).toMatchSnapshot() 299 | done() 300 | }) 301 | }) 302 | 303 | test(`onPreRenderHTML does not add metatag note for development environment`, done => { 304 | StaticEntry(`/about/`, (_, html) => { 305 | expect(html).not.toContain( 306 | `` 307 | ) 308 | done() 309 | }) 310 | }) 311 | }) 312 | 313 | describe(`sanitizeComponents`, () => { 314 | let sanitizeComponents 315 | 316 | beforeEach(() => { 317 | fs.readFileSync.mockImplementation(file => MOCK_FILE_INFO[file]) 318 | sanitizeComponents = require(`../static-entry`).sanitizeComponents 319 | }) 320 | 321 | it(`strips assetPrefix for manifest link`, () => { 322 | global.__PATH_PREFIX__ = `https://gatsbyjs.org/blog` 323 | global.__BASE_PATH__ = `/blog` 324 | global.__ASSET_PREFIX__ = `https://gatsbyjs.org` 325 | 326 | const sanitizedComponents = sanitizeComponents([ 327 | , 332 | ]) 333 | expect(sanitizedComponents[0].props.href).toBe(`/blog/manifest.webmanifest`) 334 | }) 335 | }) 336 | -------------------------------------------------------------------------------- /.cache/static-entry.js: -------------------------------------------------------------------------------- 1 | const React = require(`react`) 2 | const fs = require(`fs`) 3 | const { join } = require(`path`) 4 | const { renderToString, renderToStaticMarkup } = require(`react-dom/server`) 5 | const { ServerLocation, Router, isRedirect } = require(`@reach/router`) 6 | const { 7 | get, 8 | merge, 9 | isObject, 10 | flatten, 11 | uniqBy, 12 | flattenDeep, 13 | replace, 14 | concat, 15 | memoize, 16 | } = require(`lodash`) 17 | 18 | const { RouteAnnouncerProps } = require(`./route-announcer-props`) 19 | const apiRunner = require(`./api-runner-ssr`) 20 | const syncRequires = require(`./sync-requires`) 21 | const { version: gatsbyVersion } = require(`gatsby/package.json`) 22 | 23 | const stats = JSON.parse( 24 | fs.readFileSync(`${process.cwd()}/public/webpack.stats.json`, `utf-8`) 25 | ) 26 | 27 | const chunkMapping = JSON.parse( 28 | fs.readFileSync(`${process.cwd()}/public/chunk-map.json`, `utf-8`) 29 | ) 30 | 31 | // const testRequireError = require("./test-require-error") 32 | // For some extremely mysterious reason, webpack adds the above module *after* 33 | // this module so that when this code runs, testRequireError is undefined. 34 | // So in the meantime, we'll just inline it. 35 | const testRequireError = (moduleName, err) => { 36 | const regex = new RegExp(`Error: Cannot find module\\s.${moduleName}`) 37 | const firstLine = err.toString().split(`\n`)[0] 38 | return regex.test(firstLine) 39 | } 40 | 41 | let Html 42 | try { 43 | Html = require(`../src/html`) 44 | } catch (err) { 45 | if (testRequireError(`../src/html`, err)) { 46 | Html = require(`./default-html`) 47 | } else { 48 | throw err 49 | } 50 | } 51 | 52 | Html = Html && Html.__esModule ? Html.default : Html 53 | 54 | const getPageDataPath = path => { 55 | const fixedPagePath = path === `/` ? `index` : path 56 | return join(`page-data`, fixedPagePath, `page-data.json`) 57 | } 58 | 59 | const getPageDataUrl = pagePath => { 60 | const pageDataPath = getPageDataPath(pagePath) 61 | return `${__PATH_PREFIX__}/${pageDataPath}` 62 | } 63 | 64 | const getPageData = pagePath => { 65 | const pageDataPath = getPageDataPath(pagePath) 66 | const absolutePageDataPath = join(process.cwd(), `public`, pageDataPath) 67 | const pageDataRaw = fs.readFileSync(absolutePageDataPath) 68 | 69 | try { 70 | return JSON.parse(pageDataRaw.toString()) 71 | } catch (err) { 72 | return null 73 | } 74 | } 75 | 76 | const appDataPath = join(`page-data`, `app-data.json`) 77 | 78 | const getAppDataUrl = memoize(() => { 79 | let appData 80 | 81 | try { 82 | const absoluteAppDataPath = join(process.cwd(), `public`, appDataPath) 83 | const appDataRaw = fs.readFileSync(absoluteAppDataPath) 84 | appData = JSON.parse(appDataRaw.toString()) 85 | 86 | if (!appData) { 87 | return null 88 | } 89 | } catch (err) { 90 | return null 91 | } 92 | 93 | return `${__PATH_PREFIX__}/${appDataPath}` 94 | }) 95 | 96 | const loadPageDataSync = pagePath => { 97 | const pageDataPath = getPageDataPath(pagePath) 98 | const pageDataFile = join(process.cwd(), `public`, pageDataPath) 99 | try { 100 | const pageDataJson = fs.readFileSync(pageDataFile) 101 | return JSON.parse(pageDataJson) 102 | } catch (error) { 103 | // not an error if file is not found. There's just no page data 104 | return null 105 | } 106 | } 107 | 108 | const createElement = React.createElement 109 | 110 | export const sanitizeComponents = components => { 111 | const componentsArray = ensureArray(components) 112 | return componentsArray.map(component => { 113 | // Ensure manifest is always loaded from content server 114 | // And not asset server when an assetPrefix is used 115 | if (__ASSET_PREFIX__ && component.props.rel === `manifest`) { 116 | return React.cloneElement(component, { 117 | href: replace(component.props.href, __ASSET_PREFIX__, ``), 118 | }) 119 | } 120 | return component 121 | }) 122 | } 123 | 124 | const ensureArray = components => { 125 | if (Array.isArray(components)) { 126 | // remove falsy items and flatten 127 | return flattenDeep( 128 | components.filter(val => (Array.isArray(val) ? val.length > 0 : val)) 129 | ) 130 | } else { 131 | // we also accept single components, so we need to handle this case as well 132 | return components ? [components] : [] 133 | } 134 | } 135 | 136 | export default (pagePath, callback) => { 137 | let bodyHtml = `` 138 | let headComponents = [ 139 | , 144 | ] 145 | let htmlAttributes = {} 146 | let bodyAttributes = {} 147 | let preBodyComponents = [] 148 | let postBodyComponents = [] 149 | let bodyProps = {} 150 | 151 | const replaceBodyHTMLString = body => { 152 | bodyHtml = body 153 | } 154 | 155 | const setHeadComponents = components => { 156 | headComponents = headComponents.concat(sanitizeComponents(components)) 157 | } 158 | 159 | const setHtmlAttributes = attributes => { 160 | htmlAttributes = merge(htmlAttributes, attributes) 161 | } 162 | 163 | const setBodyAttributes = attributes => { 164 | bodyAttributes = merge(bodyAttributes, attributes) 165 | } 166 | 167 | const setPreBodyComponents = components => { 168 | preBodyComponents = preBodyComponents.concat(sanitizeComponents(components)) 169 | } 170 | 171 | const setPostBodyComponents = components => { 172 | postBodyComponents = postBodyComponents.concat( 173 | sanitizeComponents(components) 174 | ) 175 | } 176 | 177 | const setBodyProps = props => { 178 | bodyProps = merge({}, bodyProps, props) 179 | } 180 | 181 | const getHeadComponents = () => headComponents 182 | 183 | const replaceHeadComponents = components => { 184 | headComponents = sanitizeComponents(components) 185 | } 186 | 187 | const getPreBodyComponents = () => preBodyComponents 188 | 189 | const replacePreBodyComponents = components => { 190 | preBodyComponents = sanitizeComponents(components) 191 | } 192 | 193 | const getPostBodyComponents = () => postBodyComponents 194 | 195 | const replacePostBodyComponents = components => { 196 | postBodyComponents = sanitizeComponents(components) 197 | } 198 | 199 | const pageData = getPageData(pagePath) 200 | const pageDataUrl = getPageDataUrl(pagePath) 201 | 202 | const appDataUrl = getAppDataUrl() 203 | 204 | const { componentChunkName } = pageData 205 | 206 | class RouteHandler extends React.Component { 207 | render() { 208 | const props = { 209 | ...this.props, 210 | ...pageData.result, 211 | // pathContext was deprecated in v2. Renamed to pageContext 212 | pathContext: pageData.result ? pageData.result.pageContext : undefined, 213 | } 214 | 215 | const pageElement = createElement( 216 | syncRequires.components[componentChunkName], 217 | props 218 | ) 219 | 220 | const wrappedPage = apiRunner( 221 | `wrapPageElement`, 222 | { element: pageElement, props }, 223 | pageElement, 224 | ({ result }) => { 225 | return { element: result, props } 226 | } 227 | ).pop() 228 | 229 | return wrappedPage 230 | } 231 | } 232 | 233 | const routerElement = ( 234 | 235 | 236 | 237 | 238 |
239 | 240 | ) 241 | 242 | const bodyComponent = apiRunner( 243 | `wrapRootElement`, 244 | { element: routerElement, pathname: pagePath }, 245 | routerElement, 246 | ({ result }) => { 247 | return { element: result, pathname: pagePath } 248 | } 249 | ).pop() 250 | 251 | // Let the site or plugin render the page component. 252 | apiRunner(`replaceRenderer`, { 253 | bodyComponent, 254 | replaceBodyHTMLString, 255 | setHeadComponents, 256 | setHtmlAttributes, 257 | setBodyAttributes, 258 | setPreBodyComponents, 259 | setPostBodyComponents, 260 | setBodyProps, 261 | pathname: pagePath, 262 | pathPrefix: __PATH_PREFIX__, 263 | }) 264 | 265 | // If no one stepped up, we'll handle it. 266 | if (!bodyHtml) { 267 | try { 268 | bodyHtml = renderToString(bodyComponent) 269 | } catch (e) { 270 | // ignore @reach/router redirect errors 271 | if (!isRedirect(e)) throw e 272 | } 273 | } 274 | 275 | // Create paths to scripts 276 | let scriptsAndStyles = flatten( 277 | [`app`, componentChunkName].map(s => { 278 | const fetchKey = `assetsByChunkName[${s}]` 279 | 280 | let chunks = get(stats, fetchKey) 281 | const namedChunkGroups = get(stats, `namedChunkGroups`) 282 | 283 | if (!chunks) { 284 | return null 285 | } 286 | 287 | chunks = chunks.map(chunk => { 288 | if (chunk === `/`) { 289 | return null 290 | } 291 | return { rel: `preload`, name: chunk } 292 | }) 293 | 294 | namedChunkGroups[s].assets.forEach(asset => 295 | chunks.push({ rel: `preload`, name: asset }) 296 | ) 297 | 298 | const childAssets = namedChunkGroups[s].childAssets 299 | for (const rel in childAssets) { 300 | chunks = concat( 301 | chunks, 302 | childAssets[rel].map(chunk => { 303 | return { rel, name: chunk } 304 | }) 305 | ) 306 | } 307 | 308 | return chunks 309 | }) 310 | ) 311 | .filter(s => isObject(s)) 312 | .sort((s1, s2) => (s1.rel == `preload` ? -1 : 1)) // given priority to preload 313 | 314 | scriptsAndStyles = uniqBy(scriptsAndStyles, item => item.name) 315 | 316 | const scripts = scriptsAndStyles.filter( 317 | script => script.name && script.name.endsWith(`.js`) 318 | ) 319 | const styles = scriptsAndStyles.filter( 320 | style => style.name && style.name.endsWith(`.css`) 321 | ) 322 | 323 | apiRunner(`onRenderBody`, { 324 | setHeadComponents, 325 | setHtmlAttributes, 326 | setBodyAttributes, 327 | setPreBodyComponents, 328 | setPostBodyComponents, 329 | setBodyProps, 330 | pathname: pagePath, 331 | loadPageDataSync, 332 | bodyHtml, 333 | scripts, 334 | styles, 335 | pathPrefix: __PATH_PREFIX__, 336 | }) 337 | 338 | scripts 339 | .slice(0) 340 | .reverse() 341 | .forEach(script => { 342 | // Add preload/prefetch s for scripts. 343 | headComponents.push( 344 | 350 | ) 351 | }) 352 | 353 | if (pageData) { 354 | headComponents.push( 355 | 362 | ) 363 | } 364 | if (appDataUrl) { 365 | headComponents.push( 366 | 373 | ) 374 | } 375 | 376 | styles 377 | .slice(0) 378 | .reverse() 379 | .forEach(style => { 380 | // Add s for styles that should be prefetched 381 | // otherwise, inline as a