├── .editorconfig ├── .eslintignore ├── .eslintrc.json ├── .gitignore ├── .prettierrc ├── README.md ├── examples └── gatsby-plugin-graphql-component-default-example │ ├── .gitignore │ ├── .prettierignore │ ├── LICENSE │ ├── README.md │ ├── content │ ├── assets │ │ ├── gatsby-icon.png │ │ └── profile-pic.jpg │ └── blog │ │ ├── hello-world │ │ ├── index.md │ │ └── salty_egg.jpg │ │ ├── my-second-post │ │ └── index.md │ │ └── new-beginnings │ │ └── index.md │ ├── gatsby-browser.js │ ├── gatsby-config.js │ ├── gatsby-node.js │ ├── package.json │ ├── src │ ├── components │ │ ├── bio.js │ │ ├── layout.js │ │ ├── seo.js │ │ └── tester.js │ ├── pages │ │ ├── 404.js │ │ ├── index.tsx │ │ ├── page.js │ │ ├── static-hook.js │ │ └── static.js │ ├── templates │ │ └── blog-post.js │ └── utils │ │ └── typography.js │ ├── static │ ├── favicon.ico │ └── robots.txt │ └── yarn.lock ├── lerna.json ├── package.json ├── packages └── gatsby-plugin-graphql-component │ ├── LICENSE │ ├── README.md │ ├── gatsby-browser.js │ ├── gatsby-node.js │ ├── gatsby-ssr.js │ ├── index.js │ ├── output.js │ ├── package.json │ ├── static-query-babel-plugin.js │ ├── transform.js │ └── visitor.js └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | indent_size = 2 8 | indent_style = space 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | max_line_length = 120 12 | 13 | [*.md] 14 | trim_trailing_whitespace = false 15 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | **/*.min.js 2 | **/*.build.js 3 | **/node_modules/** 4 | **/vendor/** 5 | build 6 | coverage 7 | cypress 8 | node_modules 9 | vendor -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": [ 4 | "google", 5 | "eslint:recommended", 6 | "plugin:flowtype/recommended", 7 | "plugin:react/recommended", 8 | "prettier", 9 | "prettier/flowtype", 10 | "prettier/react" 11 | ], 12 | "plugins": ["flowtype", "prettier", "react", "filenames"], 13 | "parserOptions": { 14 | "ecmaVersion": 2016, 15 | "sourceType": "module", 16 | "ecmaFeatures": { 17 | "jsx": true 18 | } 19 | }, 20 | "env": { 21 | "browser": true, 22 | "es6": true, 23 | "node": true, 24 | "jest": true 25 | }, 26 | "globals": { 27 | "before": true, 28 | "after": true, 29 | "spyOn": true, 30 | "__PATH_PREFIX__": true, 31 | "__BASE_PATH__": true, 32 | "__ASSET_PREFIX__": true 33 | }, 34 | "rules": { 35 | "arrow-body-style": ["error", "as-needed", { "requireReturnForObjectLiteral": true }], 36 | "no-unused-expressions": [ 37 | "error", 38 | { 39 | "allowTaggedTemplates": true 40 | } 41 | ], 42 | "consistent-return": ["error"], 43 | "filenames/match-regex": ["error", "^[a-z-\\d\\.]+$", true], 44 | "no-console": "off", 45 | "no-inner-declarations": "off", 46 | "prettier/prettier": "error", 47 | "quotes": ["error", "backtick"], 48 | "react/display-name": "off", 49 | "react/jsx-key": "warn", 50 | "react/no-unescaped-entities": "off", 51 | "react/prop-types": "off", 52 | "require-jsdoc": "off", 53 | "valid-jsdoc": "off" 54 | }, 55 | "overrides": [ 56 | { 57 | "files": ["packages/**/gatsby-browser.js", "packages/gatsby/cache-dir/**/*"], 58 | "env": { 59 | "browser": true 60 | }, 61 | "globals": { 62 | "___loader": false, 63 | "___emitter": false 64 | } 65 | }, 66 | { 67 | "files": ["**/cypress/integration/**/*", "**/cypress/support/**/*"], 68 | "globals": { 69 | "cy": false, 70 | "Cypress": false 71 | } 72 | } 73 | ], 74 | "settings": { 75 | "react": { 76 | "version": "16.4.2" 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "endOfLine": "lf", 3 | "semi": false, 4 | "singleQuote": false, 5 | "tabWidth": 2, 6 | "trailingComma": "es5" 7 | } 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | packages/gatsby-plugin-graphql-component/README.md -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # dotenv environment variable files 55 | .env* 56 | 57 | # gatsby files 58 | .cache/ 59 | public 60 | 61 | # Mac files 62 | .DS_Store 63 | 64 | # Yarn 65 | yarn-error.log 66 | .pnp/ 67 | .pnp.js 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/.prettierignore: -------------------------------------------------------------------------------- 1 | .cache 2 | package.json 3 | package-lock.json 4 | public 5 | -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Gatsbyjs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/README.md: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | Gatsby 5 | 6 |

7 |

8 | Gatsby's blog starter 9 |

10 | 11 | Kick off your project with this blog boilerplate. This starter ships with the main Gatsby configuration files you might need to get up and running blazing fast with the blazing fast app generator for React. 12 | 13 | _Have another more specific idea? You may want to check out our vibrant collection of [official and community-created starters](https://www.gatsbyjs.org/docs/gatsby-starters/)._ 14 | 15 | ## 🚀 Quick start 16 | 17 | 1. **Create a Gatsby site.** 18 | 19 | Use the Gatsby CLI to create a new site, specifying the blog starter. 20 | 21 | ```shell 22 | # create a new Gatsby site using the blog starter 23 | gatsby new my-blog-starter https://github.com/gatsbyjs/gatsby-starter-blog 24 | ``` 25 | 26 | 1. **Start developing.** 27 | 28 | Navigate into your new site’s directory and start it up. 29 | 30 | ```shell 31 | cd my-blog-starter/ 32 | gatsby develop 33 | ``` 34 | 35 | 1. **Open the source code and start editing!** 36 | 37 | Your site is now running at `http://localhost:8000`! 38 | 39 | _Note: You'll also see a second link: _`http://localhost:8000/___graphql`_. This is a tool you can use to experiment with querying your data. Learn more about using this tool in the [Gatsby tutorial](https://www.gatsbyjs.org/tutorial/part-five/#introducing-graphiql)._ 40 | 41 | Open the `my-blog-starter` directory in your code editor of choice and edit `src/pages/index.js`. Save your changes and the browser will update in real time! 42 | 43 | ## 🧐 What's inside? 44 | 45 | A quick look at the top-level files and directories you'll see in a Gatsby project. 46 | 47 | . 48 | ├── node_modules 49 | ├── src 50 | ├── .gitignore 51 | ├── .prettierrc 52 | ├── gatsby-browser.js 53 | ├── gatsby-config.js 54 | ├── gatsby-node.js 55 | ├── gatsby-ssr.js 56 | ├── LICENSE 57 | ├── package-lock.json 58 | ├── package.json 59 | └── README.md 60 | 61 | 1. **`/node_modules`**: This directory contains all of the modules of code that your project depends on (npm packages) are automatically installed. 62 | 63 | 2. **`/src`**: This directory will contain all of the code related to what you will see on the front-end of your site (what you see in the browser) such as your site header or a page template. `src` is a convention for “source code”. 64 | 65 | 3. **`.gitignore`**: This file tells git which files it should not track / not maintain a version history for. 66 | 67 | 4. **`.prettierrc`**: This is a configuration file for [Prettier](https://prettier.io/). Prettier is a tool to help keep the formatting of your code consistent. 68 | 69 | 5. **`gatsby-browser.js`**: This file is where Gatsby expects to find any usage of the [Gatsby browser APIs](https://www.gatsbyjs.org/docs/browser-apis/) (if any). These allow customization/extension of default Gatsby settings affecting the browser. 70 | 71 | 6. **`gatsby-config.js`**: This is the main configuration file for a Gatsby site. This is where you can specify information about your site (metadata) like the site title and description, which Gatsby plugins you’d like to include, etc. (Check out the [config docs](https://www.gatsbyjs.org/docs/gatsby-config/) for more detail). 72 | 73 | 7. **`gatsby-node.js`**: This file is where Gatsby expects to find any usage of the [Gatsby Node APIs](https://www.gatsbyjs.org/docs/node-apis/) (if any). These allow customization/extension of default Gatsby settings affecting pieces of the site build process. 74 | 75 | 8. **`gatsby-ssr.js`**: This file is where Gatsby expects to find any usage of the [Gatsby server-side rendering APIs](https://www.gatsbyjs.org/docs/ssr-apis/) (if any). These allow customization of default Gatsby settings affecting server-side rendering. 76 | 77 | 9. **`LICENSE`**: Gatsby is licensed under the MIT license. 78 | 79 | 10. **`package-lock.json`** (See `package.json` below, first). This is an automatically generated file based on the exact versions of your npm dependencies that were installed for your project. **(You won’t change this file directly).** 80 | 81 | 11. **`package.json`**: A manifest file for Node.js projects, which includes things like metadata (the project’s name, author, etc). This manifest is how npm knows which packages to install for your project. 82 | 83 | 12. **`README.md`**: A text file containing useful reference information about your project. 84 | 85 | ## 🎓 Learning Gatsby 86 | 87 | Looking for more guidance? Full documentation for Gatsby lives [on the website](https://www.gatsbyjs.org/). Here are some places to start: 88 | 89 | - **For most developers, we recommend starting with our [in-depth tutorial for creating a site with Gatsby](https://www.gatsbyjs.org/tutorial/).** It starts with zero assumptions about your level of ability and walks through every step of the process. 90 | 91 | - **To dive straight into code samples, head [to our documentation](https://www.gatsbyjs.org/docs/).** In particular, check out the _Guides_, _API Reference_, and _Advanced Tutorials_ sections in the sidebar. 92 | 93 | ## 💫 Deploy 94 | 95 | [![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/gatsbyjs/gatsby-starter-blog) 96 | 97 | [![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/gatsbyjs/gatsby-starter-blog) 98 | 99 | 100 | -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/content/assets/gatsby-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pristas-peter/gatsby-plugin-graphql-component/8c51bc1bfc7aafda1eed84393113184baef2958f/examples/gatsby-plugin-graphql-component-default-example/content/assets/gatsby-icon.png -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/content/assets/profile-pic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pristas-peter/gatsby-plugin-graphql-component/8c51bc1bfc7aafda1eed84393113184baef2958f/examples/gatsby-plugin-graphql-component-default-example/content/assets/profile-pic.jpg -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/content/blog/hello-world/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Hello World 3 | date: "2015-05-01T22:12:03.284Z" 4 | description: "Hello World" 5 | --- 6 | 7 | This is my first post on my new fake blog! How exciting! 8 | 9 | I'm sure I'll write a lot more interesting things in the future. 10 | 11 | Oh, and here's a great quote from this Wikipedia on 12 | [salted duck eggs](https://en.wikipedia.org/wiki/Salted_duck_egg). 13 | 14 | > A salted duck egg is a Chinese preserved food product made by soaking duck 15 | > eggs in brine, or packing each egg in damp, salted charcoal. In Asian 16 | > supermarkets, these eggs are sometimes sold covered in a thick layer of salted 17 | > charcoal paste. The eggs may also be sold with the salted paste removed, 18 | > wrapped in plastic, and vacuum packed. From the salt curing process, the 19 | > salted duck eggs have a briny aroma, a gelatin-like egg white and a 20 | > firm-textured, round yolk that is bright orange-red in color. 21 | 22 | ![Chinese Salty Egg](./salty_egg.jpg) 23 | -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/content/blog/hello-world/salty_egg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pristas-peter/gatsby-plugin-graphql-component/8c51bc1bfc7aafda1eed84393113184baef2958f/examples/gatsby-plugin-graphql-component-default-example/content/blog/hello-world/salty_egg.jpg -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/content/blog/my-second-post/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: My Second Post! 3 | date: "2015-05-06T23:46:37.121Z" 4 | --- 5 | 6 | Wow! I love blogging so much already. 7 | 8 | Did you know that "despite its name, salted duck eggs can also be made from 9 | chicken eggs, though the taste and texture will be somewhat different, and the 10 | egg yolk will be less rich."? 11 | ([Wikipedia Link](https://en.wikipedia.org/wiki/Salted_duck_egg)) 12 | 13 | Yeah, I didn't either. 14 | -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/content/blog/new-beginnings/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: New Beginnings 3 | date: "2015-05-28T22:40:32.169Z" 4 | description: This is a custom description for SEO and Open Graph purposes, rather than the default generated excerpt. Simply add a description field to the frontmatter. 5 | --- 6 | 7 | Far far away, behind the word mountains, far from the countries Vokalia and 8 | Consonantia, there live the blind texts. Separated they live in Bookmarksgrove 9 | right at the coast of the Semantics, a large language ocean. A small river named 10 | Duden flows by their place and supplies it with the necessary regelialia. 11 | 12 | ## On deer horse aboard tritely yikes and much 13 | 14 | The Big Oxmox advised her not to do so, because there were thousands of bad 15 | Commas, wild Question Marks and devious Semikoli, but the Little Blind Text 16 | didn’t listen. She packed her seven versalia, put her initial into the belt and 17 | made herself on the way. 18 | 19 | - This however showed weasel 20 | - Well uncritical so misled 21 | - this is very interesting 22 | - Goodness much until that fluid owl 23 | 24 | When she reached the first hills of the **Italic Mountains**, she had a last 25 | view back on the skyline of her hometown _Bookmarksgrove_, the headline of 26 | [Alphabet Village](http://google.com) and the subline of her own road, the Line 27 | Lane. Pityful a rhetoric question ran over her cheek, then she continued her 28 | way. On her way she met a copy. 29 | 30 | ### Overlaid the jeepers uselessly much excluding 31 | 32 | But nothing the copy said could convince her and so it didn’t take long until a 33 | few insidious Copy Writers ambushed her, made her drunk with 34 | [Longe and Parole](http://google.com) and dragged her into their agency, where 35 | they abused her for their projects again and again. And if she hasn’t been 36 | rewritten, then they are still using her. 37 | 38 | > Far far away, behind the word mountains, far from the countries Vokalia and 39 | > Consonantia, there live the blind texts. Separated they live in Bookmarksgrove 40 | > right at the coast of the Semantics, a large language ocean. 41 | 42 | It is a paradisematic country, in which roasted parts of sentences fly into your 43 | mouth. Even the all-powerful Pointing has no control about the blind texts it is 44 | an almost unorthographic life One day however a small line of blind text by the 45 | name of Lorem Ipsum decided to leave for the far World of Grammar. 46 | 47 | ### According a funnily until pre-set or arrogant well cheerful 48 | 49 | The Big Oxmox advised her not to do so, because there were thousands of bad 50 | Commas, wild Question Marks and devious Semikoli, but the Little Blind Text 51 | didn’t listen. She packed her seven versalia, put her initial into the belt and 52 | made herself on the way. 53 | 54 | 1. So baboon this 55 | 2. Mounted militant weasel gregariously admonishingly straightly hey 56 | 3. Dear foresaw hungry and much some overhung 57 | 4. Rash opossum less because less some amid besides yikes jeepers frenetic 58 | impassive fruitlessly shut 59 | 60 | When she reached the first hills of the Italic Mountains, she had a last view 61 | back on the skyline of her hometown Bookmarksgrove, the headline of Alphabet 62 | Village and the subline of her own road, the Line Lane. Pityful a rhetoric 63 | question ran over her cheek, then she continued her way. On her way she met a 64 | copy. 65 | 66 | > The copy warned the Little Blind Text, that where it came from it would have 67 | > been rewritten a thousand times and everything that was left from its origin 68 | > would be the word "and" and the Little Blind Text should turn around and 69 | > return to its own, safe country. 70 | 71 | But nothing the copy said could convince her and so it didn’t take long until a 72 | few insidious Copy Writers ambushed her, made her drunk with Longe and Parole 73 | and dragged her into their agency, where they abused her for their projects 74 | again and again. And if she hasn’t been rewritten, then they are still using 75 | her. Far far away, behind the word mountains, far from the countries Vokalia and 76 | Consonantia, there live the blind texts. 77 | 78 | #### Silent delightfully including because before one up barring chameleon 79 | 80 | Separated they live in Bookmarksgrove right at the coast of the Semantics, a 81 | large language ocean. A small river named Duden flows by their place and 82 | supplies it with the necessary regelialia. It is a paradisematic country, in 83 | which roasted parts of sentences fly into your mouth. 84 | 85 | Even the all-powerful Pointing has no control about the blind texts it is an 86 | almost unorthographic life One day however a small line of blind text by the 87 | name of Lorem Ipsum decided to leave for the far World of Grammar. The Big Oxmox 88 | advised her not to do so, because there were thousands of bad Commas, wild 89 | Question Marks and devious Semikoli, but the Little Blind Text didn’t listen. 90 | 91 | ##### Wherever far wow thus a squirrel raccoon jeez jaguar this from along 92 | 93 | She packed her seven versalia, put her initial into the belt and made herself on 94 | the way. When she reached the first hills of the Italic Mountains, she had a 95 | last view back on the skyline of her hometown Bookmarksgrove, the headline of 96 | Alphabet Village and the subline of her own road, the Line Lane. Pityful a 97 | rhetoric question ran over her cheek, then she continued her way. On her way she 98 | met a copy. 99 | 100 | ###### Slapped cozy a that lightheartedly and far 101 | 102 | The copy warned the Little Blind Text, that where it came from it would have 103 | been rewritten a thousand times and everything that was left from its origin 104 | would be the word "and" and the Little Blind Text should turn around and return 105 | to its own, safe country. But nothing the copy said could convince her and so it 106 | didn’t take long until a few insidious Copy Writers ambushed her, made her drunk 107 | with Longe and Parole and dragged her into their agency, where they abused her 108 | for their projects again and again. 109 | -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/gatsby-browser.js: -------------------------------------------------------------------------------- 1 | // custom typefaces 2 | import "typeface-montserrat" 3 | import "typeface-merriweather" 4 | 5 | import "prismjs/themes/prism.css" 6 | -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/gatsby-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | siteMetadata: { 3 | title: `Gatsby Starter Blog`, 4 | author: { 5 | name: `Kyle Mathews`, 6 | summary: `who lives and works in San Francisco building useful things.`, 7 | }, 8 | description: `A starter blog demonstrating what Gatsby can do.`, 9 | siteUrl: `https://gatsby-starter-blog-demo.netlify.com/`, 10 | social: { 11 | twitter: `kylemathews`, 12 | }, 13 | }, 14 | plugins: [ 15 | { 16 | resolve: `gatsby-source-filesystem`, 17 | options: { 18 | path: `${__dirname}/content/blog`, 19 | name: `blog`, 20 | }, 21 | }, 22 | { 23 | resolve: `gatsby-source-filesystem`, 24 | options: { 25 | path: `${__dirname}/content/assets`, 26 | name: `assets`, 27 | }, 28 | }, 29 | { 30 | resolve: `gatsby-transformer-remark`, 31 | options: { 32 | plugins: [ 33 | { 34 | resolve: `gatsby-remark-images`, 35 | options: { 36 | maxWidth: 590, 37 | }, 38 | }, 39 | { 40 | resolve: `gatsby-remark-responsive-iframe`, 41 | options: { 42 | wrapperStyle: `margin-bottom: 1.0725rem`, 43 | }, 44 | }, 45 | `gatsby-remark-prismjs`, 46 | `gatsby-remark-copy-linked-files`, 47 | `gatsby-remark-smartypants`, 48 | ], 49 | }, 50 | }, 51 | `gatsby-transformer-sharp`, 52 | `gatsby-plugin-sharp`, 53 | { 54 | resolve: `gatsby-plugin-google-analytics`, 55 | options: { 56 | //trackingId: `ADD YOUR TRACKING ID HERE`, 57 | }, 58 | }, 59 | `gatsby-plugin-feed`, 60 | { 61 | resolve: `gatsby-plugin-manifest`, 62 | options: { 63 | name: `Gatsby Starter Blog`, 64 | short_name: `GatsbyJS`, 65 | start_url: `/`, 66 | background_color: `#ffffff`, 67 | theme_color: `#663399`, 68 | display: `minimal-ui`, 69 | icon: `content/assets/gatsby-icon.png`, 70 | }, 71 | }, 72 | `gatsby-plugin-react-helmet`, 73 | { 74 | resolve: `gatsby-plugin-typography`, 75 | options: { 76 | pathToConfigModule: `src/utils/typography`, 77 | }, 78 | }, 79 | `gatsby-plugin-graphql-component`, 80 | // this (optional) plugin enables Progressive Web App + Offline functionality 81 | // To learn more, visit: https://gatsby.dev/offline 82 | // `gatsby-plugin-offline`, 83 | ], 84 | } 85 | -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/gatsby-node.js: -------------------------------------------------------------------------------- 1 | const path = require(`path`) 2 | const { createFilePath } = require(`gatsby-source-filesystem`) 3 | const { registerComponent, createResolverField } = require(`gatsby-plugin-graphql-component`) 4 | 5 | exports.createPages = async ({ graphql, actions }) => { 6 | const { createPage } = actions 7 | 8 | const blogPost = path.resolve(`./src/templates/blog-post.js`) 9 | const result = await graphql( 10 | ` 11 | { 12 | allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }, limit: 1000) { 13 | edges { 14 | node { 15 | fields { 16 | slug 17 | } 18 | frontmatter { 19 | title 20 | } 21 | } 22 | } 23 | } 24 | } 25 | ` 26 | ) 27 | 28 | if (result.errors) { 29 | throw result.errors 30 | } 31 | 32 | // Create blog posts pages. 33 | const posts = result.data.allMarkdownRemark.edges 34 | 35 | posts.forEach((post, index) => { 36 | const previous = index === posts.length - 1 ? null : posts[index + 1].node 37 | const next = index === 0 ? null : posts[index - 1].node 38 | 39 | createPage({ 40 | path: post.node.fields.slug, 41 | component: blogPost, 42 | context: { 43 | slug: post.node.fields.slug, 44 | previous, 45 | next, 46 | }, 47 | }) 48 | }) 49 | } 50 | 51 | exports.onCreateNode = ({ node, actions, getNode }) => { 52 | const { createNodeField } = actions 53 | 54 | if (node.internal.type === `MarkdownRemark`) { 55 | const value = createFilePath({ node, getNode }) 56 | createNodeField({ 57 | name: `slug`, 58 | node, 59 | value, 60 | }) 61 | } 62 | } 63 | 64 | let id = null 65 | 66 | exports.sourceNodes = async ({ actions }) => { 67 | id = await registerComponent({ 68 | component: require.resolve(`./src/components/tester`), 69 | }) 70 | } 71 | 72 | exports.createResolvers = ({ createResolvers }) => { 73 | const resolvers = { 74 | Query: { 75 | Tester: createResolverField({ 76 | resolve: async () => id, 77 | }), 78 | }, 79 | } 80 | createResolvers(resolvers) 81 | } 82 | -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatsby-plugin-graphql-component-default-example", 3 | "private": true, 4 | "description": "A starter for a blog powered by Gatsby and Markdown", 5 | "version": "0.1.0", 6 | "author": "Kyle Mathews ", 7 | "bugs": { 8 | "url": "https://github.com/gatsbyjs/gatsby/issues" 9 | }, 10 | "dependencies": { 11 | "gatsby": "^2.21.13", 12 | "gatsby-image": "^2.4.1", 13 | "gatsby-plugin-feed": "^2.5.1", 14 | "gatsby-plugin-google-analytics": "^2.3.1", 15 | "gatsby-plugin-manifest": "^2.4.2", 16 | "gatsby-plugin-offline": "^3.2.1", 17 | "gatsby-plugin-react-helmet": "^3.3.1", 18 | "gatsby-plugin-sharp": "^2.6.1", 19 | "gatsby-plugin-typography": "^2.5.1", 20 | "gatsby-remark-copy-linked-files": "^2.3.2", 21 | "gatsby-remark-images": "^3.3.1", 22 | "gatsby-remark-prismjs": "^3.5.1", 23 | "gatsby-remark-responsive-iframe": "^2.4.2", 24 | "gatsby-remark-smartypants": "^2.3.1", 25 | "gatsby-source-filesystem": "^2.3.1", 26 | "gatsby-transformer-remark": "^2.8.6", 27 | "gatsby-transformer-sharp": "^2.5.1", 28 | "prismjs": "^1.20.0", 29 | "react": "^16.12.0", 30 | "react-dom": "^16.12.0", 31 | "react-helmet": "^5.2.1", 32 | "react-typography": "^0.16.19", 33 | "typeface-merriweather": "0.0.72", 34 | "typeface-montserrat": "0.0.75", 35 | "typography": "^0.16.19", 36 | "typography-theme-wordpress-2016": "^0.16.19" 37 | }, 38 | "devDependencies": { 39 | "prettier": "2.0.5" 40 | }, 41 | "homepage": "https://github.com/gatsbyjs/gatsby-starter-blog#readme", 42 | "keywords": [ 43 | "gatsby" 44 | ], 45 | "license": "MIT", 46 | "main": "n/a", 47 | "repository": { 48 | "type": "git", 49 | "url": "git+https://github.com/gatsbyjs/gatsby-starter-blog.git" 50 | }, 51 | "scripts": { 52 | "build": "gatsby build", 53 | "develop": "gatsby develop", 54 | "format": "prettier --write \"**/*.{js,jsx,json,md}\"", 55 | "start": "npm run develop", 56 | "serve": "gatsby serve", 57 | "clean": "gatsby clean", 58 | "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/src/components/bio.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Bio component that queries for data 3 | * with Gatsby's useStaticQuery component 4 | * 5 | * See: https://www.gatsbyjs.org/docs/use-static-query/ 6 | */ 7 | 8 | import React from "react" 9 | import { useStaticQuery, graphql } from "gatsby" 10 | import Image from "gatsby-image" 11 | 12 | import { rhythm } from "../utils/typography" 13 | 14 | const Bio = () => { 15 | const data = useStaticQuery(graphql` 16 | query BioQuery { 17 | avatar: file(absolutePath: { regex: "/profile-pic.jpg/" }) { 18 | childImageSharp { 19 | fixed(width: 50, height: 50) { 20 | ...GatsbyImageSharpFixed 21 | } 22 | } 23 | } 24 | site { 25 | siteMetadata { 26 | author { 27 | name 28 | summary 29 | } 30 | social { 31 | twitter 32 | } 33 | } 34 | } 35 | } 36 | `) 37 | 38 | const { author, social } = data.site.siteMetadata 39 | return ( 40 |
46 | {author.name} 59 |

60 | Written by {author.name} {author.summary} 61 | {` `} 62 | 63 | You should follow him on Twitter 64 | 65 |

66 |
67 | ) 68 | } 69 | 70 | export default Bio 71 | -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/src/components/layout.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Link } from "gatsby" 3 | 4 | import { rhythm, scale } from "../utils/typography" 5 | 6 | const Layout = ({ location, title, children }) => { 7 | const rootPath = `${__PATH_PREFIX__}/` 8 | let header 9 | 10 | if (location.pathname === rootPath) { 11 | header = ( 12 |

19 | 26 | {title} 27 | 28 |

29 | ) 30 | } else { 31 | header = ( 32 |

38 | 45 | {title} 46 | 47 |

48 | ) 49 | } 50 | return ( 51 |
59 |
{header}
60 |
{children}
61 |
62 | © {new Date().getFullYear()}, Built with 63 | {` `} 64 | Gatsby 65 |
66 |
67 | ) 68 | } 69 | 70 | export default Layout 71 | -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/src/components/seo.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SEO component that queries for data with 3 | * Gatsby's useStaticQuery React hook 4 | * 5 | * See: https://www.gatsbyjs.org/docs/use-static-query/ 6 | */ 7 | 8 | import React from "react" 9 | import PropTypes from "prop-types" 10 | import Helmet from "react-helmet" 11 | import { useStaticQuery, graphql } from "gatsby" 12 | 13 | const SEO = ({ description, lang, meta, title }) => { 14 | const { site } = useStaticQuery( 15 | graphql` 16 | query { 17 | site { 18 | siteMetadata { 19 | title 20 | description 21 | social { 22 | twitter 23 | } 24 | } 25 | } 26 | } 27 | ` 28 | ) 29 | 30 | const metaDescription = description || site.siteMetadata.description 31 | 32 | return ( 33 | 74 | ) 75 | } 76 | 77 | SEO.defaultProps = { 78 | lang: `en`, 79 | meta: [], 80 | description: ``, 81 | } 82 | 83 | SEO.propTypes = { 84 | description: PropTypes.string, 85 | lang: PropTypes.string, 86 | meta: PropTypes.arrayOf(PropTypes.object), 87 | title: PropTypes.string.isRequired, 88 | } 89 | 90 | export default SEO 91 | -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/src/components/tester.js: -------------------------------------------------------------------------------- 1 | export default () => `Testeros` 2 | -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/src/pages/404.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { graphql } from "gatsby" 3 | 4 | import Layout from "../components/layout" 5 | import SEO from "../components/seo" 6 | 7 | const NotFoundPage = ({ data, location }) => { 8 | const siteTitle = data.site.siteMetadata.title 9 | 10 | return ( 11 | 12 | 13 |

Not Found

14 |

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

15 |
16 | ) 17 | } 18 | 19 | export default NotFoundPage 20 | 21 | export const pageQuery = graphql` 22 | query { 23 | site { 24 | siteMetadata { 25 | title 26 | } 27 | } 28 | } 29 | ` 30 | -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | // Gatsby supports TypeScript natively! 2 | import React from "react" 3 | import { PageProps, Link, graphql } from "gatsby" 4 | 5 | import Bio from "../components/bio" 6 | import Layout from "../components/layout" 7 | import SEO from "../components/seo" 8 | import { rhythm } from "../utils/typography" 9 | 10 | type Data = { 11 | site: { 12 | siteMetadata: { 13 | title: string 14 | } 15 | } 16 | allMarkdownRemark: { 17 | edges: { 18 | node: { 19 | excerpt: string 20 | frontmatter: { 21 | title: string 22 | date: string 23 | description: string 24 | } 25 | fields: { 26 | slug: string 27 | } 28 | } 29 | }[] 30 | } 31 | } 32 | 33 | const BlogIndex = ({ data, location }: PageProps) => { 34 | const siteTitle = data.site.siteMetadata.title 35 | const posts = data.allMarkdownRemark.edges 36 | 37 | return ( 38 | 39 | 40 | 41 | {posts.map(({ node }) => { 42 | const title = node.frontmatter.title || node.fields.slug 43 | return ( 44 |
45 |
46 |

51 | 52 | {title} 53 | 54 |

55 | {node.frontmatter.date} 56 |
57 |
58 |

63 |

64 |
65 | ) 66 | })} 67 |
68 | ) 69 | } 70 | 71 | export default BlogIndex 72 | 73 | export const pageQuery = graphql` 74 | query { 75 | site { 76 | siteMetadata { 77 | title 78 | } 79 | } 80 | allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }) { 81 | edges { 82 | node { 83 | excerpt 84 | fields { 85 | slug 86 | } 87 | frontmatter { 88 | date(formatString: "MMMM DD, YYYY") 89 | title 90 | description 91 | } 92 | } 93 | } 94 | } 95 | } 96 | ` 97 | -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/src/pages/page.js: -------------------------------------------------------------------------------- 1 | import { graphql, Link } from "gatsby" 2 | import React from "react" 3 | export const pageQuery = graphql` 4 | query { 5 | Tester 6 | allSitePage { 7 | edges { 8 | node { 9 | id 10 | } 11 | } 12 | } 13 | } 14 | ` 15 | 16 | export default props => { 17 | const { Tester } = props.data 18 | 19 | console.log(props.data) 20 | 21 | return ( 22 | <> 23 | Test Page 24 | Test

25 | 26 | 27 | ) 28 | } 29 | -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/src/pages/static-hook.js: -------------------------------------------------------------------------------- 1 | import { graphql, useStaticQuery } from "gatsby" 2 | import React from "react" 3 | 4 | export default props => { 5 | const data = useStaticQuery(graphql` 6 | query { 7 | Tester 8 | allSitePage { 9 | edges { 10 | node { 11 | id 12 | } 13 | } 14 | } 15 | } 16 | `) 17 | 18 | console.log({ data }) 19 | 20 | return 21 | } 22 | -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/src/pages/static.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { StaticQuery, graphql } from "gatsby" 3 | 4 | export default props => ( 5 | 19 | {data => { 20 | return 21 | }} 22 | 23 | ) 24 | -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/src/templates/blog-post.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Link, graphql } from "gatsby" 3 | 4 | import Bio from "../components/bio" 5 | import Layout from "../components/layout" 6 | import SEO from "../components/seo" 7 | import { rhythm, scale } from "../utils/typography" 8 | 9 | const BlogPostTemplate = ({ data, pageContext, location }) => { 10 | const post = data.markdownRemark 11 | const siteTitle = data.site.siteMetadata.title 12 | const { previous, next } = pageContext 13 | 14 | return ( 15 | 16 | 20 |
21 |
22 |

28 | {post.frontmatter.title} 29 |

30 |

37 | {post.frontmatter.date} 38 |

39 |
40 |
41 |
46 |
47 | 48 |
49 |
50 | 51 | 77 |
78 | ) 79 | } 80 | 81 | export default BlogPostTemplate 82 | 83 | export const pageQuery = graphql` 84 | query BlogPostBySlug($slug: String!) { 85 | site { 86 | siteMetadata { 87 | title 88 | } 89 | } 90 | markdownRemark(fields: { slug: { eq: $slug } }) { 91 | id 92 | excerpt(pruneLength: 160) 93 | html 94 | frontmatter { 95 | title 96 | date(formatString: "MMMM DD, YYYY") 97 | description 98 | } 99 | } 100 | } 101 | ` 102 | -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/src/utils/typography.js: -------------------------------------------------------------------------------- 1 | import Typography from "typography" 2 | import Wordpress2016 from "typography-theme-wordpress-2016" 3 | 4 | Wordpress2016.overrideThemeStyles = () => { 5 | return { 6 | "a.gatsby-resp-image-link": { 7 | boxShadow: `none`, 8 | }, 9 | } 10 | } 11 | 12 | delete Wordpress2016.googleFonts 13 | 14 | const typography = new Typography(Wordpress2016) 15 | 16 | // Hot reload typography in development. 17 | if (process.env.NODE_ENV !== `production`) { 18 | typography.injectStyles() 19 | } 20 | 21 | export default typography 22 | export const rhythm = typography.rhythm 23 | export const scale = typography.scale 24 | -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pristas-peter/gatsby-plugin-graphql-component/8c51bc1bfc7aafda1eed84393113184baef2958f/examples/gatsby-plugin-graphql-component-default-example/static/favicon.ico -------------------------------------------------------------------------------- /examples/gatsby-plugin-graphql-component-default-example/static/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | "packages/*" 4 | ], 5 | "version": "0.2.4" 6 | } 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "workspaces": [ 4 | "examples/*", 5 | "packages/*" 6 | ], 7 | "dependencies": { 8 | "lerna": "^3.20.2" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/gatsby-plugin-graphql-component/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 pristas-peter 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/gatsby-plugin-graphql-component/README.md: -------------------------------------------------------------------------------- 1 | # gatsby-plugin-graphql-component 2 | 3 | This plugin alows you to register any React component file with the build system and query them via Gatsby's GraphQL queries. 4 | 5 | ## Example usage 6 | 7 | - using pageQuery 8 | 9 | ```js 10 | // src/pages/test.js 11 | import { graphql, Link } from "gatsby" 12 | import React from "react" 13 | export const pageQuery = graphql` 14 | query { 15 | Tester 16 | allSitePage { 17 | edges { 18 | node { 19 | id 20 | } 21 | } 22 | } 23 | } 24 | ` 25 | export default (props) => { 26 | const { Tester } = props.data 27 | 28 | return 29 | } 30 | ``` 31 | 32 | - using `useStaticQuery` hook 33 | 34 | ```js 35 | // src/components/test.js 36 | import { graphql, useStaticQuery } from "gatsby" 37 | import React from "react" 38 | export default (props) => { 39 | const { Tester } = useStaticQuery(graphql` 40 | query { 41 | Tester 42 | allSitePage { 43 | edges { 44 | node { 45 | id 46 | } 47 | } 48 | } 49 | } 50 | `) 51 | return 52 | } 53 | ``` 54 | 55 | - using `` component 56 | 57 | ```js 58 | // src/components/test.js 59 | import React from "react" 60 | import { StaticQuery, graphql } from "gatsby" 61 | export default (props) => ( 62 | 69 | {(data) => { 70 | return 71 | }} 72 | 73 | ) 74 | ``` 75 | 76 | ## Installation 77 | 78 | ```shell 79 | npm i gatsby-plugin-graphql-component 80 | ``` 81 | 82 | After installing `gatsby-plugin-graphql-component` you can add it to your plugins list in your 83 | `gatsby-config.js`. 84 | 85 | ```js 86 | module.exports = { 87 | plugins: [ 88 | // ... 89 | `gatsby-plugin-graphql-component`, 90 | ], 91 | } 92 | ``` 93 | 94 | ## Usage for plugin creators 95 | 96 | The component file needs to be registered with the plugin by creating a `Component` node. The plugin exports a `createComponentNode` function which you should call during the `sourceNodes` build phase. As a side effect, the component is added to the webpack's build. Then you can extend the schema with `createResolverField` function during the `createResolvers` which will enable the component in the queries. 97 | 98 | ```js 99 | const { registerComponent, createResolverField } = require(`gatsby-plugin-graphql-component`) 100 | 101 | exports.sourceNodes = async ({actions: {createNode}) => { 102 | 103 | const id = await registerComponent({ 104 | component: require.resolve(`./src/components/tester`) 105 | }) 106 | 107 | // store this id somewhere for later (preferably in the sourced node as a field when using `createNode` or `createNodeField`) 108 | } 109 | 110 | exports.createResolvers = ({ createResolvers }) => { 111 | const resolvers = { 112 | Query: { 113 | // create Tester field on root Query which using the `createResolverField` helper function 114 | // it takes resolve as an argument which is an async function which should return the id returned from `registerComponent` 115 | Tester: createResolverField({ resolve: async (source, args, context, info) => source.idReturnedFromRegisterComponent }), 116 | }, 117 | } 118 | createResolvers(resolvers) 119 | } 120 | ``` 121 | 122 | ## Supported features 123 | 124 | - server side rendering 125 | - hot reloading 126 | - query refreshing during development 127 | 128 | ## How is bundle size affected 129 | 130 | Each individual component is treated in its own webpack chunk, similar as pages are, so only the components which are included in the queries, are loaded on initial page bootstrap alongside with the page data. 131 | 132 | ## License 133 | 134 | MIT 135 | -------------------------------------------------------------------------------- /packages/gatsby-plugin-graphql-component/gatsby-browser.js: -------------------------------------------------------------------------------- 1 | import { components } from "~gatsby-plugin-graphql-component/async-requires" 2 | import { transform } from "./transform" 3 | 4 | // on client entry is called almost as a first lifecycle 5 | export const onClientEntry = async () => { 6 | // this code patches "development" mode 7 | if (process.env.NODE_ENV !== `production`) { 8 | // require is used so the 9 | // requires can be be removed during production build 10 | const { default: socketIo } = require(`~gatsby-plugin-graphql-component-gatsby-cache/socketIo`) 11 | const syncRequires = require(`~gatsby-plugin-graphql-component/sync-requires`) 12 | const { transformSync } = require(`./transform`) 13 | 14 | const emitter = window.___emitter 15 | 16 | const onResult = ({ result }) => { 17 | if (result) { 18 | Object.assign( 19 | result, 20 | transformSync({ 21 | json: result, 22 | load: ({ componentChunkName }) => syncRequires.components[componentChunkName] 23 | }) 24 | ) 25 | } 26 | } 27 | 28 | // emmitter emits new results on page / static query queries, 29 | // we will patch the response with components 30 | emitter.on(`staticQueryResult`, onResult) 31 | emitter.on(`pageQueryResult`, onResult) 32 | 33 | // we need to initialize socketIo, because core initializes it after this call, 34 | // but it needs to be initilized when calling loadPage later in the code 35 | socketIo() 36 | } 37 | 38 | const loader = window.___loader 39 | 40 | const { loadPage } = loader 41 | 42 | const cache = new WeakMap() 43 | 44 | // patch query json result in loadPage 45 | loader.loadPage = async (...args) => { 46 | const result = await loadPage(...args) 47 | 48 | if (cache.has(result)) { 49 | return result 50 | } 51 | 52 | if (result && result.json && result.json.data) { 53 | result.json.data = await transform({ 54 | json: result.json.data, 55 | load: ({ componentChunkName }) => { 56 | return components[componentChunkName]() 57 | } 58 | }) 59 | 60 | cache.set(result, true) 61 | } 62 | 63 | return result 64 | } 65 | 66 | // call loader public method before gatsby core calls underlying private method later after this lifecycle 67 | // therefore our patched method would not be called 68 | // network calls are reused in loader internally, so the page won't be loaded twice 69 | // all other code in core uses this public method, so we should be safe 70 | return loader.loadPage(window.location.pathname) 71 | } 72 | -------------------------------------------------------------------------------- /packages/gatsby-plugin-graphql-component/gatsby-node.js: -------------------------------------------------------------------------------- 1 | const path = require(`path`) 2 | const fs = require(`fs-extra`) 3 | 4 | const { GraphQLJSONObject } = require(`graphql-type-json`) 5 | const { visitor } = require(`./visitor`) 6 | 7 | const { setActions, setStore } = require(`./index`) 8 | const { ensureWriteDirectory, writeFile } = require(`./output`) 9 | 10 | exports.onPreBootstrap = async ({ actions, store }) => { 11 | setActions({ actions }) 12 | setStore({ store }) 13 | } 14 | 15 | exports.createSchemaCustomization = ({ actions, schema }) => { 16 | const { createTypes } = actions 17 | 18 | createTypes([ 19 | schema.buildScalarType({ 20 | name: `GraphQLComponent`, 21 | description: `React component available through GraphQL`, 22 | serialize: GraphQLJSONObject.serialize, 23 | parseValue: GraphQLJSONObject.parseValue, 24 | parseLiteral: GraphQLJSONObject.parseLiteral 25 | }), 26 | schema.buildObjectType({ 27 | name: `GraphQLComponentSource`, 28 | description: `React component node`, 29 | fields: { 30 | componentPath: `String!`, 31 | componentChunkName: `String!`, 32 | componentName: `String!` 33 | }, 34 | interfaces: [`Node`] 35 | }) 36 | ]) 37 | } 38 | 39 | exports.createPages = async ({ getNodesByType, store }) => { 40 | const { directory } = store.getState().program 41 | const writeDirectory = await ensureWriteDirectory({ baseDirectory: directory }) 42 | 43 | const nodes = getNodesByType(`GraphQLComponentSource`) 44 | 45 | // Create file with sync requires of components/json files. 46 | let syncRequires = ` 47 | // prefer default export if available 48 | const preferDefault = m => m && m.default || m 49 | \n\n` 50 | syncRequires += `exports.components = {\n${nodes 51 | .map(node => ` "${node.componentChunkName}": preferDefault(require("${node.componentPath}"))`) 52 | .join(`,\n`)} 53 | }\n\n` 54 | 55 | const asyncRequires = `// prefer default export if available 56 | 57 | const preferDefault = m => m && m.default || m 58 | exports.components = {\n${nodes 59 | .map(node => { 60 | return ` "${node.componentChunkName}": () => import("${node.componentPath}" /* webpackChunkName: "${node.componentChunkName}" */).then(preferDefault)` 61 | }) 62 | .join(`,\n`)} 63 | }\n\n` 64 | 65 | await Promise.all([ 66 | writeFile({ 67 | filePath: path.join(writeDirectory, `sync-requires.js`), 68 | data: syncRequires 69 | }), 70 | writeFile({ 71 | filePath: path.join(writeDirectory, `async-requires.js`), 72 | data: asyncRequires 73 | }) 74 | ]) 75 | } 76 | 77 | exports.onPreBuild = async ({ store }) => { 78 | if (process.env.NODE_ENV === `production`) { 79 | const staticQueries = {} 80 | 81 | const promises = [] 82 | 83 | const { directory } = store.getState().program 84 | const writeDirectory = await ensureWriteDirectory({ baseDirectory: directory }) 85 | 86 | store.getState().staticQueryComponents.forEach(value => { 87 | promises.push( 88 | new Promise((resolve, reject) => { 89 | fs.readFile(path.join(directory, `public`, `page-data`, `sq`, `d`, `${value.hash}.json`), `utf-8`) 90 | .then(data => { 91 | const result = JSON.parse(data) 92 | 93 | const definitions = [] 94 | 95 | visitor({ 96 | json: result, 97 | onDefinition: ({ definition }) => { 98 | definitions.push(definition) 99 | } 100 | }) 101 | 102 | if (definitions.length) { 103 | const source = ` 104 | ${definitions.map(({ componentName, componentPath }) => `import ${componentName} from "${componentPath}"`).join(`\n`)} 105 | import { transformSync } from "gatsby-plugin-graphql-component/transform" 106 | 107 | const map = { 108 | ${definitions.map(({ componentName }) => `${componentName}`).join(`,`)} 109 | } 110 | 111 | const cache = new WeakMap() 112 | 113 | export default (data) => { 114 | const cached = cache.get(data) 115 | 116 | if (cached) { 117 | return cached 118 | } 119 | 120 | const transformed = transformSync({json: data, load: ({componentName}) => { 121 | return map[componentName] 122 | }}) 123 | 124 | cache.set(data, transformed) 125 | 126 | return transformed 127 | }` 128 | const filename = `static-query-${value.hash}.js` 129 | 130 | return fs.writeFile(path.join(writeDirectory, filename), source).then(() => { 131 | staticQueries[value.componentPath] = { 132 | ...value, 133 | result, 134 | importPath: `~gatsby-plugin-graphql-component/${filename}` 135 | } 136 | }) 137 | } 138 | 139 | return null 140 | }) 141 | .then(resolve) 142 | .catch(reject) 143 | }) 144 | ) 145 | }) 146 | 147 | await Promise.all(promises) 148 | await fs.writeFile(path.join(writeDirectory, `static-queries.json`), JSON.stringify(staticQueries, null, 2)) 149 | } 150 | } 151 | 152 | exports.onCreateBabelConfig = async ({ actions, store }) => { 153 | const { directory } = store.getState().program 154 | const writeDirectory = await ensureWriteDirectory({ baseDirectory: directory }) 155 | 156 | actions.setBabelPlugin({ 157 | name: require.resolve(`./static-query-babel-plugin`), 158 | options: { 159 | staticQueriesPath: path.join(writeDirectory, `static-queries.json`) 160 | } 161 | }) 162 | } 163 | 164 | exports.onCreateWebpackConfig = async ({ store, actions }) => { 165 | const { directory } = store.getState().program 166 | const writeDirectory = await ensureWriteDirectory({ baseDirectory: directory }) 167 | 168 | actions.setWebpackConfig({ 169 | resolve: { 170 | alias: { 171 | "~gatsby-plugin-graphql-component-gatsby-cache": path.join(directory, `.cache`), 172 | "~gatsby-plugin-graphql-component": writeDirectory 173 | } 174 | } 175 | }) 176 | } 177 | -------------------------------------------------------------------------------- /packages/gatsby-plugin-graphql-component/gatsby-ssr.js: -------------------------------------------------------------------------------- 1 | import { components } from "~gatsby-plugin-graphql-component/sync-requires" 2 | import { cloneElement } from "react" 3 | import React from "react" 4 | import { transformSync } from "./transform" 5 | 6 | const componentChunkNamesByPage = {} 7 | 8 | // this is a suitable lifecycle method during ssr when we can patch raw query data 9 | export const wrapPageElement = ({ element, props }) => { 10 | const componentChunkNames = new Set() 11 | 12 | const data = transformSync({ 13 | json: props.data, 14 | load: ({ componentChunkName }) => { 15 | componentChunkNames.add(componentChunkName) 16 | return components[componentChunkName] 17 | } 18 | }) 19 | 20 | componentChunkNamesByPage[props.location.pathname] = componentChunkNames 21 | 22 | return cloneElement(element, { 23 | ...props, 24 | data 25 | }) 26 | } 27 | 28 | export const onRenderBody = ({ pathname, pathPrefix, setHeadComponents }) => { 29 | if (process.env.NODE_ENV === `production`) { 30 | const path = __non_webpack_require__(`path`) 31 | const { cwd } = __non_webpack_require__(`process`) 32 | 33 | const chunkMap = __non_webpack_require__(path.join(cwd(), `public`, `chunk-map.json`)) 34 | 35 | componentChunkNamesByPage[pathname].forEach(componentChunkName => { 36 | chunkMap[componentChunkName] 37 | .filter(asset => asset.endsWith(`.js`)) 38 | .forEach(asset => { 39 | setHeadComponents([]) 40 | }) 41 | }) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/gatsby-plugin-graphql-component/index.js: -------------------------------------------------------------------------------- 1 | const _ = require(`lodash`) 2 | const path = require(`path`) 3 | const { generateComponentChunkName } = require(`gatsby/dist/utils/js-chunk-names`) 4 | const { createContentDigest } = require(`gatsby-core-utils`) 5 | const { createNodeId } = require(`gatsby/dist/utils/create-node-id`) 6 | const { name } = require(`./package.json`) 7 | const { ensureWriteDirectory, writeFile } = require(`./output`) 8 | const fs = require(`fs-extra`) 9 | const pascalCase = _.flow(_.camelCase, _.upperFirst) 10 | 11 | let actions 12 | let store 13 | 14 | exports.setActions = options => { 15 | actions = options.actions 16 | } 17 | 18 | exports.setStore = options => { 19 | store = options.store 20 | } 21 | 22 | /** 23 | * Creates Component Node and which as a side effect registers the component into webpack's build 24 | */ 25 | exports.registerComponent = async ({ component }) => { 26 | const writeDirectory = await ensureWriteDirectory({ 27 | baseDirectory: store.getState().program.directory, 28 | paths: [`components`] 29 | }) 30 | 31 | const id = createNodeId(`graphql-component-source-${component}`, name) 32 | const componentPath = path.join(writeDirectory, `${id}.js`) 33 | 34 | // TODO: Remove all "hot" references in this `syncRequires` variable when fast-refresh is the default 35 | const hotImport = 36 | process.env.GATSBY_HOT_LOADER !== `fast-refresh` ? `const { hot } = require("react-hot-loader/root")` : `` 37 | const hotMethod = process.env.GATSBY_HOT_LOADER !== `fast-refresh` ? `hot` : `` 38 | 39 | await writeFile({ 40 | filePath: componentPath, 41 | data: ` 42 | ${hotImport} 43 | import Component from "${component}" 44 | 45 | export default ${hotMethod}(Component) 46 | ` 47 | }) 48 | 49 | const node = { 50 | id, 51 | component, 52 | componentPath, 53 | componentName: `Component${pascalCase(component)}`, 54 | componentChunkName: generateComponentChunkName(component), 55 | internal: { 56 | type: `GraphQLComponentSource` 57 | } 58 | } 59 | 60 | node.internal.contentDigest = createContentDigest(JSON.stringify(node)) 61 | 62 | actions.createNode(node) 63 | 64 | return id 65 | } 66 | 67 | /** 68 | * Helper function to create resolver field which returns the previously registered component 69 | */ 70 | exports.createResolverField = ({ resolve }) => { 71 | return { 72 | type: `GraphQLComponent`, 73 | async resolve(source, args, context, info) { 74 | const node = await context.nodeModel.runQuery({ 75 | query: { 76 | filter: { 77 | id: { 78 | eq: await resolve(source, args, context, info) 79 | } 80 | } 81 | }, 82 | type: `GraphQLComponentSource`, 83 | firstOnly: true 84 | }) 85 | 86 | if (process.env.NODE_ENV !== `production`) { 87 | const date = new Date() 88 | await fs.utimes(__filename, date, date) 89 | } 90 | 91 | return node 92 | ? { 93 | ___graphQLComponent: { 94 | componentChunkName: node.componentChunkName, 95 | componentPath: node.componentPath, 96 | componentName: node.componentName 97 | } 98 | } 99 | : null 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /packages/gatsby-plugin-graphql-component/output.js: -------------------------------------------------------------------------------- 1 | const path = require(`path`) 2 | const fs = require(`fs-extra`) 3 | 4 | const { name } = require(`./package.json`) 5 | 6 | exports.ensureWriteDirectory = async ({ baseDirectory, paths = [] }) => { 7 | const writeDirectory = path.join(baseDirectory, `.cache`, name, ...paths) 8 | await fs.mkdirp(writeDirectory) 9 | 10 | return writeDirectory 11 | } 12 | 13 | // writes file to disk only on change/new file (avoids unnecessary rebuilds) 14 | exports.writeFile = async ({ filePath, data }) => { 15 | const oldData = await fs.readFile(filePath, `utf-8`).catch(() => null) 16 | 17 | if (oldData !== data) { 18 | await fs.outputFile(filePath, data) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/gatsby-plugin-graphql-component/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatsby-plugin-graphql-component", 3 | "version": "0.2.4", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "dependencies": { 7 | "fs-extra": "^9.0.1", 8 | "graphql-type-json": "^0.3.1", 9 | "jsonfile": "^6.0.1", 10 | "lodash": "^4.17.15" 11 | }, 12 | "description": "Query React Components in Gatsby GraphQL queries", 13 | "author": "Peter Pristas ", 14 | "bugs": { 15 | "url": "https://github.com/pristas-peter/gatsby-plugin-graphql-component/issues" 16 | }, 17 | "keywords": [ 18 | "gatsby", 19 | "gatsby-plugin", 20 | "components", 21 | "graphql", 22 | "graphql-query-components" 23 | ], 24 | "peerDependencies": { 25 | "gatsby": ">2.23.0" 26 | }, 27 | "repository": { 28 | "type": "git", 29 | "url": "https://github.com/pristas-peter/gatsby-plugin-graphql-component.git" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/gatsby-plugin-graphql-component/static-query-babel-plugin.js: -------------------------------------------------------------------------------- 1 | module.exports = function({ types: t }) { 2 | return { 3 | visitor: { 4 | Program(path, state) { 5 | if (process.env.NODE_ENV === `production`) { 6 | const staticQueries = require(state.opts.staticQueriesPath) 7 | 8 | const definition = staticQueries[state.filename] 9 | 10 | if (definition) { 11 | const identifier = t.identifier(`transformStaticQueryData`) 12 | 13 | const importDefaultSpecifier = t.importDefaultSpecifier(identifier) 14 | const importDeclaration = t.importDeclaration( 15 | [importDefaultSpecifier], 16 | t.stringLiteral(definition.importPath) 17 | ) 18 | path.unshiftContainer(`body`, importDeclaration) 19 | 20 | path.traverse({ 21 | Identifier(identifierPath) { 22 | if (identifierPath.node.name === `staticQueryData`) { 23 | if (identifierPath.parent.type === `MemberExpression`) { 24 | identifierPath.parentPath.replaceWith( 25 | t.callExpression(identifier, [t.identifier(identifierPath.parentPath.toString())]) 26 | ) 27 | } else if (identifierPath.parent.type === `JSXExpressionContainer`) { 28 | identifierPath.replaceWith(t.callExpression(identifier, [t.identifier(identifierPath.toString())])) 29 | } 30 | } 31 | }, 32 | }) 33 | } 34 | } 35 | }, 36 | }, 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/gatsby-plugin-graphql-component/transform.js: -------------------------------------------------------------------------------- 1 | import { visitor } from "./visitor" 2 | 3 | export const transform = ({ json = {}, load }) => { 4 | const promises = [] 5 | 6 | const newJson = visitor({ 7 | json, 8 | onDefinition: ({ definition, value, key }) => { 9 | promises.push( 10 | load(definition).then(component => { 11 | value[key] = component 12 | }) 13 | ) 14 | }, 15 | }) 16 | 17 | return Promise.all(promises).then(() => newJson) 18 | } 19 | 20 | export const transformSync = ({ json = {}, load }) => 21 | visitor({ 22 | json, 23 | onDefinition: ({ definition, value, key }) => { 24 | value[key] = load(definition) 25 | }, 26 | }) 27 | -------------------------------------------------------------------------------- /packages/gatsby-plugin-graphql-component/visitor.js: -------------------------------------------------------------------------------- 1 | exports.visitor = ({ json, onDefinition }) => 2 | JSON.parse(JSON.stringify(json), (_, value) => { 3 | if (value instanceof Object) { 4 | Object.keys(value).forEach(key => { 5 | if (value[key] instanceof Object && value[key].___graphQLComponent) { 6 | const definition = value[key].___graphQLComponent 7 | 8 | if (definition) { 9 | onDefinition({ definition, value, key }) 10 | } 11 | } 12 | }) 13 | } 14 | 15 | return value 16 | }) 17 | --------------------------------------------------------------------------------