├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .github
└── workflows
│ └── push-wp-gatsby-gutenberg.yml
├── .gitignore
├── .prettierrc.js
├── .vscode
└── launch.json
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── docs
├── .gitignore
├── .prettierignore
├── .prettierrc
├── README.md
├── content
│ ├── api
│ │ └── api.mdx
│ ├── contributing
│ │ └── contributing.mdx
│ ├── example
│ │ └── example.mdx
│ ├── features
│ │ ├── blocks.mdx
│ │ └── previews.mdx
│ ├── images
│ │ ├── author.png
│ │ ├── block-preview.gif
│ │ ├── gatsby-icon.png
│ │ └── page-preview.gif
│ ├── index.mdx
│ ├── installation
│ │ ├── images
│ │ │ └── quickstart
│ │ │ │ ├── 01-post.png
│ │ │ │ ├── 02-Blocks.png
│ │ │ │ ├── 03-Unknown.gif
│ │ │ │ ├── 03-Unknown.mov
│ │ │ │ ├── 04-Paragraph.png
│ │ │ │ ├── 05-Layout.gif
│ │ │ │ └── 05-Layout.mov
│ │ ├── installation.mdx
│ │ ├── packages.mdx
│ │ └── quickstart.mdx
│ └── overview
│ │ ├── sourcing.mdx
│ │ └── theme.mdx
├── gatsby-config.js
├── gatsby-node.js
├── package.json
├── src
│ ├── components
│ │ ├── style.css
│ │ └── universal-link.js
│ ├── gatsby-theme-apollo-core
│ │ └── components
│ │ │ └── logo.js
│ ├── gatsby-theme-apollo-docs
│ │ ├── assets
│ │ │ └── social-bg.jpg
│ │ └── components
│ │ │ ├── custom-seo.js
│ │ │ ├── header-button.js
│ │ │ ├── page-layout.js
│ │ │ └── social-card.js
│ └── images
│ │ └── gatsby-icon.png
└── yarn.lock
├── examples
└── gatsby-wordpress-gutenberg-default-example
│ ├── .gitignore
│ ├── README.md
│ ├── backend
│ ├── .gitignore
│ ├── docker-compose.xdebug.yml
│ ├── docker-compose.yml
│ ├── docker-entrypoint-initdb.d
│ │ └── 01-example.sql
│ └── wordpress
│ │ ├── composer.json
│ │ └── composer.lock
│ └── frontend
│ ├── .gitignore
│ ├── .prettierignore
│ ├── .prettierrc
│ ├── LICENSE
│ ├── README.md
│ ├── gatsby-browser.js
│ ├── gatsby-config.js
│ ├── gatsby-node.js
│ ├── gatsby-ssr.js
│ ├── package.json
│ ├── src
│ ├── components
│ │ ├── block.js
│ │ ├── header.js
│ │ ├── image.js
│ │ ├── layout.css
│ │ ├── layout.js
│ │ └── seo.js
│ ├── gatsby-theme-wordpress-gutenberg
│ │ └── components
│ │ │ ├── blocks
│ │ │ └── core
│ │ │ │ ├── column.js
│ │ │ │ ├── columns.js
│ │ │ │ └── paragraph.js
│ │ │ └── unknown-block.js
│ ├── images
│ │ ├── gatsby-astronaut.png
│ │ └── gatsby-icon.png
│ ├── pages
│ │ ├── 404.js
│ │ ├── index.js
│ │ └── using-typescript.tsx
│ └── templates
│ │ └── blog-post.js
│ └── yarn.lock
├── lerna.json
├── netlify.toml
├── package.json
├── packages
└── gatsby-theme-wordpress-gutenberg
│ ├── README.md
│ ├── gatsby-config.js
│ ├── gatsby-node.js
│ ├── index.js
│ ├── package.json
│ └── src
│ └── components
│ ├── blocks
│ └── core
│ │ └── block.js
│ ├── previews
│ └── block-preview.js
│ └── unknown-block.js
├── plugins
└── wp-gatsby-gutenberg
│ ├── .eslintrc.js
│ ├── .prettierrc.js
│ ├── build
│ ├── 0.js
│ ├── 0.js.map
│ ├── index.asset.php
│ ├── index.js
│ └── index.js.map
│ ├── composer.json
│ ├── package-lock.json
│ ├── package.json
│ ├── phpcs.xml.dist
│ ├── plugin.php
│ ├── src
│ ├── Admin
│ │ ├── Editor.php
│ │ └── Settings.php
│ ├── Preview
│ │ ├── Preview.php
│ │ ├── gatsby-block-preview.js
│ │ ├── icon.js
│ │ └── preview.js
│ └── index.js
│ └── vendor
│ ├── autoload.php
│ └── composer
│ ├── ClassLoader.php
│ ├── LICENSE
│ ├── autoload_classmap.php
│ ├── autoload_namespaces.php
│ ├── autoload_psr4.php
│ ├── autoload_real.php
│ └── autoload_static.php
└── 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.js:
--------------------------------------------------------------------------------
1 | const TSEslint = require("@typescript-eslint/eslint-plugin")
2 |
3 | module.exports = {
4 | parser: "babel-eslint",
5 | extends: [
6 | "google",
7 | "eslint:recommended",
8 | "plugin:flowtype/recommended",
9 | "plugin:react/recommended",
10 | "prettier",
11 | "prettier/flowtype",
12 | "prettier/react"
13 | ],
14 | plugins: ["flowtype", "prettier", "react", "filenames"],
15 | parserOptions: {
16 | ecmaVersion: 2016,
17 | sourceType: "module",
18 | ecmaFeatures: {
19 | jsx: true
20 | }
21 | },
22 | env: {
23 | browser: true,
24 | es6: true,
25 | node: true,
26 | jest: true
27 | },
28 | globals: {
29 | before: true,
30 | after: true,
31 | spyOn: true,
32 | __PATH_PREFIX__: true,
33 | __BASE_PATH__: true,
34 | __ASSET_PREFIX__: true
35 | },
36 | rules: {
37 | "arrow-body-style": ["error", "as-needed", { requireReturnForObjectLiteral: true }],
38 | "no-unused-expressions": [
39 | "error",
40 | {
41 | allowTaggedTemplates: true
42 | }
43 | ],
44 | "consistent-return": ["error"],
45 | "filenames/match-regex": ["error", "^[a-z-\\d\\.]+$", true],
46 | "no-console": "off",
47 | "no-inner-declarations": "off",
48 | "prettier/prettier": "error",
49 | quotes: ["error", "backtick"],
50 | "react/display-name": "off",
51 | "react/jsx-key": "warn",
52 | "react/no-unescaped-entities": "off",
53 | "react/prop-types": "off",
54 | "require-jsdoc": "off",
55 | "valid-jsdoc": "off"
56 | },
57 | overrides: [
58 | {
59 | files: ["packages/**/gatsby-browser.js", "packages/gatsby/cache-dir/**/*"],
60 | env: {
61 | browser: true
62 | },
63 | globals: {
64 | ___loader: false,
65 | ___emitter: false
66 | }
67 | },
68 | {
69 | files: ["**/cypress/integration/**/*", "**/cypress/support/**/*"],
70 | globals: {
71 | cy: false,
72 | Cypress: false
73 | }
74 | },
75 | {
76 | files: ["www/**/*"],
77 | rules: {
78 | // We need to import React to use the Fragment shorthand (`<>`).
79 | // When we use theme-ui's JSX pragma, it lists React as an unused var
80 | // even though it's still needed.
81 | "no-unused-vars": ["error", { varsIgnorePattern: "React" }]
82 | }
83 | },
84 | {
85 | files: ["*.ts", "*.tsx"],
86 | parser: "@typescript-eslint/parser",
87 | plugins: ["@typescript-eslint/eslint-plugin"],
88 | rules: {
89 | ...TSEslint.configs.recommended.rules,
90 | // We should absolutely avoid using ts-ignore, but it's not always possible.
91 | // particular when a dependencies types are incorrect.
92 | "@typescript-eslint/ban-ts-ignore": "warn",
93 | // This rule is great. It helps us not throw on types for areas that are
94 | // easily inferrable. However we have a desire to have all function inputs
95 | // and outputs declaratively typed. So this let's us ignore the parameters
96 | // inferrable lint.
97 | "@typescript-eslint/no-inferrable-types": ["error", { ignoreParameters: true }],
98 | // This rule tries to ensure we use camelCase for all variables, properties
99 | // functions, etc. However, it is not always possible to ensure properties
100 | // are camelCase. Specifically we have `node.__gatsby_resolve` which breaks
101 | // this rule. This allows properties to be whatever they need to be.
102 | "@typescript-eslint/camelcase": ["error", { properties: "never" }],
103 | // This rule tries to prevent using `require()`. However in node code,
104 | // there are times where this makes sense. And it specifically is causing
105 | // problems in our tests where we often want this functionality for module
106 | // mocking. At this point it's easier to have it off and just encouarge
107 | // using top-level imports via code reviews.
108 | "@typescript-eslint/no-var-requires": "off",
109 | // This rule ensures that typescript types do not have semicolons
110 | // at the end of their lines, since our prettier setup is to have no semicolons
111 | // e.g.,
112 | // interface Foo {
113 | // - baz: string;
114 | // + baz: string
115 | // }
116 | "@typescript-eslint/member-delimiter-style": [
117 | "error",
118 | {
119 | multiline: {
120 | delimiter: "none"
121 | }
122 | }
123 | ],
124 | // This ensures all interfaces are named with an I as a prefix
125 | // e.g.,
126 | // interface IFoo {}
127 | "@typescript-eslint/interface-name-prefix": ["error", { prefixWithI: "always" }],
128 | "@typescript-eslint/no-empty-function": "off",
129 | // This ensures that we always type the return type of functions
130 | // a high level focus of our TS setup is typing fn inputs and outputs.
131 | "@typescript-eslint/explicit-function-return-type": "error",
132 | // This forces us to use interfaces over types aliases for object defintions.
133 | // Type is still useful for opaque types
134 | // e.g.,
135 | // type UUID = string
136 | "@typescript-eslint/consistent-type-definitions": ["error", "interface"],
137 | "@typescript-eslint/no-use-before-define": ["error", { functions: false }],
138 | // Allows us to write unions like `type Foo = "baz" | "bar"`
139 | // otherwise eslint will want to switch the strings to backticks,
140 | // which then crashes the ts compiler
141 | quotes: "off",
142 | "@typescript-eslint/quotes": [
143 | 2,
144 | "backtick",
145 | {
146 | avoidEscape: true
147 | }
148 | ],
149 | // bump to @typescript-eslint/parser started showing Flow related errors in ts(x) files
150 | // so disabling them in .ts(x) files
151 | "flowtype/no-types-missing-file-annotation": "off"
152 | }
153 | }
154 | ],
155 | settings: {
156 | react: {
157 | version: "16.4.2"
158 | }
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/.github/workflows/push-wp-gatsby-gutenberg.yml:
--------------------------------------------------------------------------------
1 | name: Push to wp-gatsby-gutenberg
2 | on:
3 | push:
4 | branches:
5 | - master # Push events on master branch
6 | jobs:
7 | publish:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - uses: actions/checkout@master
11 | - name: publish:wp-gatsby-gutenberg
12 | uses: s0/git-publish-subdir-action@master
13 | env:
14 | REPO: git@github.com:GatsbyWPGutenberg/wp-gatsby-gutenberg.git
15 | BRANCH: master
16 | FOLDER: plugins/wp-gatsby-gutenberg
17 | SSH_PRIVATE_KEY: ${{ secrets.WP_GATSBY_GUTENBERG_PRIVATE_KEY }}
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | .idea
9 |
10 | # Runtime data
11 | pids
12 | *.pid
13 | *.seed
14 | *.pid.lock
15 |
16 | # Directory for instrumented libs generated by jscoverage/JSCover
17 | lib-cov
18 |
19 | # Coverage directory used by tools like istanbul
20 | coverage
21 |
22 | # nyc test coverage
23 | .nyc_output
24 |
25 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
26 | .grunt
27 |
28 | # Bower dependency directory (https://bower.io/)
29 | bower_components
30 |
31 | # node-waf configuration
32 | .lock-wscript
33 |
34 | # Compiled binary addons (http://nodejs.org/api/addons.html)
35 | build/Release
36 |
37 | # Dependency directories
38 | node_modules/
39 | jspm_packages/
40 |
41 | # Typescript v1 declaration files
42 | typings/
43 |
44 | # Optional npm cache directory
45 | .npm
46 |
47 | # Optional eslint cache
48 | .eslintcache
49 |
50 | # Optional REPL history
51 | .node_repl_history
52 |
53 | # Output of 'npm pack'
54 | *.tgz
55 |
56 | # dotenv environment variable files
57 | .env*
58 |
59 | # Mac files
60 | .DS_Store
61 |
62 | # Yarn
63 | yarn-error.log
64 | .pnp/
65 | .pnp.js
66 | # Yarn Integrity file
67 | .yarn-integrity
68 |
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | arrowParens: "avoid",
3 | semi: false
4 | }
5 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "type": "node",
9 | "request": "launch",
10 | "name": "Gatsby build",
11 | "program": "${workspaceFolder}/node_modules/gatsby/dist/bin/gatsby",
12 | "args": ["build"],
13 | "cwd": "${workspaceFolder}/examples/gatsby-wordpress-gutenberg-default-example/frontend",
14 | "runtimeArgs": ["--nolazy"],
15 | "sourceMaps": false,
16 | "outputCapture": "std"
17 | },
18 |
19 | {
20 | "name": "Listen for Default Example XDebug",
21 | "type": "php",
22 | "request": "launch",
23 | "port": 9000,
24 | "pathMappings": {
25 | "/var/www/html": "${workspaceRoot}/examples/gatsby-wordpress-gutenberg-default-example/backend/wordpress",
26 | "/plugins": "${workspaceRoot}/plugins"
27 | }
28 | }
29 | ]
30 | }
31 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6 |
7 | ## Our Standards
8 |
9 | Examples of behavior that contributes to creating a positive environment include:
10 |
11 | * Using welcoming and inclusive language
12 | * Being respectful of differing viewpoints and experiences
13 | * Gracefully accepting constructive criticism
14 | * Focusing on what is best for the community
15 | * Showing empathy towards other community members
16 |
17 | Examples of unacceptable behavior by participants include:
18 |
19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances
20 | * Trolling, insulting/derogatory comments, and personal or political attacks
21 | * Public or private harassment
22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission
23 | * Other conduct which could reasonably be considered inappropriate in a professional setting
24 |
25 | ## Our Responsibilities
26 |
27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28 |
29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30 |
31 | ## Scope
32 |
33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34 |
35 | ## Enforcement
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at info@wpgraphql.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38 |
39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40 |
41 | ## Attribution
42 |
43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44 |
45 | [homepage]: http://contributor-covenant.org
46 | [version]: http://contributor-covenant.org/version/1/4/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GatsbyWPGutenberg
2 |
3 | This is a monorepo for the GatsbyWPGutenberg framework
4 |
5 | - Usage Docs
6 | - Join our community through WpGraphQL Slack
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/.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 |
--------------------------------------------------------------------------------
/docs/.prettierignore:
--------------------------------------------------------------------------------
1 | .cache
2 | package.json
3 | package-lock.json
4 | public
5 |
--------------------------------------------------------------------------------
/docs/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "endOfLine": "lf",
3 | "semi": false,
4 | "singleQuote": false,
5 | "tabWidth": 2,
6 | "trailingComma": "es5"
7 | }
8 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Gatsby's default starter
9 |
10 |
11 | Kick off your project with this default 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 default starter.
20 |
21 | ```shell
22 | # create a new Gatsby site using the default starter
23 | gatsby new my-default-starter https://github.com/gatsbyjs/gatsby-starter-default
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-default-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-default-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 | [](https://app.netlify.com/start/deploy?repository=https://github.com/gatsbyjs/gatsby-starter-default)
96 |
97 |
98 |
--------------------------------------------------------------------------------
/docs/content/api/api.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Reference
3 | ---
4 |
5 | > This is a stub. Help our community expand it.
6 |
--------------------------------------------------------------------------------
/docs/content/contributing/contributing.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: How to contribute
3 | ---
4 |
5 | > This is a stub. Help our community expand it.
6 |
--------------------------------------------------------------------------------
/docs/content/example/example.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Installation
3 | ---
4 |
5 | > This is a stub. Help our community expand it.
6 |
7 | You can find an example project with WordPress running in `docker` (backend) and configured Gatsby project (frontend).
8 |
9 | For more information follow the README in `/examples/gatsby-wordpress-gutenberg-default-example` inside [repo](https://github.com/GatsbyWPGutenberg/gatsby-wordpress-gutenberg/tree/develop/examples/gatsby-wordpress-gutenberg-default-example).
10 |
--------------------------------------------------------------------------------
/docs/content/features/blocks.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Block components
3 | description: Create your block component
4 | ---
5 |
6 | You can write your own custom block implementation for each block. Otherwise the default ` ` component is used which just displays the raw html output of the block.
7 |
8 | ## Example
9 |
10 | To create your own block component:
11 |
12 | - create a file with path `src/gatsby-theme-wordpress-gutenberg/components/blocks/[block-name].[ext]` which has the component as its default export
13 | - the file should contain a graphql fragment definition on the block's graphql type, where you can query for block fields, this fragment will be included when querying for `Blocks` component field
14 | - the `innerBlocks` components are passed in as the `children` prop
15 |
16 | > The components can be shadowed. That means if multiple themes or your project implement the same block, the last definition wins.
17 |
18 | For example for the default `core/quote` block, the file should be created as `src/gatsby-theme-wordpress-gutenberg/components/blocks/core/quote.js`:
19 |
20 | > Graphql typename for block type name is camelCased and uses Block suffix, for example: `core/quote` -> `WpCoreQuoteBlock`
21 |
22 | ```jsx
23 | import React from "react"
24 | import { graphql } from "gatsby"
25 |
26 | export const query = graphql`
27 | fragment Quote on WpCoreQuoteBlock {
28 | attributes {
29 | ... on WpCoreQuoteBlockAttributes {
30 | value
31 | }
32 | }
33 | }
34 | `
35 |
36 | export default ({ attributes }) => (
37 |
38 | This is a custom implementation of quote block
39 | My value is {attributes.value}
40 |
41 | )
42 | ```
43 |
--------------------------------------------------------------------------------
/docs/content/features/previews.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Previews
3 | ---
4 |
5 | To enable previews you either need a running instance of `gatsby develop` with ENABLE_GATSBY_REFRESH_ENDPOINT env variable enabled or a Preview instance running in `Gatsby Cloud`.
6 |
7 | > Check out the [official docs](https://www.gatsbyjs.org/docs/running-a-gatsby-preview-server/) on how tu run your preview instance
8 |
9 | ## Wordpress
10 |
11 | To be able to see previews in gutenberg, you need to install a plugin into Wordpress.
12 |
13 | ### wp-gatsby-gutenberg
14 |
15 | - Install the plugin manually, by downloading it from [here](https://github.com/GatsbyWPGutenberg/wp-gatsby-gutenberg/releases).
16 | - Install with [composer](https://packagist.org/packages/gatsby-wordpress-gutenberg/wp-gatsby-gutenberg)
17 |
18 | ```sh
19 | composer require gatsby-wordpress-gutenberg/wp-gatsby-gutenberg
20 | ```
21 |
22 | ## Setup
23 |
24 | The enable live previews in Gutenberg, follow these steps:
25 |
26 | - enable your preview instance through `Settings -> GatsbyJS`
27 | - enable previews in gutenberg in `Settings -> GatsbyJS Gutenberg`
28 |
29 | > You should see preview icon inside block's edit toolbar.
30 |
31 | 
32 |
33 | > Each time a block content is changed and the preview button is clicked, a new Gatsby Preview trigger is send. This means this will also count to your previews count when running on Gatsby Cloud.
34 |
35 | ## How does it work
36 |
37 | - `wp-graphql-gutenberg` saves the live changes in gutenberg in the database within custom post type, which has one to one relationship with the edited post
38 | - when clicking the block preview button (available when the option is enabled), the preview content is sourced by `gatsby-source-wordpress-experimental` and special preview page for that post type is created within `gatsby-theme-wordpress-gutenberg`
39 | - the page with the highlighted block is then displayed inside gutenberg within an iframe
40 |
--------------------------------------------------------------------------------
/docs/content/images/author.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GatsbyWPGutenberg/gatsby-wordpress-gutenberg/4bcd987b1a79f47849a7f3b97e2e0bbea673a022/docs/content/images/author.png
--------------------------------------------------------------------------------
/docs/content/images/block-preview.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GatsbyWPGutenberg/gatsby-wordpress-gutenberg/4bcd987b1a79f47849a7f3b97e2e0bbea673a022/docs/content/images/block-preview.gif
--------------------------------------------------------------------------------
/docs/content/images/gatsby-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GatsbyWPGutenberg/gatsby-wordpress-gutenberg/4bcd987b1a79f47849a7f3b97e2e0bbea673a022/docs/content/images/gatsby-icon.png
--------------------------------------------------------------------------------
/docs/content/images/page-preview.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GatsbyWPGutenberg/gatsby-wordpress-gutenberg/4bcd987b1a79f47849a7f3b97e2e0bbea673a022/docs/content/images/page-preview.gif
--------------------------------------------------------------------------------
/docs/content/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Introduction
3 | ---
4 |
5 | ## What is Gutenberg
6 |
7 | Gutenberg is the new default WordPress content editor. Gutenberg introduces a block based approach to editing that aims to makes it easier to work with media rich pages and posts.
8 |
9 | ## What is GatsbyWPGutenberg
10 |
11 | GatsbyWPGutenberg is a framework that makes it possible to work with Gutenberg blocks in Gatsby instead of using raw HTML content.
12 |
13 | In other words, you can use Gutenberg as a page builder for your Gatsby's content.
14 |
15 | ## Features
16 |
17 | - Render Gutenberg blocks with custom React components
18 | - Live preview in Gatsby and Gutenberg
19 | - Automatic React component generation based on post's content to keep bundle size small
20 |
21 | > Consider this software is still in beta.
22 |
23 | ## Main contributors
24 |
25 |
31 |
32 | > Hi, my name is Peter Pristas. I am a full stack developer from Slovakia. Check out my other open-source projects on [Github](https://github.com/pristas-peter), or my [LinkedIn](https://www.linkedin.com/in/peter-pristas/) profile.
33 |
--------------------------------------------------------------------------------
/docs/content/installation/images/quickstart/01-post.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GatsbyWPGutenberg/gatsby-wordpress-gutenberg/4bcd987b1a79f47849a7f3b97e2e0bbea673a022/docs/content/installation/images/quickstart/01-post.png
--------------------------------------------------------------------------------
/docs/content/installation/images/quickstart/02-Blocks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GatsbyWPGutenberg/gatsby-wordpress-gutenberg/4bcd987b1a79f47849a7f3b97e2e0bbea673a022/docs/content/installation/images/quickstart/02-Blocks.png
--------------------------------------------------------------------------------
/docs/content/installation/images/quickstart/03-Unknown.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GatsbyWPGutenberg/gatsby-wordpress-gutenberg/4bcd987b1a79f47849a7f3b97e2e0bbea673a022/docs/content/installation/images/quickstart/03-Unknown.gif
--------------------------------------------------------------------------------
/docs/content/installation/images/quickstart/03-Unknown.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GatsbyWPGutenberg/gatsby-wordpress-gutenberg/4bcd987b1a79f47849a7f3b97e2e0bbea673a022/docs/content/installation/images/quickstart/03-Unknown.mov
--------------------------------------------------------------------------------
/docs/content/installation/images/quickstart/04-Paragraph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GatsbyWPGutenberg/gatsby-wordpress-gutenberg/4bcd987b1a79f47849a7f3b97e2e0bbea673a022/docs/content/installation/images/quickstart/04-Paragraph.png
--------------------------------------------------------------------------------
/docs/content/installation/images/quickstart/05-Layout.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GatsbyWPGutenberg/gatsby-wordpress-gutenberg/4bcd987b1a79f47849a7f3b97e2e0bbea673a022/docs/content/installation/images/quickstart/05-Layout.gif
--------------------------------------------------------------------------------
/docs/content/installation/images/quickstart/05-Layout.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GatsbyWPGutenberg/gatsby-wordpress-gutenberg/4bcd987b1a79f47849a7f3b97e2e0bbea673a022/docs/content/installation/images/quickstart/05-Layout.mov
--------------------------------------------------------------------------------
/docs/content/installation/installation.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Installation
3 | description: How to install
4 | ---
5 |
6 | To get the core functionality you need to install plugins into Wordpress and npm packages into gatsby.
7 |
8 | ## Dependencies
9 |
10 | > The source plugin is based on the new `gatsby-source-wordpress-experimental` which uses `wp-graphql` under the hood.
11 |
12 | ### gatsby-source-wordpress-experimental
13 |
14 | Follow the instructions on the [plugin's repo](https://github.com/gatsbyjs/gatsby-source-wordpress-experimental).
15 |
16 | ## Gatsby
17 |
18 | - Install the theme with npm / yarn
19 |
20 | ```sh
21 | npm i gatsby-theme-wordpress-gutenberg
22 | # or
23 | yarn add gatsby-theme-wordpress-gutenberg
24 | ```
25 |
26 | - Setup theme in your `gatsby-config.js`:
27 |
28 | ```js
29 | module.exports = {
30 | // ...
31 | plugins: [
32 | // ... other plugins
33 | {
34 | resolve: `gatsby-source-wordpress-experimental`,
35 | options: {
36 | // configure according to plugin's instructions
37 | },
38 | },
39 | `gatsby-theme-wordpress-gutenberg`,
40 | ],
41 | }
42 | ```
43 |
44 | - To setup previews, read the [previews](/features/previews/) section.
45 |
--------------------------------------------------------------------------------
/docs/content/installation/packages.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Packages
3 | description: Various packages/plugins which define the framework
4 | ---
5 |
6 | The framework is defined by various packages which need to be installed inside wordpress and gatsby.
7 |
8 | ## Dependencies
9 |
10 | - [`gatsby-source-wordpress-experimental` / `wp-gatsby`](https://github.com/gatsbyjs/gatsby-source-wordpress-experimental): Gatsby package / WP plugin to source Wordpress content into gatsby's GraphQL schema.
11 |
12 | - [`wp-graphql-gutenberg`](https://github.com/pristas-peter/wp-graphql-gutenberg): WP plugin to expose gutenberg blocks through GraphQL schema.
13 |
14 | ## Core
15 |
16 | - `gatsby-theme-wordpress-gutenberg`: Gatsby package responsible for mapping blocks into react components with ability to query them automatically as one component
17 |
18 | > Read more about how theme works [here](/overview/theme/).
19 |
20 | ## Addons
21 |
22 | - `wp-gatsby-gutenberg`: WP plugin to enable live gatsby block previews in gutenberg
23 |
24 | - [`wp-graphql-gutenberg-acf`](https://github.com/pristas-peter/wp-graphql-gutenberg-acf) WP plugin to support ACF blocks (Pro).
25 |
--------------------------------------------------------------------------------
/docs/content/installation/quickstart.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Quickstart Tutorial
3 | description: Simple tutorial on how to use the theme
4 | ---
5 |
6 | ## Install all dependencies
7 |
8 | This tutorial works with following versions of the plugins:
9 |
10 | - wp-graphql 0.9.1
11 | - wp-gatsby 0.4.1
12 | - wp-graphql-gutenberg 0.3.4
13 | - gatsby-source-wordpress-experimental 0.7.13
14 |
15 | ## Create a site
16 |
17 | > This tutorial follows up the the official create a site from strach tutorial from `gatsby-source-wordpress-experimental`.
18 |
19 | Follow the offical [site from stratch](https://github.com/gatsbyjs/gatsby-source-wordpress-experimental/blob/master/docs/tutorials/building-a-new-site-wordpress-and-gatsby.md) tutorial. When your site is up and running go to the next section.
20 |
21 | ## Add testing content
22 |
23 | Add new blocks to the default **Hello World** post. In this example, we added `Quote` and `Columns` blocks with some random content.
24 |
25 |
26 |
27 | ## Query Blocks component
28 |
29 | Open your `src/templates/blog-post.js`. Instead of `content`, we will now query for `Blocks` field. The Blocks field returns a React component which you can use when rendering your BlogPost component.
30 |
31 | > During fast refreshing of new content, there can be situations when the Blocks component can resolve to null, so you need to also make checks for this situation in your code.
32 |
33 | The `Blocks` component is a component which represents your structured content and is created during build phase. The post content is analyzed for all the blocks it contains and then the components which currently represent each block are consolidated into one component. This way, you only provide your custom implementations for each block and the magic of querying and sticking up the content together is done for you behind the scenes.
34 |
35 | ```js
36 | import React from "react"
37 | import Layout from "../components/layout"
38 | import { graphql } from "gatsby"
39 |
40 | export default function BlogPost({ data }) {
41 | const post = data.allWpPost.nodes[0]
42 | console.log(post)
43 | return (
44 |
45 |
46 |
{post.title}
47 | {/* Changed rendering of content to post.Blocks */}
48 | {post.Blocks &&
}
49 |
50 |
51 | )
52 | }
53 | export const query = graphql`
54 | query($slug: String!) {
55 | allWpPost(filter: { slug: { eq: $slug } }) {
56 | nodes {
57 | title
58 | Blocks ### changed content to Blocks
59 | }
60 | }
61 | }
62 | ```
63 |
64 |
65 |
66 | Not much has changed visually, however now we are now not rendering the content as a raw html, but rather as a list of child components.
67 |
68 | > You may encounter a bug when nothing is rendered when you change the fields in the query for the first time. Until this is resolved, simply stop the develop command, run `gatsby clean` and start the `gatsby develop` again.
69 |
70 | ## Add your first block implementation
71 |
72 | You can write your own custom block implementation for each block. Otherwise the default ` ` implementation is used which just displays the raw html output of the block.
73 |
74 | We will start with shadowing this special component so we can display tooltip with the block name when hovering mouse over each block.
75 |
76 | > The example uses `rmwc` library which is a fantastic React Material Design implementation. Make sure to install it using npm/yarn.
77 |
78 | Create a file with path `src/gatsby-theme-wordpress-gutenberg/components/unknown-block.js`, with following content:
79 |
80 | ```js
81 | import React from "react"
82 | import { graphql } from "gatsby"
83 |
84 | import Block from "../../components/block"
85 |
86 | export const query = graphql`
87 | fragment UnknownBlock on WpBlock {
88 | ...Block
89 | saveContent
90 | }
91 | `
92 |
93 | export default function UnknownBlock(props) {
94 | const { saveContent } = props
95 |
96 | return (
97 |
98 |
99 |
100 | )
101 | }
102 | ```
103 |
104 | > The file should contain a graphql fragment definition on the block's graphql type, where you can query for block fields, this fragment will be included when querying for `Blocks` component field. In the example we are using `WpBlock` type which is common interface type for all blocks.
105 |
106 | As you can see in the file above, we also need to create a file in `src/components/block.js`, with following content (this component will be reused later in our various block implementations):
107 |
108 | ```js
109 | import React from "react"
110 | import { graphql } from "gatsby"
111 | import { Tooltip } from "@rmwc/tooltip"
112 |
113 | import "@rmwc/tooltip/styles"
114 |
115 | export const query = graphql`
116 | fragment Block on WpBlock {
117 | name
118 | }
119 | `
120 |
121 | export default function Block({ name, children }) {
122 | return {children}
123 | }
124 | ```
125 |
126 | Now you should see a tooltip when hovering each block with its name.
127 |
128 |
129 |
130 | ## Add Paragraph
131 |
132 | Let's say we want to have a paragraph block which has an oval shape with border and some custom background color.
133 |
134 | You can add your custom block implementations in `src/gatsby-theme-wordpress-gutenberg/components/blocks/[block-name].[ext]`.
135 |
136 | To create a custom Paragraph block implementation create `src/gatsby-theme-wordpress-gutenberg/components/blocks/core/paragraph.js`:
137 |
138 | ```js
139 | import React from "react"
140 | import { graphql } from "gatsby"
141 |
142 | import Block from "../../../../components/block"
143 |
144 | import "@rmwc/tooltip/styles"
145 |
146 | export const query = graphql`
147 | fragment Paragraph on WpCoreParagraphBlock {
148 | ...Block
149 | attributes {
150 | ... on WpCoreParagraphBlockAttributes {
151 | content
152 | dropCap
153 | customBackgroundColor
154 | }
155 | }
156 | }
157 | `
158 |
159 | export default function Paragraph(props) {
160 | const { attributes } = props
161 |
162 | return (
163 |
164 |
173 |
174 | )
175 | }
176 | ```
177 |
178 | After a hot reload you should see the result instantly:
179 |
180 |
181 |
182 | ## Add custom layout for Columns, Column
183 |
184 | To demonstrate how to work with the inner blocks feature, we will create custom implementations of Columns and Column blocks, which will map to rmwc's `` and ``.
185 |
186 | > The `innerBlocks` components are passed in as the `children` prop
187 |
188 | To create a custom Columns block implementation create `src/gatsby-theme-wordpress-gutenberg/components/blocks/core/columns.js`:
189 |
190 | ```js
191 | import React, { useMemo } from "react"
192 | import { graphql } from "gatsby"
193 | import { Grid } from "@rmwc/grid"
194 |
195 | import Block from "../../../../components/block"
196 |
197 | import "@rmwc/grid/styles"
198 |
199 | export const query = graphql`
200 | fragment Columns on WpCoreColumnsBlock {
201 | ...Block
202 | }
203 | `
204 |
205 | export const ColumnsContext = React.createContext()
206 |
207 | export default function Columns(props) {
208 | const { children, ...rest } = props
209 |
210 | const value = useMemo(() => {
211 | const element = React.Children.toArray(children).pop()
212 |
213 | return {
214 | columns: element?.props?.blocks?.length || 0,
215 | }
216 | }, [children])
217 |
218 | return (
219 |
220 |
221 | {children}
222 |
223 |
224 | )
225 | }
226 | ```
227 |
228 | To create a custom Columns block implementation create `src/gatsby-theme-wordpress-gutenberg/components/blocks/core/column.js`:
229 |
230 | ```js
231 | import React, { useContext } from "react"
232 | import { graphql } from "gatsby"
233 | import { GridCell } from "@rmwc/grid"
234 | import { ColumnsContext } from "./columns"
235 |
236 | import Block from "../../../../components/block"
237 |
238 | import "@rmwc/grid/styles"
239 |
240 | export const query = graphql`
241 | fragment Column on WpCoreColumnBlock {
242 | ...Block
243 | }
244 | `
245 |
246 | export default function Column(props) {
247 | const { children, ...rest } = props
248 | const { columns } = useContext(ColumnsContext)
249 |
250 | return (
251 |
252 | {children}
253 |
254 | )
255 | }
256 | ```
257 |
258 | And the result should like this:
259 |
260 |
261 |
262 | > You can find the final result of this tutorial in the `examples/gatsby-wordpress-gutenberg-default-example/frontend` in the project's repo
263 |
--------------------------------------------------------------------------------
/docs/content/overview/sourcing.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Sourcing
3 | description: How does sourcing work?
4 | ---
5 |
6 | ## How does Gutenberg store its content?
7 |
8 | > Get familiar with blocks core concepts from the [official handbook](https://developer.wordpress.org/block-editor/principles/key-concepts/).
9 |
10 | In a nutshell, `block` is some kind of unit for defining structured content. Every block has unique namespaced name and has to be registered in the `block registry` upon gutenberg bootstrap.
11 | Each block also contains `attributes` or configuration setting, which acts as a further metadata storage.
12 |
13 | The gutenberg editor than uses raw post html content to serialize/parse block information which is stored in html comments.
14 |
15 | Here is the example of serialized blocks in raw html post content,
16 |
17 | ```html
18 |
19 |
20 |
21 |
26 |
27 |
28 |
29 |
30 |
31 |
Middle
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | ```
42 |
43 | and here the parsed counterpart:
44 |
45 | ```js
46 | const blocks = [
47 | {
48 | blockName: "core/columns",
49 | attrs: {
50 | columns: 3,
51 | },
52 | innerBlocks: [
53 | {
54 | blockName: "core/column",
55 | attrs: null,
56 | innerBlocks: [
57 | {
58 | blockName: "core/paragraph",
59 | attrs: null,
60 | innerBlocks: [],
61 | innerHTML: "\nLeft
\n",
62 | },
63 | ],
64 | innerHTML: '\n
\n',
65 | },
66 | {
67 | blockName: "core/column",
68 | attrs: null,
69 | innerBlocks: [
70 | {
71 | blockName: "core/paragraph",
72 | attrs: null,
73 | innerBlocks: [],
74 | innerHTML: "\nMiddle
\n",
75 | },
76 | ],
77 | innerHTML: '\n
\n',
78 | },
79 | {
80 | blockName: "core/column",
81 | attrs: null,
82 | innerBlocks: [],
83 | innerHTML: '\n
\n',
84 | },
85 | ],
86 | innerHTML: '\n\n\n\n\n
\n',
87 | },
88 | ]
89 | ```
90 |
91 | ## Issues with Gutenberg
92 |
93 | Gutenberg's main issue lies within its client-side only architecture for registering/validating blocks. This way the block registry and block definitions are only available in the editor itself and not available from the PHP side of WordPress. This exposes many challenges on how to actually expose this information outside of WordPress.
94 |
95 | ## How is the content sourced?
96 |
97 | The main maintainer of this project is also the author of the [`wp-graphql-gutenberg`](https://github.com/pristas-peter/wp-graphql-gutenberg). This plugin is also responsible for providing the block data when the content is sourced through `gatsby-source-wordpress-experimental`.
98 |
--------------------------------------------------------------------------------
/docs/content/overview/theme.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Theme
3 | description: How does the theme work?
4 | ---
5 |
6 | Theme gives you these features:
7 |
8 | - allows you to write custom React component for each block
9 | - autogenerates the ` ` component importing only react components that are used in the content, to keep bundle size small
10 | - manages live previews (as you type in gutenberg)
11 |
12 | The `Blocks` component can be obtained as a field through graphql query in Gatsby:
13 |
14 | ```js
15 | import React from "react"
16 | import Layout from "../components/layout"
17 | import { graphql } from "gatsby"
18 |
19 | export default function BlogPost({ data }) {
20 | const post = data.allWpPost.nodes[0]
21 | console.log(post)
22 | return (
23 |
24 |
25 |
{post.title}
26 | {post.Blocks &&
}
27 |
28 |
29 | )
30 | }
31 | export const query = graphql`
32 | query($slug: String!) {
33 | allWpPost(filter: { slug: { eq: $slug } }) {
34 | nodes {
35 | title
36 | Blocks
37 | }
38 | }
39 | }
40 | `
41 | ```
42 |
43 | > Read more about how to [write your custom React component](/features/blocks/) and how the [previews](/features/previews/) work.
44 |
--------------------------------------------------------------------------------
/docs/gatsby-config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | siteMetadata: {
3 | title: `GatsbyWPGutenberg Docs`,
4 | description: `GatsbyWPGutenberg documentation.`,
5 | },
6 | plugins: [
7 | {
8 | resolve: `gatsby-theme-apollo-docs`,
9 | options: {
10 | // defaultVersion: `0.1 Beta`,
11 | // versions: {
12 | // "0.1 Beta": `version-0.1`,
13 | // },
14 | // algoliaApiKey: `4575706171508518950c4bf031729fc9`,
15 | // algoliaIndexName: `wpgg`,
16 | siteName: `GatsbyWPGutenberg Docs`,
17 | menuTitle: `GatsbyWPGutenberg Menu`,
18 | subtitle: `GatsbyWPGutenberg`,
19 | baseUrl: `https://gatsbywpgutenberg.netlify.app`,
20 | root: __dirname,
21 | description: `GatsbyWPGutenberg documentation`,
22 | githubRepo: `GatsbyWPGutenberg/gatsby-wordpress-gutenberg/docs`,
23 | logoLink: `https://gatsbywpgutenberg.netlify.app`,
24 | navConfig: {
25 | Docs: {
26 | url: `https://gatsbywpgutenberg.netlify.app`,
27 | description: `The GatsbyWPGutenberg docs`,
28 | },
29 | Github: {
30 | url: `https://github.com/GatsbyWPGutenberg`,
31 | description: `GatsbyWPGutenberg on Github`,
32 | },
33 | },
34 | // footerNavConfig: {
35 | // SomeFooterLink: {
36 | // href: `https://github.com/wpgg`,
37 | // target: `_blank`,
38 | // rel: `noopener noreferrer`,
39 | // },
40 | // },
41 | sidebarCategories: {
42 | null: [`index`],
43 | "Get started": [`installation/packages`, `installation/installation`, `installation/quickstart`],
44 | Overview: [`overview/sourcing`, `overview/theme`],
45 | Features: [`features/blocks`, `features/page-templates`, `features/previews`],
46 | "Example Project": [`example/example`],
47 | Contributing: [`contributing/contributing`],
48 | "API Reference": [`api/api`],
49 | },
50 | },
51 | },
52 | {
53 | resolve: `gatsby-transformer-remark`,
54 | options: {
55 | plugins: [
56 | {
57 | resolve: `gatsby-remark-images`,
58 | options: {
59 | maxWidth: 800,
60 | },
61 | },
62 | ],
63 | },
64 | },
65 | `gatsby-plugin-preval`,
66 | ],
67 | }
68 |
--------------------------------------------------------------------------------
/docs/gatsby-node.js:
--------------------------------------------------------------------------------
1 | exports.createSchemaCustomization = ({ actions }) => {
2 | actions.createTypes(`
3 | type File implements Node @infer {
4 | childMarkdownRemark: MarkdownRemark
5 | }
6 |
7 | type MarkdownRemark implements Node @infer {
8 | frontmatter: MarkdownRemarkFrontmatter
9 | fields: MarkdownRemarkFields
10 | }
11 |
12 | type MarkdownRemarkFields {
13 | image: String
14 | version: String
15 | slug: String
16 | graphManagerUrl: String
17 | versionRef: String
18 | sidebarTitle: String
19 | }
20 |
21 | type MarkdownRemarkFrontmatter {
22 | title: String
23 | subtitle: String
24 | description: String
25 | }
26 | `)
27 | }
28 |
--------------------------------------------------------------------------------
/docs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gatsby-wordpress-gutenberg-docs",
3 | "private": true,
4 | "description": "GatsbyWPGutenberg Documentation",
5 | "version": "0.1.0",
6 | "contributors": [
7 | {
8 | "name": "Peter Pristas",
9 | "email": "pristas.peter@gmail.com",
10 | "url": "https://github.com/pristas-peter"
11 | },
12 | {
13 | "name": "Henrik Wirth",
14 | "url": "https://github.com/henrikwirth"
15 | }
16 | ],
17 | "dependencies": {
18 | "gatsby": "^2.19.21",
19 | "gatsby-plugin-preval": "^1.0.0",
20 | "gatsby-plugin-sharp": "^2.6.14",
21 | "gatsby-remark-images": "^3.3.13",
22 | "gatsby-theme-apollo-docs": "4.1.3",
23 | "gatsby-transformer-remark": "^2.8.19",
24 | "react": "16.13.1",
25 | "react-dom": "16.13.1"
26 | },
27 | "devDependencies": {
28 | "prettier": "^1.19.1"
29 | },
30 | "keywords": [
31 | "gatsby"
32 | ],
33 | "license": "MIT",
34 | "scripts": {
35 | "prestart": "gatsby clean",
36 | "build": "gatsby build",
37 | "develop": "gatsby develop",
38 | "format": "prettier --write \"**/*.{js,jsx,json,md}\"",
39 | "start": "npm run develop",
40 | "serve": "gatsby serve",
41 | "clean": "gatsby clean",
42 | "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1"
43 | },
44 | "repository": {
45 | "type": "git",
46 | "url": "https://github.com/GatsbyWPGutenberg/gatsby-wordpress-gutenberg-docs"
47 | },
48 | "bugs": {
49 | "url": "https://github.com/gatsbyjs/gatsby/issues"
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/docs/src/components/style.css:
--------------------------------------------------------------------------------
1 | p {
2 | word-break: break-word;
3 | }
4 |
--------------------------------------------------------------------------------
/docs/src/components/universal-link.js:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { Link as GatsbyLink } from "gatsby"
3 | // Since DOM elements cannot receive activeClassName
4 | // and partiallyActive, destructure the prop here and
5 | // pass it only to GatsbyLink
6 | const UniversalLink = ({ children, to, activeClassName, partiallyActive, ...other }) => {
7 | // Tailor the following test to your environment.
8 | // This example assumes that any internal link (intended for Gatsby)
9 | // will start with exactly one slash, and that anything else is external.
10 | const internal = /^\/(?!\/)/.test(to)
11 | // Use Gatsby Link for internal links, and for others
12 | if (internal) {
13 | return (
14 |
15 | {children}
16 |
17 | )
18 | }
19 | return (
20 |
21 | {children}
22 |
23 | )
24 | }
25 | export default UniversalLink
26 |
--------------------------------------------------------------------------------
/docs/src/gatsby-theme-apollo-core/components/logo.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default function Logo() {
4 | return (
5 | 🚀 GatsbyWPGutenberg Docs
10 | );
11 | }
12 |
--------------------------------------------------------------------------------
/docs/src/gatsby-theme-apollo-docs/assets/social-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GatsbyWPGutenberg/gatsby-wordpress-gutenberg/4bcd987b1a79f47849a7f3b97e2e0bbea673a022/docs/src/gatsby-theme-apollo-docs/assets/social-bg.jpg
--------------------------------------------------------------------------------
/docs/src/gatsby-theme-apollo-docs/components/custom-seo.js:
--------------------------------------------------------------------------------
1 | import PropTypes from "prop-types"
2 | import React from "react"
3 | import { SEO } from "gatsby-theme-apollo-core"
4 | import { withPrefix } from "gatsby"
5 |
6 | export default function CustomSEO({ image, baseUrl, twitterHandle, ...props }) {
7 | const imagePath = withPrefix(`/` + image)
8 | return (
9 |
10 |
11 | {baseUrl && }
12 | {twitterHandle && }
13 |
14 | )
15 | }
16 |
17 | CustomSEO.propTypes = {
18 | baseUrl: PropTypes.string,
19 | image: PropTypes.string.isRequired,
20 | twitterHandle: PropTypes.string,
21 | }
22 |
--------------------------------------------------------------------------------
/docs/src/gatsby-theme-apollo-docs/components/header-button.js:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import styled from "@emotion/styled"
3 | import { IconProceed } from "@apollo/space-kit/icons/IconProceed"
4 | import { breakpoints } from "gatsby-theme-apollo-core"
5 | import { colors } from "@apollo/space-kit/colors"
6 |
7 | const Container = styled.div({
8 | display: `flex`,
9 | flexShrink: 0,
10 | width: 240,
11 | [breakpoints.lg]: {
12 | width: `auto`,
13 | marginRight: 0,
14 | },
15 | [breakpoints.md]: {
16 | display: `none`,
17 | },
18 | })
19 |
20 | const StyledLink = styled.a({
21 | display: `flex`,
22 | alignItems: `center`,
23 | color: colors.indigo.dark,
24 | lineHeight: 2,
25 | textDecoration: `none`,
26 | ":hover": {
27 | color: colors.indigo.darker,
28 | },
29 | })
30 |
31 | const StyledIcon = styled(IconProceed)({
32 | height: `0.75em`,
33 | marginLeft: `0.5em`,
34 | })
35 |
36 | export default function HeaderButton() {
37 | return (
38 |
39 |
44 | Visit us on GitHub
45 |
46 |
47 |
48 | )
49 | }
50 |
--------------------------------------------------------------------------------
/docs/src/gatsby-theme-apollo-docs/components/page-layout.js:
--------------------------------------------------------------------------------
1 | import "gatsby-theme-apollo-docs/src/prism.less"
2 | import "prismjs/plugins/line-numbers/prism-line-numbers.css"
3 | import DocsetSwitcher from "gatsby-theme-apollo-docs/src/components/docset-switcher"
4 | import Header from "gatsby-theme-apollo-docs/src/components/header"
5 | import HeaderButton from "gatsby-theme-apollo-docs/src/components/header-button"
6 | import PropTypes from "prop-types"
7 | import React, { createContext, useMemo, useRef, useState } from "react"
8 | import Search from "gatsby-theme-apollo-docs/src/components/search"
9 | import styled from "@emotion/styled"
10 | import useLocalStorage from "react-use/lib/useLocalStorage"
11 | import { Button } from "@apollo/space-kit/Button"
12 | import {
13 | FlexWrapper,
14 | Layout,
15 | MenuButton,
16 | Sidebar,
17 | SidebarNav,
18 | breakpoints,
19 | colors,
20 | useResponsiveSidebar,
21 | } from "gatsby-theme-apollo-core"
22 | import { Helmet } from "react-helmet"
23 | import { IconLayoutModule } from "@apollo/space-kit/icons/IconLayoutModule"
24 | import { Link, graphql, navigate, useStaticQuery } from "gatsby"
25 | // import { MobileLogo } from "gatsby-theme-apollo-docs/src/components/mobile-logo"
26 | import { Select } from "gatsby-theme-apollo-docs/src/components/select"
27 | import { SelectedLanguageContext } from "gatsby-theme-apollo-docs/src/components/multi-code-block"
28 | import { getSpectrumUrl, getVersionBasePath } from "gatsby-theme-apollo-docs/src/utils"
29 | import { size } from "polished"
30 |
31 | const Main = styled.main({
32 | flexGrow: 1,
33 | })
34 |
35 | const ButtonWrapper = styled.div({
36 | flexGrow: 1,
37 | })
38 |
39 | const StyledButton = styled(Button)({
40 | width: `100%`,
41 | ":not(:hover)": {
42 | backgroundColor: colors.background,
43 | },
44 | })
45 |
46 | const StyledIcon = styled(IconLayoutModule)(size(16), {
47 | marginLeft: `auto`,
48 | })
49 |
50 | const MobileNav = styled.div({
51 | display: `none`,
52 | [breakpoints.md]: {
53 | display: `flex`,
54 | alignItems: `center`,
55 | marginRight: 32,
56 | color: colors.text1,
57 | },
58 | })
59 |
60 | const HeaderInner = styled.span({
61 | display: `flex`,
62 | alignItems: `center`,
63 | justifyContent: `space-between`,
64 | marginBottom: 32,
65 | })
66 |
67 | const Eyebrow = styled.div({
68 | flexShrink: 0,
69 | padding: `8px 56px`,
70 | backgroundColor: colors.background,
71 | color: colors.primary,
72 | fontSize: 14,
73 | position: `sticky`,
74 | top: 0,
75 | a: {
76 | color: `inherit`,
77 | fontWeight: 600,
78 | },
79 | [breakpoints.md]: {
80 | padding: `8px 24px`,
81 | },
82 | })
83 |
84 | const NetlifyLink = styled.a({
85 | marginRight: 12,
86 | })
87 |
88 | function getVersionLabel(version) {
89 | return `v${version}`
90 | }
91 |
92 | const GA_EVENT_CATEGORY_SIDEBAR = `Sidebar`
93 |
94 | function handleToggleAll(expanded) {
95 | if (typeof window.analytics !== `undefined`) {
96 | window.analytics.track(`Toggle all`, {
97 | category: GA_EVENT_CATEGORY_SIDEBAR,
98 | label: expanded ? `expand` : `collapse`,
99 | })
100 | }
101 | }
102 |
103 | function handleToggleCategory(title, expanded) {
104 | if (typeof window.analytics !== `undefined`) {
105 | window.analytics.track(`Toggle category`, {
106 | category: GA_EVENT_CATEGORY_SIDEBAR,
107 | label: title,
108 | value: Number(expanded),
109 | })
110 | }
111 | }
112 |
113 | export const NavItemsContext = createContext()
114 |
115 | export default function PageLayout(props) {
116 | const data = useStaticQuery(
117 | graphql`
118 | {
119 | site {
120 | siteMetadata {
121 | title
122 | siteName
123 | }
124 | }
125 | }
126 | `
127 | )
128 |
129 | const { sidebarRef, openSidebar, sidebarOpen, handleWrapperClick, handleSidebarNavLinkClick } = useResponsiveSidebar()
130 |
131 | const buttonRef = useRef(null)
132 | const [menuOpen, setMenuOpen] = useState(false)
133 | const selectedLanguageState = useLocalStorage(`docs-lang`)
134 |
135 | function openMenu() {
136 | setMenuOpen(true)
137 | }
138 |
139 | function closeMenu() {
140 | setMenuOpen(false)
141 | }
142 |
143 | const { pathname } = props.location
144 | const { siteName, title } = data.site.siteMetadata
145 | const { subtitle, sidebarContents, versions, versionDifference, versionBasePath, defaultVersion } = props.pageContext
146 | const {
147 | spectrumHandle,
148 | twitterHandle,
149 | youtubeUrl,
150 | navConfig = {},
151 | footerNavConfig,
152 | logoLink,
153 | algoliaApiKey,
154 | algoliaIndexName,
155 | menuTitle,
156 | } = props.pluginOptions
157 |
158 | const navItems = useMemo(
159 | () =>
160 | Object.entries(navConfig).map(([title, navItem]) => ({
161 | ...navItem,
162 | title,
163 | })),
164 | [navConfig]
165 | )
166 |
167 | const hasNavItems = navItems.length > 0
168 | const sidebarTitle = {subtitle || siteName}
169 |
170 | return (
171 |
172 |
173 |
174 |
175 |
176 |
177 |
185 |
186 | {hasNavItems ? (
187 |
188 |
195 | {sidebarTitle}
196 |
197 |
198 |
199 | ) : (
200 | sidebarTitle
201 | )}
202 | {versions && versions.length > 0 && (
203 | {
211 | return {
212 | ...acc,
213 | [getVersionBasePath(version)]: getVersionLabel(version),
214 | }
215 | },
216 | {
217 | "/": defaultVersion ? getVersionLabel(defaultVersion) : `Latest`,
218 | }
219 | )}
220 | />
221 | )}
222 |
223 |
224 | {sidebarContents && (
225 |
232 | )}
233 |
234 |
235 |
238 | {versionDifference !== 0 && (
239 |
240 | You're viewing documentation for a{` `}
241 | {versionDifference > 0
242 | ? `version of this software that is in development`
243 | : `previous version of this software`}
244 | . Switch to the latest stable version
245 |
246 | )}
247 | >
248 | }
249 | >
250 |
251 |
252 | {/* */}
253 |
254 |
255 |
256 |
257 | {algoliaApiKey && algoliaIndexName && (
258 |
259 | )}
260 |
261 |
262 |
263 | {props.children}
264 |
265 |
266 |
267 | {hasNavItems && (
268 |
279 | )}
280 |
281 | )
282 | }
283 |
284 | PageLayout.propTypes = {
285 | children: PropTypes.node.isRequired,
286 | location: PropTypes.object.isRequired,
287 | pageContext: PropTypes.object.isRequired,
288 | pluginOptions: PropTypes.object.isRequired,
289 | }
290 |
--------------------------------------------------------------------------------
/docs/src/gatsby-theme-apollo-docs/components/social-card.js:
--------------------------------------------------------------------------------
1 | /* global preval */
2 | import PropTypes from "prop-types"
3 | import React, { Fragment } from "react"
4 | import TextFit from "react-textfit"
5 | import { Global, css } from "@emotion/core"
6 | import { IconArrowRight } from "@apollo/space-kit/icons/IconArrowRight"
7 | import { colors } from "gatsby-theme-apollo-core/src/utils/colors"
8 | import { smallCaps } from "gatsby-theme-apollo-core/src/utils/typography"
9 |
10 | const { fonts, image } = preval`
11 | const fs = require('fs');
12 | const path = require('path');
13 |
14 | function getBase64(path) {
15 | const fontPath = require.resolve('source-sans-pro/' + path);
16 | const base64Font = fs.readFileSync(fontPath, 'base64');
17 | return 'data:application/x-font-woff;charset=utf-8;base64,' + base64Font;
18 | }
19 |
20 | const base64Regular = getBase64('/WOFF2/TTF/SourceSansPro-Regular.ttf.woff2');
21 | const base64Semibold = getBase64('/WOFF2/TTF/SourceSansPro-Semibold.ttf.woff2');
22 |
23 | const cssPath = require.resolve('source-sans-pro/source-sans-pro.css');
24 | const fonts = fs
25 | .readFileSync(cssPath, 'utf-8')
26 | .replace('WOFF2/TTF/SourceSansPro-Regular.ttf.woff2', base64Regular)
27 | .replace('WOFF2/TTF/SourceSansPro-Semibold.ttf.woff2', base64Semibold);
28 |
29 | const imagePath = path.resolve(__dirname, '../assets/social-bg.jpg');
30 | const base64Image = fs.readFileSync(imagePath, 'base64');
31 |
32 | module.exports = {
33 | fonts,
34 | image: 'data:image/jpeg;base64,' + base64Image
35 | };
36 | `
37 |
38 | export default function SocialCard(props) {
39 | return (
40 |
54 |
63 |
72 | {props.subtitle}
73 | {props.category && (
74 |
75 | {` `}
76 |
84 | {` `}
85 | {props.category}
86 |
87 | )}
88 |
89 |
100 | {props.title.replace(/\s+(\S*)$/, `\xA0$1`)}
101 |
102 |
103 | GatsbyWPGutenberg
104 |
105 |
106 | )
107 | }
108 |
109 | SocialCard.propTypes = {
110 | title: PropTypes.string.isRequired,
111 | subtitle: PropTypes.string.isRequired,
112 | category: PropTypes.string,
113 | }
114 |
--------------------------------------------------------------------------------
/docs/src/images/gatsby-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GatsbyWPGutenberg/gatsby-wordpress-gutenberg/4bcd987b1a79f47849a7f3b97e2e0bbea673a022/docs/src/images/gatsby-icon.png
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/.gitignore:
--------------------------------------------------------------------------------
1 | db
2 | wordpress
3 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/README.md:
--------------------------------------------------------------------------------
1 | ## Frontend
2 |
3 | ```
4 | cd frontend; yarn && yarn gatsby develop
5 | ```
6 |
7 | ## Backend
8 |
9 | ```
10 | cd backend; docker-compose up
11 | ```
12 |
13 | > url: http://localhost:8020
14 |
15 | > login: admin
16 |
17 | > pass: admin
18 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/backend/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 |
3 | !composer*
4 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/backend/docker-compose.xdebug.yml:
--------------------------------------------------------------------------------
1 | version: "3.1"
2 |
3 | services:
4 | wordpress:
5 | image: andreccosta/wordpress-xdebug
6 | environment:
7 | XDEBUG_CONFIG: remote_host=host.docker.internal
8 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/backend/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.1"
2 |
3 | services:
4 | composer:
5 | image: composer
6 | command: install
7 | volumes:
8 | - ./wordpress:/app
9 | - ../../../plugins:/plugins:ro
10 | wordpress:
11 | depends_on:
12 | - db
13 | - composer
14 | image: wordpress
15 | restart: always
16 | ports:
17 | - 8020:80
18 | environment:
19 | WORDPRESS_DB_HOST: db
20 | WORDPRESS_DB_USER: exampleuser
21 | WORDPRESS_DB_PASSWORD: examplepass
22 | WORDPRESS_DB_NAME: exampledb
23 | WORDPRESS_CONFIG_EXTRA: |
24 | define( 'GRAPHQL_DEBUG', true );
25 |
26 | volumes:
27 | - ./wordpress:/var/www/html
28 | - ../../../plugins:/plugins:ro
29 | cli:
30 | depends_on:
31 | - db
32 | - wordpress
33 | image: wordpress:cli
34 | volumes:
35 | - ./wordpress:/var/www/html
36 | - ../../../plugins:/plugins:ro
37 | db:
38 | image: mysql:5.7
39 | restart: always
40 | environment:
41 | MYSQL_DATABASE: exampledb
42 | MYSQL_USER: exampleuser
43 | MYSQL_PASSWORD: examplepass
44 | MYSQL_ROOT_PASSWORD: rootpass
45 | MYSQL_RANDOM_ROOT_PASSWORD: "1"
46 | volumes:
47 | - ./db:/var/lib/mysql
48 | - ./docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
49 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/backend/wordpress/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "minimum-stability": "dev",
3 | "prefer-stable": true,
4 | "repositories": [
5 | {
6 | "type": "composer",
7 | "url": "https://wpackagist.org"
8 | },
9 | {
10 | "type": "path",
11 | "url": "/plugins/wp-gatsby-gutenberg",
12 | "options": {
13 | "symlink": true
14 | }
15 | }
16 | ],
17 | "require": {
18 | "composer/installers": "~1.0",
19 | "wp-graphql/wp-graphql": "0.9.1",
20 | "gatsbyjs/wp-gatsby": "0.4.1",
21 | "pristas-peter/wp-graphql-gutenberg": "0.3.4",
22 | "pristas-peter/wp-graphql-gutenberg-acf": "0.3.0",
23 | "gatsby-wordpress-gutenberg/wp-gatsby-gutenberg": "@dev"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/.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-wordpress-gutenberg-default-example/frontend/.prettierignore:
--------------------------------------------------------------------------------
1 | .cache
2 | package.json
3 | package-lock.json
4 | public
5 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "arrowParens": "avoid",
3 | "semi": false
4 | }
5 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/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 |
23 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Gatsby's default starter
9 |
10 |
11 | Kick off your project with this default 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 default starter.
20 |
21 | ```shell
22 | # create a new Gatsby site using the default starter
23 | gatsby new my-default-starter https://github.com/gatsbyjs/gatsby-starter-default
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-default-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-default-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 | [](https://app.netlify.com/start/deploy?repository=https://github.com/gatsbyjs/gatsby-starter-default)
96 |
97 | [](https://vercel.com/import/project?template=https://github.com/gatsbyjs/gatsby-starter-default)
98 |
99 |
100 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/gatsby-browser.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Implement Gatsby's Browser APIs in this file.
3 | *
4 | * See: https://www.gatsbyjs.org/docs/browser-apis/
5 | */
6 |
7 | // You can delete this file if you're not using it
8 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/gatsby-config.js:
--------------------------------------------------------------------------------
1 | require("dotenv").config({
2 | path: `.env.${process.env.NODE_ENV}`,
3 | })
4 |
5 | module.exports = {
6 | siteMetadata: {
7 | title: `Gatsby Default Starter`,
8 | description: `Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`,
9 | author: `@gatsbyjs`,
10 | },
11 | plugins: [
12 | `gatsby-plugin-react-helmet`,
13 | {
14 | resolve: `gatsby-source-filesystem`,
15 | options: {
16 | name: `images`,
17 | path: `${__dirname}/src/images`,
18 | },
19 | },
20 | `gatsby-transformer-sharp`,
21 | `gatsby-plugin-sharp`,
22 | {
23 | resolve: `gatsby-plugin-manifest`,
24 | options: {
25 | name: `gatsby-starter-default`,
26 | short_name: `starter`,
27 | start_url: `/`,
28 | background_color: `#663399`,
29 | theme_color: `#663399`,
30 | display: `minimal-ui`,
31 | icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site.
32 | },
33 | },
34 | {
35 | resolve: `gatsby-source-wordpress-experimental`,
36 | options: {
37 | url: "http://localhost:8020/graphql",
38 | // verbose: true,
39 | // develop: {
40 | // nodeUpdateInterval: 5000,
41 | // },
42 | // debug: {
43 | // graphql: {
44 | // showQueryOnError: true,
45 | // showQueryVarsOnError: false,
46 | // copyQueryOnError: false,
47 | // panicOnError: false,
48 | // onlyReportCriticalErrors: false,
49 | // },
50 | // },
51 | },
52 | },
53 | `gatsby-theme-wordpress-gutenberg`,
54 | // this (optional) plugin enables Progressive Web App + Offline functionality
55 | // To learn more, visit: https://gatsby.dev/offline
56 | // `gatsby-plugin-offline`,
57 | ],
58 | }
59 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/gatsby-node.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Implement Gatsby's Node APIs in this file.
3 | *
4 | * See: https://www.gatsbyjs.org/docs/node-apis/
5 | */
6 |
7 | const path = require(`path`)
8 |
9 | exports.createPages = ({ graphql, actions }) => {
10 | const { createPage } = actions
11 | return graphql(`
12 | {
13 | allWpPost(sort: { fields: [date] }) {
14 | nodes {
15 | title
16 | excerpt
17 | content
18 | slug
19 | }
20 | }
21 | }
22 | `).then(result => {
23 | //highlight-start
24 | result.data.allWpPost.nodes.forEach(node => {
25 | createPage({
26 | path: node.slug,
27 | component: path.resolve(`./src/templates/blog-post.js`),
28 | context: {
29 | // This is the $slug variable
30 | // passed to blog-post.js
31 | slug: node.slug,
32 | },
33 | })
34 | })
35 | //highlight-end
36 | })
37 | }
38 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/gatsby-ssr.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Implement Gatsby's SSR (Server Side Rendering) APIs in this file.
3 | *
4 | * See: https://www.gatsbyjs.org/docs/ssr-apis/
5 | */
6 |
7 | // You can delete this file if you're not using it
8 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gatsby-wordpress-gutenberg-default-example",
3 | "private": true,
4 | "description": "A simple starter to get up and developing quickly with WPGatsbyGutenberg",
5 | "version": "0.1.0",
6 | "author": "Peter Pristas ",
7 | "dependencies": {
8 | "gatsby": "^2.23.10",
9 | "gatsby-image": "^2.4.8",
10 | "gatsby-plugin-manifest": "^2.4.13",
11 | "gatsby-plugin-offline": "^3.2.12",
12 | "gatsby-plugin-react-helmet": "^3.3.5",
13 | "gatsby-plugin-sharp": "^2.6.13",
14 | "gatsby-source-filesystem": "^2.3.13",
15 | "gatsby-source-wordpress-experimental": "^0.7.13",
16 | "gatsby-theme-wordpress-gutenberg": "^0.1.0",
17 | "gatsby-transformer-sharp": "^2.5.6",
18 | "prop-types": "^15.7.2",
19 | "react": "^16.12.0",
20 | "react-dom": "^16.12.0",
21 | "react-helmet": "^6.1.0",
22 | "rmwc": "^6.1.3"
23 | },
24 | "devDependencies": {
25 | "prettier": "2.0.5"
26 | },
27 | "keywords": [
28 | "gatsby"
29 | ],
30 | "license": "MIT",
31 | "scripts": {
32 | "build": "gatsby build",
33 | "develop": "gatsby develop",
34 | "format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,md}\"",
35 | "start": "npm run develop",
36 | "serve": "gatsby serve",
37 | "clean": "gatsby clean",
38 | "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1"
39 | },
40 | "repository": {
41 | "type": "git",
42 | "url": "https://github.com/gatsbyjs/gatsby-starter-default"
43 | },
44 | "bugs": {
45 | "url": "https://github.com/gatsbyjs/gatsby/issues"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/src/components/block.js:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { graphql } from "gatsby"
3 | import { Tooltip } from "@rmwc/tooltip"
4 |
5 | import "@rmwc/tooltip/styles"
6 |
7 | export const query = graphql`
8 | fragment Block on WpBlock {
9 | name
10 | }
11 | `
12 |
13 | export default function Block({ name, children }) {
14 | return {children}
15 | }
16 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/src/components/header.js:
--------------------------------------------------------------------------------
1 | import { Link } from "gatsby"
2 | import PropTypes from "prop-types"
3 | import React from "react"
4 |
5 | const Header = ({ siteTitle }) => (
6 |
32 | )
33 |
34 | Header.propTypes = {
35 | siteTitle: PropTypes.string,
36 | }
37 |
38 | Header.defaultProps = {
39 | siteTitle: ``,
40 | }
41 |
42 | export default Header
43 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/src/components/image.js:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { useStaticQuery, graphql } from "gatsby"
3 | import Img from "gatsby-image"
4 |
5 | /*
6 | * This component is built using `gatsby-image` to automatically serve optimized
7 | * images with lazy loading and reduced file sizes. The image is loaded using a
8 | * `useStaticQuery`, which allows us to load the image from directly within this
9 | * component, rather than having to pass the image data down from pages.
10 | *
11 | * For more information, see the docs:
12 | * - `gatsby-image`: https://gatsby.dev/gatsby-image
13 | * - `useStaticQuery`: https://www.gatsbyjs.org/docs/use-static-query/
14 | */
15 |
16 | const Image = () => {
17 | const data = useStaticQuery(graphql`
18 | query {
19 | placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) {
20 | childImageSharp {
21 | fluid(maxWidth: 300) {
22 | ...GatsbyImageSharpFluid
23 | }
24 | }
25 | }
26 | }
27 | `)
28 |
29 | return
30 | }
31 |
32 | export default Image
33 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/src/components/layout.css:
--------------------------------------------------------------------------------
1 | html {
2 | font-family: sans-serif;
3 | -ms-text-size-adjust: 100%;
4 | -webkit-text-size-adjust: 100%;
5 | }
6 | body {
7 | margin: 0;
8 | -webkit-font-smoothing: antialiased;
9 | -moz-osx-font-smoothing: grayscale;
10 | }
11 | article,
12 | aside,
13 | details,
14 | figcaption,
15 | figure,
16 | footer,
17 | header,
18 | main,
19 | menu,
20 | nav,
21 | section,
22 | summary {
23 | display: block;
24 | }
25 | audio,
26 | canvas,
27 | progress,
28 | video {
29 | display: inline-block;
30 | }
31 | audio:not([controls]) {
32 | display: none;
33 | height: 0;
34 | }
35 | progress {
36 | vertical-align: baseline;
37 | }
38 | [hidden],
39 | template {
40 | display: none;
41 | }
42 | a {
43 | background-color: transparent;
44 | -webkit-text-decoration-skip: objects;
45 | }
46 | a:active,
47 | a:hover {
48 | outline-width: 0;
49 | }
50 | abbr[title] {
51 | border-bottom: none;
52 | text-decoration: underline;
53 | text-decoration: underline dotted;
54 | }
55 | b,
56 | strong {
57 | font-weight: inherit;
58 | font-weight: bolder;
59 | }
60 | dfn {
61 | font-style: italic;
62 | }
63 | h1 {
64 | font-size: 2em;
65 | margin: 0.67em 0;
66 | }
67 | mark {
68 | background-color: #ff0;
69 | color: #000;
70 | }
71 | small {
72 | font-size: 80%;
73 | }
74 | sub,
75 | sup {
76 | font-size: 75%;
77 | line-height: 0;
78 | position: relative;
79 | vertical-align: baseline;
80 | }
81 | sub {
82 | bottom: -0.25em;
83 | }
84 | sup {
85 | top: -0.5em;
86 | }
87 | img {
88 | border-style: none;
89 | }
90 | svg:not(:root) {
91 | overflow: hidden;
92 | }
93 | code,
94 | kbd,
95 | pre,
96 | samp {
97 | font-family: monospace, monospace;
98 | font-size: 1em;
99 | }
100 | figure {
101 | margin: 1em 40px;
102 | }
103 | hr {
104 | box-sizing: content-box;
105 | height: 0;
106 | overflow: visible;
107 | }
108 | button,
109 | input,
110 | optgroup,
111 | select,
112 | textarea {
113 | font: inherit;
114 | margin: 0;
115 | }
116 | optgroup {
117 | font-weight: 700;
118 | }
119 | button,
120 | input {
121 | overflow: visible;
122 | }
123 | button,
124 | select {
125 | text-transform: none;
126 | }
127 | [type="reset"],
128 | [type="submit"],
129 | button,
130 | html [type="button"] {
131 | -webkit-appearance: button;
132 | }
133 | [type="button"]::-moz-focus-inner,
134 | [type="reset"]::-moz-focus-inner,
135 | [type="submit"]::-moz-focus-inner,
136 | button::-moz-focus-inner {
137 | border-style: none;
138 | padding: 0;
139 | }
140 | [type="button"]:-moz-focusring,
141 | [type="reset"]:-moz-focusring,
142 | [type="submit"]:-moz-focusring,
143 | button:-moz-focusring {
144 | outline: 1px dotted ButtonText;
145 | }
146 | fieldset {
147 | border: 1px solid silver;
148 | margin: 0 2px;
149 | padding: 0.35em 0.625em 0.75em;
150 | }
151 | legend {
152 | box-sizing: border-box;
153 | color: inherit;
154 | display: table;
155 | max-width: 100%;
156 | padding: 0;
157 | white-space: normal;
158 | }
159 | textarea {
160 | overflow: auto;
161 | }
162 | [type="checkbox"],
163 | [type="radio"] {
164 | box-sizing: border-box;
165 | padding: 0;
166 | }
167 | [type="number"]::-webkit-inner-spin-button,
168 | [type="number"]::-webkit-outer-spin-button {
169 | height: auto;
170 | }
171 | [type="search"] {
172 | -webkit-appearance: textfield;
173 | outline-offset: -2px;
174 | }
175 | [type="search"]::-webkit-search-cancel-button,
176 | [type="search"]::-webkit-search-decoration {
177 | -webkit-appearance: none;
178 | }
179 | ::-webkit-input-placeholder {
180 | color: inherit;
181 | opacity: 0.54;
182 | }
183 | ::-webkit-file-upload-button {
184 | -webkit-appearance: button;
185 | font: inherit;
186 | }
187 | html {
188 | font: 112.5%/1.45em georgia, serif;
189 | box-sizing: border-box;
190 | overflow-y: scroll;
191 | }
192 | * {
193 | box-sizing: inherit;
194 | }
195 | *:before {
196 | box-sizing: inherit;
197 | }
198 | *:after {
199 | box-sizing: inherit;
200 | }
201 | body {
202 | color: hsla(0, 0%, 0%, 0.8);
203 | font-family: georgia, serif;
204 | font-weight: normal;
205 | word-wrap: break-word;
206 | font-kerning: normal;
207 | -moz-font-feature-settings: "kern", "liga", "clig", "calt";
208 | -ms-font-feature-settings: "kern", "liga", "clig", "calt";
209 | -webkit-font-feature-settings: "kern", "liga", "clig", "calt";
210 | font-feature-settings: "kern", "liga", "clig", "calt";
211 | }
212 | img {
213 | max-width: 100%;
214 | margin-left: 0;
215 | margin-right: 0;
216 | margin-top: 0;
217 | padding-bottom: 0;
218 | padding-left: 0;
219 | padding-right: 0;
220 | padding-top: 0;
221 | margin-bottom: 1.45rem;
222 | }
223 | h1 {
224 | margin-left: 0;
225 | margin-right: 0;
226 | margin-top: 0;
227 | padding-bottom: 0;
228 | padding-left: 0;
229 | padding-right: 0;
230 | padding-top: 0;
231 | margin-bottom: 1.45rem;
232 | color: inherit;
233 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
234 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
235 | font-weight: bold;
236 | text-rendering: optimizeLegibility;
237 | font-size: 2.25rem;
238 | line-height: 1.1;
239 | }
240 | h2 {
241 | margin-left: 0;
242 | margin-right: 0;
243 | margin-top: 0;
244 | padding-bottom: 0;
245 | padding-left: 0;
246 | padding-right: 0;
247 | padding-top: 0;
248 | margin-bottom: 1.45rem;
249 | color: inherit;
250 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
251 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
252 | font-weight: bold;
253 | text-rendering: optimizeLegibility;
254 | font-size: 1.62671rem;
255 | line-height: 1.1;
256 | }
257 | h3 {
258 | margin-left: 0;
259 | margin-right: 0;
260 | margin-top: 0;
261 | padding-bottom: 0;
262 | padding-left: 0;
263 | padding-right: 0;
264 | padding-top: 0;
265 | margin-bottom: 1.45rem;
266 | color: inherit;
267 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
268 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
269 | font-weight: bold;
270 | text-rendering: optimizeLegibility;
271 | font-size: 1.38316rem;
272 | line-height: 1.1;
273 | }
274 | h4 {
275 | margin-left: 0;
276 | margin-right: 0;
277 | margin-top: 0;
278 | padding-bottom: 0;
279 | padding-left: 0;
280 | padding-right: 0;
281 | padding-top: 0;
282 | margin-bottom: 1.45rem;
283 | color: inherit;
284 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
285 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
286 | font-weight: bold;
287 | text-rendering: optimizeLegibility;
288 | font-size: 1rem;
289 | line-height: 1.1;
290 | }
291 | h5 {
292 | margin-left: 0;
293 | margin-right: 0;
294 | margin-top: 0;
295 | padding-bottom: 0;
296 | padding-left: 0;
297 | padding-right: 0;
298 | padding-top: 0;
299 | margin-bottom: 1.45rem;
300 | color: inherit;
301 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
302 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
303 | font-weight: bold;
304 | text-rendering: optimizeLegibility;
305 | font-size: 0.85028rem;
306 | line-height: 1.1;
307 | }
308 | h6 {
309 | margin-left: 0;
310 | margin-right: 0;
311 | margin-top: 0;
312 | padding-bottom: 0;
313 | padding-left: 0;
314 | padding-right: 0;
315 | padding-top: 0;
316 | margin-bottom: 1.45rem;
317 | color: inherit;
318 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
319 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
320 | font-weight: bold;
321 | text-rendering: optimizeLegibility;
322 | font-size: 0.78405rem;
323 | line-height: 1.1;
324 | }
325 | hgroup {
326 | margin-left: 0;
327 | margin-right: 0;
328 | margin-top: 0;
329 | padding-bottom: 0;
330 | padding-left: 0;
331 | padding-right: 0;
332 | padding-top: 0;
333 | margin-bottom: 1.45rem;
334 | }
335 | ul {
336 | margin-left: 1.45rem;
337 | margin-right: 0;
338 | margin-top: 0;
339 | padding-bottom: 0;
340 | padding-left: 0;
341 | padding-right: 0;
342 | padding-top: 0;
343 | margin-bottom: 1.45rem;
344 | list-style-position: outside;
345 | list-style-image: none;
346 | }
347 | ol {
348 | margin-left: 1.45rem;
349 | margin-right: 0;
350 | margin-top: 0;
351 | padding-bottom: 0;
352 | padding-left: 0;
353 | padding-right: 0;
354 | padding-top: 0;
355 | margin-bottom: 1.45rem;
356 | list-style-position: outside;
357 | list-style-image: none;
358 | }
359 | dl {
360 | margin-left: 0;
361 | margin-right: 0;
362 | margin-top: 0;
363 | padding-bottom: 0;
364 | padding-left: 0;
365 | padding-right: 0;
366 | padding-top: 0;
367 | margin-bottom: 1.45rem;
368 | }
369 | dd {
370 | margin-left: 0;
371 | margin-right: 0;
372 | margin-top: 0;
373 | padding-bottom: 0;
374 | padding-left: 0;
375 | padding-right: 0;
376 | padding-top: 0;
377 | margin-bottom: 1.45rem;
378 | }
379 | p {
380 | margin-left: 0;
381 | margin-right: 0;
382 | margin-top: 0;
383 | padding-bottom: 0;
384 | padding-left: 0;
385 | padding-right: 0;
386 | padding-top: 0;
387 | margin-bottom: 1.45rem;
388 | }
389 | figure {
390 | margin-left: 0;
391 | margin-right: 0;
392 | margin-top: 0;
393 | padding-bottom: 0;
394 | padding-left: 0;
395 | padding-right: 0;
396 | padding-top: 0;
397 | margin-bottom: 1.45rem;
398 | }
399 | pre {
400 | margin-left: 0;
401 | margin-right: 0;
402 | margin-top: 0;
403 | margin-bottom: 1.45rem;
404 | font-size: 0.85rem;
405 | line-height: 1.42;
406 | background: hsla(0, 0%, 0%, 0.04);
407 | border-radius: 3px;
408 | overflow: auto;
409 | word-wrap: normal;
410 | padding: 1.45rem;
411 | }
412 | table {
413 | margin-left: 0;
414 | margin-right: 0;
415 | margin-top: 0;
416 | padding-bottom: 0;
417 | padding-left: 0;
418 | padding-right: 0;
419 | padding-top: 0;
420 | margin-bottom: 1.45rem;
421 | font-size: 1rem;
422 | line-height: 1.45rem;
423 | border-collapse: collapse;
424 | width: 100%;
425 | }
426 | fieldset {
427 | margin-left: 0;
428 | margin-right: 0;
429 | margin-top: 0;
430 | padding-bottom: 0;
431 | padding-left: 0;
432 | padding-right: 0;
433 | padding-top: 0;
434 | margin-bottom: 1.45rem;
435 | }
436 | blockquote {
437 | margin-left: 1.45rem;
438 | margin-right: 1.45rem;
439 | margin-top: 0;
440 | padding-bottom: 0;
441 | padding-left: 0;
442 | padding-right: 0;
443 | padding-top: 0;
444 | margin-bottom: 1.45rem;
445 | }
446 | form {
447 | margin-left: 0;
448 | margin-right: 0;
449 | margin-top: 0;
450 | padding-bottom: 0;
451 | padding-left: 0;
452 | padding-right: 0;
453 | padding-top: 0;
454 | margin-bottom: 1.45rem;
455 | }
456 | noscript {
457 | margin-left: 0;
458 | margin-right: 0;
459 | margin-top: 0;
460 | padding-bottom: 0;
461 | padding-left: 0;
462 | padding-right: 0;
463 | padding-top: 0;
464 | margin-bottom: 1.45rem;
465 | }
466 | iframe {
467 | margin-left: 0;
468 | margin-right: 0;
469 | margin-top: 0;
470 | padding-bottom: 0;
471 | padding-left: 0;
472 | padding-right: 0;
473 | padding-top: 0;
474 | margin-bottom: 1.45rem;
475 | }
476 | hr {
477 | margin-left: 0;
478 | margin-right: 0;
479 | margin-top: 0;
480 | padding-bottom: 0;
481 | padding-left: 0;
482 | padding-right: 0;
483 | padding-top: 0;
484 | margin-bottom: calc(1.45rem - 1px);
485 | background: hsla(0, 0%, 0%, 0.2);
486 | border: none;
487 | height: 1px;
488 | }
489 | address {
490 | margin-left: 0;
491 | margin-right: 0;
492 | margin-top: 0;
493 | padding-bottom: 0;
494 | padding-left: 0;
495 | padding-right: 0;
496 | padding-top: 0;
497 | margin-bottom: 1.45rem;
498 | }
499 | b {
500 | font-weight: bold;
501 | }
502 | strong {
503 | font-weight: bold;
504 | }
505 | dt {
506 | font-weight: bold;
507 | }
508 | th {
509 | font-weight: bold;
510 | }
511 | li {
512 | margin-bottom: calc(1.45rem / 2);
513 | }
514 | ol li {
515 | padding-left: 0;
516 | }
517 | ul li {
518 | padding-left: 0;
519 | }
520 | li > ol {
521 | margin-left: 1.45rem;
522 | margin-bottom: calc(1.45rem / 2);
523 | margin-top: calc(1.45rem / 2);
524 | }
525 | li > ul {
526 | margin-left: 1.45rem;
527 | margin-bottom: calc(1.45rem / 2);
528 | margin-top: calc(1.45rem / 2);
529 | }
530 | blockquote *:last-child {
531 | margin-bottom: 0;
532 | }
533 | li *:last-child {
534 | margin-bottom: 0;
535 | }
536 | p *:last-child {
537 | margin-bottom: 0;
538 | }
539 | li > p {
540 | margin-bottom: calc(1.45rem / 2);
541 | }
542 | code {
543 | font-size: 0.85rem;
544 | line-height: 1.45rem;
545 | }
546 | kbd {
547 | font-size: 0.85rem;
548 | line-height: 1.45rem;
549 | }
550 | samp {
551 | font-size: 0.85rem;
552 | line-height: 1.45rem;
553 | }
554 | abbr {
555 | border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5);
556 | cursor: help;
557 | }
558 | acronym {
559 | border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5);
560 | cursor: help;
561 | }
562 | abbr[title] {
563 | border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5);
564 | cursor: help;
565 | text-decoration: none;
566 | }
567 | thead {
568 | text-align: left;
569 | }
570 | td,
571 | th {
572 | text-align: left;
573 | border-bottom: 1px solid hsla(0, 0%, 0%, 0.12);
574 | font-feature-settings: "tnum";
575 | -moz-font-feature-settings: "tnum";
576 | -ms-font-feature-settings: "tnum";
577 | -webkit-font-feature-settings: "tnum";
578 | padding-left: 0.96667rem;
579 | padding-right: 0.96667rem;
580 | padding-top: 0.725rem;
581 | padding-bottom: calc(0.725rem - 1px);
582 | }
583 | th:first-child,
584 | td:first-child {
585 | padding-left: 0;
586 | }
587 | th:last-child,
588 | td:last-child {
589 | padding-right: 0;
590 | }
591 | tt,
592 | code {
593 | background-color: hsla(0, 0%, 0%, 0.04);
594 | border-radius: 3px;
595 | font-family: "SFMono-Regular", Consolas, "Roboto Mono", "Droid Sans Mono",
596 | "Liberation Mono", Menlo, Courier, monospace;
597 | padding: 0;
598 | padding-top: 0.2em;
599 | padding-bottom: 0.2em;
600 | }
601 | pre code {
602 | background: none;
603 | line-height: 1.42;
604 | }
605 | code:before,
606 | code:after,
607 | tt:before,
608 | tt:after {
609 | letter-spacing: -0.2em;
610 | content: " ";
611 | }
612 | pre code:before,
613 | pre code:after,
614 | pre tt:before,
615 | pre tt:after {
616 | content: "";
617 | }
618 | @media only screen and (max-width: 480px) {
619 | html {
620 | font-size: 100%;
621 | }
622 | }
623 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/src/components/layout.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Layout 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 PropTypes from "prop-types"
10 | import { useStaticQuery, graphql } from "gatsby"
11 |
12 | import Header from "./header"
13 | import "./layout.css"
14 |
15 | const Layout = ({ children }) => {
16 | const data = useStaticQuery(graphql`
17 | query SiteTitleQuery {
18 | site {
19 | siteMetadata {
20 | title
21 | }
22 | }
23 | }
24 | `)
25 |
26 | return (
27 | <>
28 |
29 |
36 |
{children}
37 |
38 | © {new Date().getFullYear()}, Built with
39 | {` `}
40 | Gatsby
41 |
42 |
43 | >
44 | )
45 | }
46 |
47 | Layout.propTypes = {
48 | children: PropTypes.node.isRequired,
49 | }
50 |
51 | export default Layout
52 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/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 | function SEO({ description, lang, meta, title }) {
14 | const { site } = useStaticQuery(
15 | graphql`
16 | query {
17 | site {
18 | siteMetadata {
19 | title
20 | description
21 | author
22 | }
23 | }
24 | }
25 | `
26 | )
27 |
28 | const metaDescription = description || site.siteMetadata.description
29 |
30 | return (
31 |
72 | )
73 | }
74 |
75 | SEO.defaultProps = {
76 | lang: `en`,
77 | meta: [],
78 | description: ``,
79 | }
80 |
81 | SEO.propTypes = {
82 | description: PropTypes.string,
83 | lang: PropTypes.string,
84 | meta: PropTypes.arrayOf(PropTypes.object),
85 | title: PropTypes.string.isRequired,
86 | }
87 |
88 | export default SEO
89 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/src/gatsby-theme-wordpress-gutenberg/components/blocks/core/column.js:
--------------------------------------------------------------------------------
1 | import React, { useContext } from "react"
2 | import { graphql } from "gatsby"
3 | import { GridCell } from "@rmwc/grid"
4 | import { ColumnsContext } from "./columns"
5 |
6 | import Block from "../../../../components/block"
7 |
8 | import "@rmwc/grid/styles"
9 |
10 | export const query = graphql`
11 | fragment Column on WpCoreColumnBlock {
12 | ...Block
13 | }
14 | `
15 |
16 | export default function Column(props) {
17 | const { children, attributes, ...rest } = props
18 | const { columns } = useContext(ColumnsContext)
19 |
20 | return (
21 |
22 | {children}
23 |
24 | )
25 | }
26 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/src/gatsby-theme-wordpress-gutenberg/components/blocks/core/columns.js:
--------------------------------------------------------------------------------
1 | import React, { useMemo } from "react"
2 | import { graphql } from "gatsby"
3 | import { Grid } from "@rmwc/grid"
4 |
5 | import Block from "../../../../components/block"
6 |
7 | import "@rmwc/grid/styles"
8 |
9 | export const query = graphql`
10 | fragment Columns on WpCoreColumnsBlock {
11 | ...Block
12 | }
13 | `
14 |
15 | export const ColumnsContext = React.createContext()
16 |
17 | export default function Columns(props) {
18 | const { children, ...rest } = props
19 |
20 | const value = useMemo(() => {
21 | const element = React.Children.toArray(children).pop()
22 |
23 | return {
24 | columns: element?.props?.blocks?.length || 0,
25 | }
26 | }, [children])
27 |
28 | return (
29 |
30 |
31 | {children}
32 |
33 |
34 | )
35 | }
36 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/src/gatsby-theme-wordpress-gutenberg/components/blocks/core/paragraph.js:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { graphql } from "gatsby"
3 |
4 | import Block from "../../../../components/block"
5 |
6 | import "@rmwc/tooltip/styles"
7 |
8 | export const query = graphql`
9 | fragment Paragraph on WpCoreParagraphBlock {
10 | ...Block
11 | attributes {
12 | ... on WpCoreParagraphBlockAttributes {
13 | content
14 | dropCap
15 | customBackgroundColor
16 | }
17 | }
18 | }
19 | `
20 |
21 | export default function Paragraph(props) {
22 | const { attributes } = props
23 |
24 | return (
25 |
26 |
35 |
36 | )
37 | }
38 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/src/gatsby-theme-wordpress-gutenberg/components/unknown-block.js:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { graphql } from "gatsby"
3 |
4 | import Block from "../../components/block"
5 |
6 | export const query = graphql`
7 | fragment UnknownBlock on WpBlock {
8 | ...Block
9 | saveContent
10 | }
11 | `
12 |
13 | export default function UnknownBlock(props) {
14 | const { saveContent } = props
15 |
16 | return (
17 |
18 |
19 |
20 | )
21 | }
22 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/src/images/gatsby-astronaut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GatsbyWPGutenberg/gatsby-wordpress-gutenberg/4bcd987b1a79f47849a7f3b97e2e0bbea673a022/examples/gatsby-wordpress-gutenberg-default-example/frontend/src/images/gatsby-astronaut.png
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/src/images/gatsby-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GatsbyWPGutenberg/gatsby-wordpress-gutenberg/4bcd987b1a79f47849a7f3b97e2e0bbea673a022/examples/gatsby-wordpress-gutenberg-default-example/frontend/src/images/gatsby-icon.png
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/src/pages/404.js:
--------------------------------------------------------------------------------
1 | import React from "react"
2 |
3 | import Layout from "../components/layout"
4 | import SEO from "../components/seo"
5 |
6 | const NotFoundPage = () => (
7 |
8 |
9 | NOT FOUND
10 | You just hit a route that doesn't exist... the sadness.
11 |
12 | )
13 |
14 | export default NotFoundPage
15 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/src/pages/index.js:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { Link, graphql } from "gatsby"
3 | import Layout from "../components/layout"
4 | import SEO from "../components/seo"
5 |
6 | export default function Home({ data }) {
7 | return (
8 |
9 |
10 | My WordPress Blog
11 | Posts
12 | {data.allWpPost.nodes.map(node => (
13 |
14 |
15 |
{node.title}
16 |
17 |
18 |
19 | ))}
20 |
21 | )
22 | }
23 |
24 | export const pageQuery = graphql`
25 | query {
26 | allWpPost(sort: { fields: [date] }) {
27 | nodes {
28 | title
29 | excerpt
30 | slug
31 | }
32 | }
33 | }
34 | `
35 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/src/pages/using-typescript.tsx:
--------------------------------------------------------------------------------
1 | // If you don't want to use TypeScript you can delete this file!
2 | import React from "react"
3 | import { PageProps, Link, graphql } from "gatsby"
4 |
5 | import Layout from "../components/layout"
6 | import SEO from "../components/seo"
7 |
8 | type DataProps = {
9 | site: {
10 | buildTime: string
11 | }
12 | }
13 |
14 | const UsingTypescript: React.FC> = ({ data, path }) => (
15 |
16 |
17 | Gatsby supports TypeScript by default!
18 | This means that you can create and write .ts/.tsx files for your pages, components etc. Please note that the gatsby-*.js files (like gatsby-node.js) currently don't support TypeScript yet.
19 | For type checking you'll want to install typescript via npm and run tsc --init to create a .tsconfig file.
20 | You're currently on the page "{path}" which was built on {data.site.buildTime}.
21 | To learn more, head over to our documentation about TypeScript .
22 | Go back to the homepage
23 |
24 | )
25 |
26 | export default UsingTypescript
27 |
28 | export const query = graphql`
29 | {
30 | site {
31 | buildTime(formatString: "YYYY-MM-DD hh:mm a z")
32 | }
33 | }
34 | `
35 |
--------------------------------------------------------------------------------
/examples/gatsby-wordpress-gutenberg-default-example/frontend/src/templates/blog-post.js:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import Layout from "../components/layout"
3 | import { graphql } from "gatsby"
4 |
5 | export default function BlogPost({ data }) {
6 | const post = data.allWpPost.nodes[0]
7 | console.log(post)
8 | return (
9 |
10 |
11 |
{post.title}
12 | {post.Blocks &&
}
13 |
14 |
15 | )
16 | }
17 | export const query = graphql`
18 | query($slug: String!) {
19 | allWpPost(filter: { slug: { eq: $slug } }) {
20 | nodes {
21 | title
22 | Blocks
23 | }
24 | }
25 | }
26 | `
27 |
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "npmClient": "yarn",
3 | "packages": [
4 | "examples/*",
5 | "examples/gatsby-wordpress-gutenberg-default-example/frontend",
6 | "packages/*"
7 | ],
8 | "version": "0.1.0",
9 | "useWorkspaces": true
10 | }
11 |
--------------------------------------------------------------------------------
/netlify.toml:
--------------------------------------------------------------------------------
1 | [build]
2 | # Directory to change to before starting a build.
3 | # This is where we will look for package.json/.nvmrc/etc.
4 | base = "docs/"
5 |
6 | # Directory (relative to root of your repo) that contains the deploy-ready
7 | # HTML files and assets generated by the build. If a base directory has
8 | # been specified, include it in the publish directory path.
9 | publish = "public/"
10 |
11 | # Default build command.
12 | command = "gatsby build"
13 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gatsby-wordpress-gutenberg",
3 | "version": "0.0.1",
4 | "description": "Gatsby WordPress Gutenberg Framework",
5 | "main": "packages/gatsby-source-wordpress-gutenberg/index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "private": true,
10 | "workspaces": [
11 | "examples/*",
12 | "examples/gatsby-wordpress-gutenberg-default-example/frontend",
13 | "packages/*"
14 | ],
15 | "contributors": [
16 | {
17 | "name": "Peter Pristas",
18 | "email": "pristas.peter@gmail.com",
19 | "url": "https://github.com/pristas-peter"
20 | },
21 | {
22 | "name": "Henrik Wirth",
23 | "url": "https://github.com/henrikwirth"
24 | }
25 | ],
26 | "license": "MIT",
27 | "devDependencies": {
28 | "@prettier/plugin-php": "^0.12.0",
29 | "lerna": "^3.20.2",
30 | "prettier": "^1.19.1"
31 | },
32 | "dependencies": {
33 | "eslint-config-google": "^0.14.0",
34 | "eslint-config-prettier": "^6.9.0",
35 | "eslint-plugin-filenames": "^1.3.2",
36 | "eslint-plugin-prettier": "^3.1.2",
37 | "typescript": "^3.9.5",
38 | "typescript-eslint": "^0.0.1-alpha.0"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/packages/gatsby-theme-wordpress-gutenberg/README.md:
--------------------------------------------------------------------------------
1 | # Gatsby Theme WordPress Gutenberg
2 |
3 | Use WordPress gutenberg editor as a page builder for your Gatsby site.
4 |
5 | ## Features
6 |
7 | - Render Gutenberg blocks with custom React components
8 | - Live preview in Gatsby and Gutenberg
9 | - Automatic React component generation based on post's content to keep bundle size small
10 |
11 | ## Example
12 |
13 | ### Querying
14 |
15 | > The `Blocks` component is a component which represents your structured content and is created during build phase. The post content is analyzed for all the blocks it contains and then the components which currently represent each block are consolidated into one component. This way, you only provide your custom implementations for each block and the magic of querying and sticking up the content together is done for you behind the scenes.
16 |
17 | ```js
18 | import React from "react"
19 | import Layout from "../components/layout"
20 | import { graphql } from "gatsby"
21 |
22 | export default function BlogPost({ data }) {
23 | const post = data.allWpPost.nodes[0]
24 | console.log(post)
25 | return (
26 |
27 |
28 |
{post.title}
29 | {/* Render post.Blocks instead of raw html content */}
30 | {post.Blocks &&
}
31 |
32 |
33 | )
34 | }
35 | export const query = graphql`
36 | query($slug: String!) {
37 | allWpPost(filter: { slug: { eq: $slug } }) {
38 | nodes {
39 | title
40 | Blocks ### query component as a graphql field
41 | }
42 | }
43 | }
44 | ```
45 |
46 | ### Custom block implementation
47 |
48 | > You can write your own custom block implementation for each block. Otherwise the default ` ` implementation is used.
49 |
50 | An example of custom Paragraph block:
51 |
52 | ```js
53 | import React from "react"
54 | import { graphql } from "gatsby"
55 |
56 | import Block from "../../../../components/block"
57 |
58 | import "@rmwc/tooltip/styles"
59 |
60 | export const query = graphql`
61 | fragment Paragraph on WpCoreParagraphBlock {
62 | ...Block
63 | attributes {
64 | ... on WpCoreParagraphBlockAttributes {
65 | content
66 | dropCap
67 | customBackgroundColor
68 | }
69 | }
70 | }
71 | `
72 |
73 | export default function Paragraph(props) {
74 | const { attributes } = props
75 |
76 | return (
77 |
78 |
87 |
88 | )
89 | }
90 | ```
91 |
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/packages/gatsby-theme-wordpress-gutenberg/gatsby-config.js:
--------------------------------------------------------------------------------
1 | module.exports = () => {
2 | return {
3 | plugins: [`gatsby-plugin-graphql-component`]
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/packages/gatsby-theme-wordpress-gutenberg/gatsby-node.js:
--------------------------------------------------------------------------------
1 | const { default: pluck } = require(`graphql-tag-pluck`)
2 | const { parse, Kind } = require(`graphql`)
3 | const path = require(`path`)
4 | const fs = require(`fs-extra`)
5 | const chokidar = require(`chokidar`)
6 | const { registerComponent, createResolverField } = require(`gatsby-plugin-graphql-component`)
7 |
8 | /**
9 | * - the component is autogenerated from querying sourced data - this way you only import/query blocks which are used in post's content
10 | * - the component file contains fragment definition on all the blocks/innerBlocks used in that post
11 |
12 | * - user / child theme can provide block component implemention, if not the default 'unknown-block.js' is used (uses dangerouslySetInnerHTML internally)
13 |
14 | * - user / child theme can create block component implementation inside its
15 | * src/gatsby-theme-wordpress-gutenberg/components/blocks/[block-name] folder
16 | * eq: src/gatsby-theme-wordpress-gutenberg/components/blocks/core/paragraph.[js,jsx,ts,tsx]
17 |
18 | * - the created component file should contain fragment definition on the block graphql type which will be
19 | * automatically imported into the generated component fragment
20 |
21 | /**
22 | * CONSTANTS
23 | */
24 |
25 | const PLUGIN_NAME = require(`./package.json`).name
26 | // we are using .cache/fragments folder for auto-generated stuff
27 | // because it is auto-watched by gatsby when it is parsing queries
28 | const BLOCKS_PATH = path.join(`.cache`, `fragments`, PLUGIN_NAME, `blocks`)
29 | const PAGES_PATH = path.join(`.cache`, `fragments`, PLUGIN_NAME, `pages`)
30 |
31 | const typenameToFieldName = ({ typename }) => typename.charAt(0).toLowerCase() + typename.slice(1)
32 |
33 | // creates fragment sdl for all blocks/innerBlocks
34 | const createFragment = ({ name, blockFragmentNames, innerBlocksLevel, asPreview }) => {
35 | const spreads = blockFragmentNames.map(blockFragmentName => `...${blockFragmentName}`)
36 |
37 | if (asPreview) {
38 | spreads.push(`previewUUID`)
39 | }
40 |
41 | // since we cannot create recursive fragment definition,
42 | // we have to statically analyse nesting count and generate proper fields selections
43 | const generate = (level = 0) => {
44 | let fragment = level === 0 ? `{ __typename ${spreads.join(` `)} ` : ` innerBlocks { __typename ${spreads.join(` `)}`
45 |
46 | if (level < innerBlocksLevel) {
47 | fragment += generate(level + 1)
48 | }
49 |
50 | fragment += ` }`
51 |
52 | return fragment
53 | }
54 |
55 | return `fragment ${name} on WpBlock ${generate()}`
56 | }
57 |
58 | // extracts graphql sdl from graphql`` tag inside component file
59 | const extractGraphql = async ({ componentPath }) => {
60 | try {
61 | const sdl = await pluck.fromFile(componentPath, {
62 | modules: [
63 | {
64 | name: `gatsby`,
65 | identifier: `graphql`,
66 | },
67 | ],
68 | })
69 |
70 | return parse(sdl)
71 | } catch (err) {
72 | return null
73 | }
74 | }
75 |
76 | // writes file to disk only on change/new file (avoids unnecessary rebuilds)
77 | const writeFile = async ({ filePath, data }) => {
78 | const oldData = await fs.readFile(filePath, `utf-8`).catch(() => null)
79 |
80 | if (oldData !== data) {
81 | await fs.outputFile(filePath, data)
82 | }
83 | }
84 |
85 | // resolves component path which will be used in our generated sources
86 | // uses same alghoritm as component shadowing so the component which
87 | // is closest to the user's project in the template hierarchy wins
88 | const resolveComponentPath = async ({ store, componentPath }) => {
89 | const extensions = [`.tsx`, `.ts`, `.mjs`, `.js`]
90 | const projectRoot = store.getState().program.directory
91 |
92 | // flattenedPlugins are already properly sorted accoridng to gatsby's template hierarchy
93 | // so the themes which use another themes are properly ordered
94 | const pluginPaths = store.getState().flattenedPlugins.map(flattenedPlugin => {
95 | if (flattenedPlugin.name === PLUGIN_NAME) {
96 | return path.join(flattenedPlugin.pluginFilepath, `src`)
97 | }
98 |
99 | return path.join(flattenedPlugin.pluginFilepath, `src`, `gatsby-theme-wordpress-gutenberg`)
100 | })
101 |
102 | // reverse reverses array in place, so we create a copy first
103 | const dirs = Array.from(new Set([projectRoot, ...[...pluginPaths].reverse()]))
104 |
105 | for (const dir of dirs) {
106 | const possiblePath = path.join(dir, componentPath)
107 |
108 | let exists = await fs.exists(possiblePath)
109 |
110 | if (exists) {
111 | return path
112 | }
113 |
114 | for (const extension of extensions) {
115 | const possiblePathWithExtension = `${possiblePath}${extension}`
116 |
117 | exists = await fs.exists(possiblePathWithExtension)
118 | if (exists) {
119 | return possiblePathWithExtension
120 | }
121 | }
122 | }
123 |
124 | return null
125 | }
126 |
127 | // resolves unknown component path
128 | // uses same alghoritm as component shadowing so the component which
129 | // is closest to the user's project in the template hierarchy wins
130 | const resolveUnknownComponentPath = options =>
131 | resolveComponentPath({
132 | ...options,
133 | componentPath: path.join(`components`, `unknown-block`),
134 | })
135 |
136 | // resolves block component path
137 | // uses same alghoritm as component shadowing so the component which
138 | // is closest to the user's project in the template hierarchy wins
139 | const resolveBlockComponentPath = async ({ blockName, ...options }) => {
140 | const possibleComponentPath = await resolveComponentPath({
141 | ...options,
142 | componentPath: path.join(`components`, `blocks`, blockName),
143 | })
144 |
145 | return possibleComponentPath
146 | }
147 |
148 | const extractBlockFragment = async ({ store, componentPath }) => {
149 | const document = await extractGraphql({ componentPath })
150 |
151 | if (document) {
152 | let fragment
153 |
154 | document.definitions.forEach(d => {
155 | if (d.kind === Kind.FRAGMENT_DEFINITION) {
156 | if (fragment) {
157 | const { directory } = store.getState().program
158 |
159 | throw new Error(
160 | `GraphQL Error: Block component file at '${path.relative(
161 | directory,
162 | componentPath
163 | )}' must contain only one fragment definition`
164 | )
165 | }
166 |
167 | fragment = d
168 | }
169 | })
170 |
171 | return fragment
172 | }
173 |
174 | return null
175 | }
176 |
177 | // visits all blocks
178 | // applies visitor pattern on every block
179 | // calculates and returns innerBlocks level
180 | const visitBlocks = async ({ blocks, visitor }) => {
181 | let innerBlocksLevel = 0
182 |
183 | const visitInnerBlock = async ({ innerBlock, currentInnerBlocksLevel }) => {
184 | innerBlocksLevel = Math.max(currentInnerBlocksLevel, innerBlocksLevel)
185 | const visitedBlock = await visitor({ block: innerBlock })
186 |
187 | if (visitedBlock.innerBlocks) {
188 | await Promise.all(
189 | visitedBlock.innerBlocks.map(async innerBlock => {
190 | await visitInnerBlock({ innerBlock, currentInnerBlocksLevel: currentInnerBlocksLevel + 1 })
191 | })
192 | )
193 | }
194 | }
195 |
196 | await Promise.all(
197 | blocks.map(async block => {
198 | const visitedBlock = await visitor({ block })
199 |
200 | await Promise.all(
201 | visitedBlock.innerBlocks.map(async innerBlock => {
202 | await visitInnerBlock({ innerBlock, currentInnerBlocksLevel: 1 })
203 | })
204 | )
205 | })
206 | )
207 |
208 | return innerBlocksLevel
209 | }
210 |
211 | const createBlockMatcher = () => {
212 | const cache = new Map()
213 | let unknownBlockData = null
214 |
215 | const match = async ({ block, ...options }) => {
216 | const { name, __typename } = block
217 |
218 | const cachedData = cache.get(name)
219 |
220 | if (cachedData) {
221 | return cachedData
222 | }
223 |
224 | let componentPath = await resolveBlockComponentPath({ ...options, blockName: name })
225 | let fragment
226 |
227 | if (!componentPath) {
228 | if (!unknownBlockData) {
229 | const unknownComponentPath = await resolveUnknownComponentPath(options)
230 |
231 | unknownBlockData = {
232 | componentPath: unknownComponentPath,
233 | fragment: await extractBlockFragment({ ...options, componentPath: unknownComponentPath }),
234 | }
235 | }
236 |
237 | componentPath = unknownBlockData.componentPath
238 | fragment = unknownBlockData.fragment
239 | } else {
240 | fragment = await extractBlockFragment({ ...options, componentPath })
241 | }
242 |
243 | const data = {
244 | componentPath,
245 | fragment,
246 | typename: `Wp${__typename}`,
247 | }
248 |
249 | cache.set(name, data)
250 | return data
251 | }
252 |
253 | match.cache = cache
254 | return match
255 | }
256 |
257 | const getBlockAtrributes = ({ block }) => {
258 | for (const key of Object.keys(block)) {
259 | if (key.startsWith(`attributes`)) {
260 | return block[key]
261 | }
262 | }
263 |
264 | return null
265 | }
266 |
267 | const createBlocksComponent = async ({ node, matchBlock, ...options }) => {
268 | const { store, getNodesByType } = options
269 |
270 | const asPreview = node.internal.type === `WpBlockEditorPreview`
271 |
272 | const componentByBlockName = new Map()
273 |
274 | const innerBlocksLevel = await visitBlocks({
275 | blocks: node.blocks,
276 | visitor: async ({ block }) => {
277 | componentByBlockName.set(block.name, await matchBlock({ ...options, block }))
278 |
279 | if (block.name === `core/block`) {
280 | const { ref } = getBlockAtrributes({ block })
281 |
282 | for (const reusableBlockNode of getNodesByType(`WpReusableBlock`)) {
283 | if (reusableBlockNode.databaseId === ref) {
284 | return {
285 | ...block,
286 | innerBlocks: reusableBlockNode.blocks,
287 | }
288 | }
289 | }
290 | }
291 |
292 | return block
293 | },
294 | })
295 |
296 | const fragmentName = `Blocks${node.databaseId}`
297 | const components = Array.from(componentByBlockName.values())
298 | const fieldName = typenameToFieldName({ typename: node.internal.type })
299 |
300 | const source = `/* eslint-disable */
301 | /* Warning: this file is autogerated, any changes would be lost */
302 | import React, { useMemo } from 'react'
303 | import { graphql, useStaticQuery } from 'gatsby'
304 |
305 | ${components.map(({ componentPath, typename }) => `import ${typename} from '${componentPath}'`).join(`\n`)}
306 |
307 | ${
308 | asPreview
309 | ? `
310 | const visitor = ({blocks, visit}) => {
311 |
312 | for (let block of blocks) {
313 | const result = visit({block})
314 |
315 | if (result || visitor({blocks: block.innerBlocks || [], visit})) {
316 | return true
317 | }
318 | }
319 |
320 | return false;
321 | }
322 | `
323 | : ``
324 | }
325 |
326 | const Blocks = ({ blocks = [], previewUUID }) => {
327 | return (
328 | <>
329 | {useMemo(() => {
330 | ${
331 | asPreview
332 | ? `
333 | if (!previewUUID) {
334 | return blocks
335 | }
336 |
337 | const result = []
338 |
339 | visitor({blocks, visit: ({block}) => {
340 | if (block.previewUUID === previewUUID) {
341 | result.push(block)
342 | return true
343 | }
344 |
345 | return false
346 | }})
347 |
348 | return result`
349 | : `
350 | return blocks`
351 | }
352 | }, [blocks, previewUUID]).map((block, i) => {
353 | const children = block.innerBlocks ? : null;
354 |
355 | ${components
356 | .map(
357 | ({ typename }) => `if (block.__typename === '${typename}') {
358 | return <${typename} {...block} children={children} key={i} />
359 | }`
360 | )
361 | .join(`\n `)}
362 |
363 | return null;
364 | })}
365 | >
366 | );
367 | };
368 |
369 | export default ({ previewUUID }) => {
370 |
371 | const { ${fieldName}: { blocks } } = useStaticQuery(graphql\`
372 | ${createFragment({
373 | name: fragmentName,
374 | blockFragmentNames: Array.from(
375 | new Set(components.map(({ fragment }) => fragment && fragment.name.value).filter(Boolean))
376 | ),
377 | innerBlocksLevel,
378 | asPreview,
379 | })}
380 | query {
381 | ${fieldName}(id: {eq: "${node.id}"}) {
382 | blocks {
383 | ...${fragmentName}
384 | }
385 | }
386 | }\`)
387 |
388 | return
389 | }
390 | `
391 | const outputFile = path.join(store.getState().program.directory, BLOCKS_PATH, `${node.id}.js`)
392 | await writeFile({ filePath: outputFile, data: source })
393 | return outputFile
394 | }
395 |
396 | const isNodeWithBlocks = ({ node }) => node.internal.owner.startsWith(`gatsby-source-wordpress`) && node.blocks
397 |
398 | /**
399 | * MODULE VARIABLES
400 | */
401 |
402 | // stores instance of chokidar watcher (for detecting changes through `develop` mode)
403 | let watcher
404 | //
405 | let matchBlock = createBlockMatcher()
406 |
407 | const previewPages = new Set()
408 |
409 | exports.onCreateNode = async (options, pluginOptions) => {
410 | const {
411 | node,
412 | actions: { createNodeField },
413 | } = options
414 |
415 | if (node.internal.owner.startsWith(`gatsby-source-wordpress`)) {
416 | if (isNodeWithBlocks({ node })) {
417 | createNodeField({
418 | node,
419 | name: `blocksComponent`,
420 | value: await registerComponent({
421 | component: await createBlocksComponent({ ...options, matchBlock }, pluginOptions),
422 | }),
423 | })
424 | }
425 | }
426 | }
427 |
428 | exports.createResolvers = async ({ createResolvers, getNodes, store }) => {
429 | const typenames = new Set([`WpBlockEditorPreview`])
430 | const blockTypenames = new Set()
431 |
432 | for (const type of store.getState().schemaCustomization.types) {
433 | const config = type.typeOrTypeDef && type.typeOrTypeDef.config
434 |
435 | if (config) {
436 | const interfaces = config && config.interfaces
437 |
438 | if (interfaces) {
439 | if (interfaces.includes(`WpBlockEditorContentNode`)) {
440 | typenames.add(config.name)
441 | } else if (interfaces.includes(`WpBlock`)) {
442 | blockTypenames.add(config.name)
443 | }
444 | }
445 | }
446 | }
447 |
448 | const resolvers = {}
449 |
450 | blockTypenames.forEach(type => {
451 | resolvers[type] = {
452 | innerBlocks: {
453 | resolve: async (block, args, context, info) => {
454 | if (block.name === `core/block`) {
455 | const { ref } = getBlockAtrributes({ block })
456 |
457 | const reusableBlock = await context.nodeModel.runQuery({
458 | query: {
459 | filter: {
460 | databaseId: {
461 | eq: ref,
462 | },
463 | },
464 | },
465 | type: `WpReusableBlock`,
466 | firstOnly: true,
467 | })
468 |
469 | if (!reusableBlock) {
470 | return null
471 | }
472 |
473 | context.nodeModel.trackPageDependencies(reusableBlock)
474 | return reusableBlock.blocks
475 | }
476 |
477 | return block.innerBlocks
478 | },
479 | },
480 | }
481 | })
482 |
483 | typenames.forEach(typename => {
484 | resolvers[typename] = {
485 | Blocks: createResolverField({
486 | resolve: async (node, args, context, info) => {
487 | if (node.fields) {
488 | context.nodeModel.trackPageDependencies(node.fields)
489 | }
490 |
491 | return node.fields && node.fields.blocksComponent
492 | },
493 | }),
494 | }
495 | })
496 |
497 | createResolvers(resolvers)
498 | }
499 |
500 | exports.createPages = async ({ getNodesByType, actions, store }, pluginOptions) => {
501 | const { createPage } = actions
502 |
503 | const nodes = getNodesByType(`WpBlockEditorPreview`)
504 | previewPages.clear()
505 |
506 | for (const node of nodes) {
507 | const component = path.join(store.getState().program.directory, PAGES_PATH, `${node.uri}.js`)
508 |
509 | await writeFile({
510 | filePath: component,
511 | data: `
512 | import React from "react"
513 | import { graphql, useStaticQuery } from "gatsby"
514 | import BlockPreview from "gatsby-theme-wordpress-gutenberg/src/components/previews/block-preview"
515 |
516 |
517 | export default props => {
518 | const data = useStaticQuery(graphql\`
519 | query GetThemeWordpressGutenbergBlockPreview${node.databaseId} {
520 | wpBlockEditorPreview(id: { eq: "${node.id}" }) {
521 | Blocks
522 | }
523 | }
524 | \`)
525 |
526 | const Blocks = data?.wpBlockEditorPreview?.Blocks
527 | return
528 | }
529 | `,
530 | })
531 |
532 | createPage({
533 | path: node.uri,
534 | component,
535 | })
536 |
537 | previewPages.add(node.uri)
538 | }
539 |
540 | if (nodes.length)
541 | setTimeout(() => {
542 | const time = new Date()
543 | fs.utimesSync(__filename, time, time)
544 | }, 0)
545 | }
546 |
547 | exports.createPagesStatefully = (options, pluginOptions) => {
548 | if (process.env.NODE_ENV === `development`) {
549 | if (watcher) {
550 | return
551 | }
552 |
553 | // to enhance developer experience we will track changes in all
554 | // child themes/root project's src/gatsby-theme-wordpress-gutenberg/{components/templates} and the theme itself
555 | // and regenerate source files upon change
556 | const {
557 | store,
558 | reporter,
559 | getNodes,
560 | actions: { createNodeField },
561 | } = options
562 |
563 | const program = store.getState().program
564 | const exts = program.extensions.map(e => `${e.slice(1)}`).join(`,`)
565 |
566 | const refresh = async () => {
567 | matchBlock = createBlockMatcher()
568 |
569 | for (const node of getNodes()) {
570 | if (isNodeWithBlocks({ node })) {
571 | createNodeField({
572 | node,
573 | name: `blocksComponent`,
574 | value: await registerComponent({
575 | component: await createBlocksComponent({ ...options, node, matchBlock }, pluginOptions),
576 | }),
577 | })
578 | }
579 | }
580 | }
581 |
582 | const cb = () => {
583 | // if we are already running return
584 | if (cb.current) {
585 | return
586 | }
587 |
588 | reporter.info(`Refreshing Blocks components`)
589 | cb.current = refresh()
590 | .catch(err => {
591 | reporter.error(err)
592 | })
593 | .finally(() => {
594 | cb.current = null
595 | })
596 | }
597 |
598 | watcher = chokidar
599 | .watch(
600 | store.getState().flattenedPlugins.map(flattenedPlugin => {
601 | const directoryPath = flattenedPlugin.pluginFilepath
602 | return `${directoryPath}/${
603 | flattenedPlugin.name === PLUGIN_NAME ? `src/` : `src/gatsby-theme-wordpress-gutenberg/`
604 | }components/**/*.{${exts}}`
605 | }),
606 | { ignoreInitial: true }
607 | )
608 | .on(`all`, cb)
609 | }
610 | }
611 |
612 | exports.onCreateDevServer = ({ app }) => {
613 | app.get("*", function (req, res, next) {
614 | if (previewPages.has(req.path)) {
615 | res.set("Access-Control-Expose-Headers", "X-Theme-Wordpress-Gutenberg-Preview-Page")
616 | res.set("X-Theme-Wordpress-Gutenberg-Preview-Page", "true")
617 | }
618 |
619 | next()
620 | })
621 | }
622 |
--------------------------------------------------------------------------------
/packages/gatsby-theme-wordpress-gutenberg/index.js:
--------------------------------------------------------------------------------
1 | // noop
2 |
--------------------------------------------------------------------------------
/packages/gatsby-theme-wordpress-gutenberg/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gatsby-theme-wordpress-gutenberg",
3 | "version": "0.1.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [
10 | "gatsby",
11 | "gatsby-plugin",
12 | "gatsby-theme",
13 | "wordpress",
14 | "gutenberg",
15 | "block-editor",
16 | "page-builder"
17 | ],
18 | "repository": {
19 | "type": "git",
20 | "url": "https://github.com/GatsbyWPGutenberg/gatsby-wordpress-gutenberg.git",
21 | "directory": "packages/gatsby-theme-wordpress-gutenberg"
22 | },
23 | "contributors": [
24 | {
25 | "name": "Peter Pristas",
26 | "email": "pristas.peter@gmail.com",
27 | "url": "https://github.com/pristas-peter"
28 | },
29 | {
30 | "name": "Henrik Wirth",
31 | "url": "https://github.com/henrikwirth"
32 | }
33 | ],
34 | "license": "MIT",
35 | "bugs": {
36 | "url": "https://github.com/GatsbyWPGutenberg/gatsby-wordpress-gutenberg/issues"
37 | },
38 | "homepage": "https://github.com/GatsbyWPGutenberg/gatsby-wordpress-gutenberg/#readme",
39 | "dependencies": {
40 | "fs-extra": "^9.0.1",
41 | "gatsby-page-utils": "^0.2.10",
42 | "gatsby-plugin-graphql-component": "^0.2.2",
43 | "graphql-tag-pluck": "^0.8.7",
44 | "humps": "^2.0.1",
45 | "jsonfile": "^6.0.1"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/packages/gatsby-theme-wordpress-gutenberg/src/components/blocks/core/block.js:
--------------------------------------------------------------------------------
1 | import { graphql } from "gatsby"
2 |
3 | export const query = graphql`
4 | fragment ThemeWordpressGutenbergCoreBlock on WpCoreBlock {
5 | __typename
6 | }
7 | `
8 | const CoreBlock = ({ children }) => {
9 | return children
10 | }
11 |
12 | export default CoreBlock
13 |
--------------------------------------------------------------------------------
/packages/gatsby-theme-wordpress-gutenberg/src/components/previews/block-preview.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react"
2 | import { createPortal } from "react-dom"
3 |
4 | export default ({ Blocks }) => {
5 | const [el, setEl] = useState(null)
6 | const [previewUUID, setPreviewUUID] = useState(null)
7 |
8 | useEffect(() => {
9 | const params = new URLSearchParams(window.location.search)
10 |
11 | const style = document.createElement("style")
12 | const div = document.createElement("div")
13 | div.setAttribute("id", "gatsby-gutenberg-block-preview")
14 |
15 | style.innerHTML = `
16 | .gatsby-theme-wordpress-gutenberg--hidden {
17 | display: none;
18 | }
19 | `
20 | document.head.appendChild(style)
21 |
22 | const elements = []
23 |
24 | document.body.childNodes.forEach(node => {
25 | if (node.nodeType === Node.ELEMENT_NODE) {
26 | node.classList.add("gatsby-theme-wordpress-gutenberg--hidden")
27 | elements.push(node)
28 | }
29 | })
30 |
31 | document.body.appendChild(div)
32 |
33 | setPreviewUUID(params.get("previewUUID"))
34 | setEl(div)
35 |
36 | return () => {
37 | if (div.parentNode) {
38 | div.parentNode.removeChild(div)
39 | }
40 |
41 | if (style.parentNode) {
42 | style.parentNode.removeChild(style)
43 | }
44 |
45 | elements.forEach(element => {
46 | element.classList.remove("gatsby-theme-wordpress-gutenberg--hidden")
47 | })
48 | }
49 | }, [])
50 |
51 | if (!el || !previewUUID) {
52 | return null
53 | }
54 |
55 | return createPortal(Blocks ? : null, el)
56 | }
57 |
--------------------------------------------------------------------------------
/packages/gatsby-theme-wordpress-gutenberg/src/components/unknown-block.js:
--------------------------------------------------------------------------------
1 | import React, { memo } from "react"
2 | import { graphql } from "gatsby"
3 |
4 | export const query = graphql`
5 | fragment ThemeWordpressGutenbergUnknownBlock on WpBlock {
6 | saveContent
7 | }
8 | `
9 |
10 | export default memo(({ saveContent }) =>
)
11 |
--------------------------------------------------------------------------------
/plugins/wp-gatsby-gutenberg/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['plugin:@wordpress/eslint-plugin/recommended'],
3 | rules: {
4 | 'prettier/prettier': 0,
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/plugins/wp-gatsby-gutenberg/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = require("@wordpress/scripts/config/.prettierrc.js");
2 |
--------------------------------------------------------------------------------
/plugins/wp-gatsby-gutenberg/build/0.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"] = window["webpackJsonp"] || []).push([[0],{
2 |
3 | /***/ "./src/Admin/settings.js":
4 | /*!*******************************!*\
5 | !*** ./src/Admin/settings.js ***!
6 | \*******************************/
7 | /*! exports provided: default */
8 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
9 |
10 | "use strict";
11 | __webpack_require__.r(__webpack_exports__);
12 | /* harmony default export */ __webpack_exports__["default"] = (function () {
13 | return 'Settings';
14 | });
15 |
16 | /***/ })
17 |
18 | }]);
19 | //# sourceMappingURL=0.js.map
--------------------------------------------------------------------------------
/plugins/wp-gatsby-gutenberg/build/0.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack:///./src/Admin/settings.js"],"names":[],"mappings":";;;;;;;;;;AAAA;AAAe,2EAAM;AACpB,SAAO,UAAP;AACA,CAFD,E","file":"0.js","sourcesContent":["export default () => {\n\treturn 'Settings';\n};\n"],"sourceRoot":""}
--------------------------------------------------------------------------------
/plugins/wp-gatsby-gutenberg/build/index.asset.php:
--------------------------------------------------------------------------------
1 | array('wp-api-fetch', 'wp-block-editor', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-polyfill'), 'version' => '8c623330a4d15a1dfeb92b2eb8ac8056');
--------------------------------------------------------------------------------
/plugins/wp-gatsby-gutenberg/build/index.js:
--------------------------------------------------------------------------------
1 | !function(e){var t={};function r(n){if(t[n])return t[n].exports;var c=t[n]={i:n,l:!1,exports:{}};return e[n].call(c.exports,c,c.exports,r),c.l=!0,c.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var c in e)r.d(n,c,function(t){return e[t]}.bind(null,c));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=13)}([function(e,t){!function(){e.exports=this.wp.element}()},function(e,t,r){var n=r(10),c=r(11),o=r(12);e.exports=function(e,t){return n(e)||c(e,t)||o()}},function(e,t){!function(){e.exports=this.wp.components}()},function(e,t){!function(){e.exports=this.wp.i18n}()},function(e,t){function r(){return e.exports=r=Object.assign||function(e){for(var t=1;t
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | packages/block-library/src/*
26 |
27 |
28 |
29 |
30 |
31 |
32 | ./gatsby-wordpress-gutenberg.php
33 | ./lib
34 |
35 | ./phpunit
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | gatsby-wordpress-gutenberg.php
44 |
45 |
46 |
47 |
48 | phpunit/*
49 |
50 |
51 | phpunit/*
52 |
53 |
54 | phpunit/*
55 |
56 |
57 | phpunit/*
58 |
59 |
60 | phpunit/*
61 |
62 |
63 | phpunit/*
64 |
65 |
66 | phpunit/*
67 |
68 |
69 | phpunit/*
70 |
71 |
--------------------------------------------------------------------------------
/plugins/wp-gatsby-gutenberg/plugin.php:
--------------------------------------------------------------------------------
1 | Settings::get_settings(),
23 | ]);
24 | }
25 |
26 | function __construct()
27 | {
28 | add_action('enqueue_block_editor_assets', function () {
29 | self::enqueue_script();
30 | });
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/plugins/wp-gatsby-gutenberg/src/Admin/Settings.php:
--------------------------------------------------------------------------------
1 |
28 |
38 | 'array',
49 | 'sanitize_callback' => function ($input) {
50 | $value = $input ?? [];
51 |
52 | $value['enable_live_preview'] =
53 | !empty($value['enable_live_preview']) &&
54 | $value['enable_live_preview'] === '1';
55 | return $value;
56 | },
57 | ]
58 | );
59 |
60 | add_settings_section('default', '', '', 'wp_gatsby_gutenberg');
61 |
62 | add_settings_field(
63 | 'enable_live_preview',
64 | __(
65 | 'Enable Gatsby Preview in Gutenberg?',
66 | 'wp-ga
67 | utenberg'
68 | ),
69 | function () {
70 | echo ' ' .
77 | __('Yes', 'wordpress');
78 | },
79 | 'wp_gatsby_gutenberg'
80 | );
81 | });
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/plugins/wp-gatsby-gutenberg/src/Preview/Preview.php:
--------------------------------------------------------------------------------
1 | post_type)->graphql_single_name ?? null;
32 |
33 | $graphql_endpoint = apply_filters('graphql_endpoint', 'graphql');
34 |
35 | $graphql_url = get_home_url() . '/' . ltrim($graphql_endpoint, '/');
36 |
37 | $post_body = [
38 | 'preview' => true,
39 | 'token' => $token,
40 | 'previewId' => $post_ID,
41 | 'id' => $global_relay_id,
42 | 'singleName' => lcfirst($referenced_node_single_name),
43 | 'isNewPostDraft' => false,
44 | 'isRevision' => false,
45 | 'remoteUrl' => $graphql_url,
46 | ];
47 |
48 | return wp_remote_post($preview_webhook, [
49 | 'body' => wp_json_encode($post_body),
50 | 'headers' => [
51 | 'Content-Type' => 'application/json; charset=utf-8',
52 | ],
53 | 'method' => 'POST',
54 | 'data_format' => 'body',
55 | ]);
56 | }
57 |
58 | public static function get_gatsby_preview_url($post_ID)
59 | {
60 | $post_type_object = \get_post_type_object(get_post_type($post_ID));
61 |
62 | $referenced_node_single_name = lcfirst(
63 | $post_type_object->graphql_single_name
64 | );
65 |
66 | $post_url = get_the_permalink($post_ID);
67 | $path = str_ireplace(get_home_url(), '', $post_url);
68 |
69 | if (strpos($path, '?')) {
70 | $path = "/$referenced_node_single_name/$post_ID";
71 | }
72 |
73 | $preview_url = \WPGatsby\Admin\Preview::get_gatsby_preview_instance_url();
74 | $preview_url = rtrim($preview_url, '/');
75 | return "$preview_url$path";
76 | }
77 |
78 | function __construct()
79 | {
80 | // this is a fix for node not resolving properly when revision
81 | // will be fixed in wp-graphql 0.10
82 | add_filter(
83 | 'graphql_resolve_node_type',
84 | function ($type, $node) {
85 | if ($type === null && $node instanceof Post) {
86 | if ('revision' === $node->post_type) {
87 | return get_post_type_object(
88 | get_post_type(get_post($node->ID)->post_parent)
89 | )->graphql_single_name ?? null;
90 | }
91 | }
92 |
93 | return $type;
94 | },
95 | 10,
96 | 2
97 | );
98 |
99 | add_action('graphql_register_types', function () {
100 | register_graphql_field('Block', 'previewUUID', [
101 | 'type' => 'String',
102 | 'description' => __(
103 | 'Preview UUID of the block',
104 | 'wp-gatsby-gutenberg'
105 | ),
106 | 'resolve' => function ($block) {
107 | return $block->attributes['wpGatsbyGutenbergUUID'];
108 | },
109 | ]);
110 | });
111 |
112 | add_action('rest_api_init', function () {
113 | register_rest_route('wp-gatsby-gutenberg/v1', '/previews/refresh', [
114 | 'methods' => 'POST',
115 | 'callback' => function (WP_REST_Request $request) {
116 | if (
117 | 'on' !==
118 | WPGatsbyPreview::get_setting('enable_gatsby_preview')
119 | ) {
120 | return new WP_Error(
121 | 400,
122 | __(
123 | 'Gatsby previews are not configured.',
124 | 'wp-gatsby-gutenberg'
125 | )
126 | );
127 | }
128 |
129 | if (!Settings::get_setting('enable_live_preview')) {
130 | return new WP_Error(
131 | 400,
132 | __(
133 | 'Gatsby Gutenberg previews are disabled.',
134 | 'wp-gatsby-gutenberg'
135 | )
136 | );
137 | }
138 |
139 | $id = BlockEditorPreview::get_preview_id(
140 | $request->get_param('postId'),
141 | $request->get_param('previewPostId')
142 | );
143 |
144 | if (empty($id)) {
145 | return new WP_Error(
146 | 400,
147 | __(
148 | 'Preview data for given post does not exist.',
149 | 'wp-gatsby-gutenberg'
150 | )
151 | );
152 | }
153 |
154 | $result = self::post_preview($id);
155 |
156 | if (is_wp_error($result)) {
157 | return $result;
158 | }
159 |
160 | return array_merge($result['response'], [
161 | 'gatsby_preview_url' => self::get_gatsby_preview_url(
162 | $id
163 | ),
164 | ]);
165 | },
166 | 'permission_callback' => function () {
167 | return current_user_can('edit_others_posts');
168 | },
169 | 'args' => [
170 | 'postId' => [
171 | 'required' => true,
172 | 'validate_callback' => 'is_numeric',
173 | ],
174 | 'previewPostId' => [
175 | 'required' => true,
176 | 'validate_callback' => 'is_numeric',
177 | ],
178 | ],
179 | ]);
180 | });
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/plugins/wp-gatsby-gutenberg/src/Preview/gatsby-block-preview.js:
--------------------------------------------------------------------------------
1 | import { Spinner, Button } from '@wordpress/components';
2 | import { useState, useEffect, useRef, useCallback } from '@wordpress/element';
3 | import { __ } from '@wordpress/i18n';
4 | import apiFetch from '@wordpress/api-fetch';
5 |
6 | export const useGatsbyBlockPreview = ( props ) => {
7 | const { postId, attributes, previewPostId, refresh } = props;
8 |
9 | const [ loading, setLoading ] = useState( false );
10 | const [ error, setError ] = useState( null );
11 | const [ data, setData ] = useState( null );
12 | const currentPromiseRef = useRef( null );
13 | const previousRefreshPreviewRef = useRef( null );
14 | const previousRefreshRef = useRef( null );
15 |
16 | const refreshPreview = useCallback( () => {
17 | setLoading( true );
18 | setError( null );
19 |
20 | const promise = apiFetch( {
21 | path: `/wp-gatsby-gutenberg/v1/previews/refresh`,
22 | method: `POST`,
23 | data: { postId, previewPostId },
24 | } )
25 | .then( ( data ) => {
26 | if ( promise === currentPromiseRef.current ) {
27 | setData( data );
28 | }
29 | } )
30 |
31 | .catch( ( error ) => {
32 | if ( promise === currentPromiseRef.current ) {
33 | setError( error );
34 | }
35 | } )
36 |
37 | .finally( () => {
38 | if ( promise === currentPromiseRef.current ) {
39 | setLoading( false );
40 | }
41 | } );
42 |
43 | currentPromiseRef.current = promise;
44 | return promise;
45 | }, [ postId, previewPostId, attributes, currentPromiseRef ] );
46 |
47 | useEffect( () => {
48 | if (
49 | refresh &&
50 | ( previousRefreshPreviewRef.current !== refreshPreview ||
51 | ( previousRefreshRef.current === false && error ) )
52 | ) {
53 | previousRefreshPreviewRef.current = refreshPreview;
54 |
55 | refreshPreview();
56 | }
57 |
58 | previousRefreshRef.current = refresh;
59 | }, [ refresh, refreshPreview ] );
60 |
61 | return {
62 | loading,
63 | data,
64 | error,
65 | retry: refreshPreview,
66 | previewUUID: attributes.wpGatsbyGutenbergUUID,
67 | };
68 | };
69 |
70 | const Loader = ( { style, message } ) => (
71 |
72 |
73 |
{ message }
74 |
75 | );
76 |
77 | const ErrorMessage = ( { style, retry, message } ) => (
78 |
79 |
{ message }
80 |
81 | { __( 'Retry' ) }
82 |
83 |
84 | );
85 |
86 | const Preview = ( { src, style } ) => {
87 | const [ pageReady, setPageReady ] = useState( false );
88 | const fetchPromiseRef = useRef( null );
89 | const timeoutRef = useRef( null );
90 | const mountedRef = useRef( true );
91 |
92 | const cleanup = useCallback( () => {
93 | if ( timeoutRef.current ) {
94 | clearTimeout( timeoutRef.current );
95 | timeoutRef.current = null;
96 | }
97 | }, [ timeoutRef ] );
98 |
99 | const check = useCallback( () => {
100 | cleanup();
101 |
102 | const promise = fetch( src )
103 | .then( ( response ) => {
104 | if ( fetchPromiseRef.current === promise ) {
105 | if (
106 | response &&
107 | response.headers.get(
108 | 'X-Theme-Wordpress-Gutenberg-Preview-Page'
109 | )
110 | ) {
111 | setPageReady( true );
112 | } else {
113 | return Promise.reject( new Error() );
114 | }
115 | }
116 | } )
117 | .catch( () => {
118 | if ( fetchPromiseRef.current === promise ) {
119 | timeoutRef.current = setTimeout( () => {
120 | if ( mountedRef.current ) {
121 | check();
122 | }
123 | }, 1500 );
124 | }
125 | } );
126 |
127 | fetchPromiseRef.current = promise;
128 |
129 | return promise;
130 | }, [ src, mountedRef ] );
131 |
132 | useEffect( () => {
133 | check();
134 |
135 | return () => {
136 | mountedRef.current = false;
137 | cleanup();
138 | };
139 | }, [] );
140 |
141 | if ( pageReady ) {
142 | return ;
143 | }
144 |
145 | return (
146 |
153 | );
154 | };
155 |
156 | const GatsbyBlockPreview = ( props ) => {
157 | const { loading, error, data, minHeight, previewUUID, retry } = props;
158 |
159 | const [ src, setSrc ] = useState( null );
160 |
161 | useEffect( () => {
162 | if ( data && data.gatsby_preview_url ) {
163 | const url = new URL( data.gatsby_preview_url );
164 | const search = new URLSearchParams( url.search );
165 | search.set( 'previewUUID', previewUUID );
166 | search.set( 'timestamp', new Date().getTime() );
167 |
168 | url.search = search;
169 |
170 | setSrc( url.href );
171 | }
172 | }, [ data, previewUUID ] );
173 |
174 | if ( loading ) {
175 | return (
176 |
183 | );
184 | }
185 |
186 | if ( error ) {
187 | return (
188 |
193 | );
194 | }
195 |
196 | return src ? : null;
197 | };
198 |
199 | export default GatsbyBlockPreview;
200 |
--------------------------------------------------------------------------------
/plugins/wp-gatsby-gutenberg/src/Preview/icon.js:
--------------------------------------------------------------------------------
1 | import { Icon as WpIcon } from '@wordpress/components';
2 |
3 | const Icon = ({ active }) => (
4 |
7 |
14 |
15 |
20 |
25 |
26 |
27 |
28 | }
29 | />
30 | );
31 |
32 | export default Icon;
33 |
--------------------------------------------------------------------------------
/plugins/wp-gatsby-gutenberg/src/Preview/preview.js:
--------------------------------------------------------------------------------
1 | /**
2 | * WordPress dependencies
3 | */
4 | import { __ } from '@wordpress/i18n';
5 | import {
6 | useContext,
7 | useState,
8 | createContext,
9 | useEffect,
10 | } from '@wordpress/element';
11 | import { useSelect } from '@wordpress/data';
12 | import { addFilter } from '@wordpress/hooks';
13 | import { Toolbar, Button } from '@wordpress/components';
14 | import { BlockControls } from '@wordpress/block-editor';
15 | import { v4 } from 'uuid';
16 |
17 | import PreviewIcon from './icon';
18 | import GatsbyBlockPreview, {
19 | useGatsbyBlockPreview,
20 | } from './gatsby-block-preview';
21 |
22 | const CoreBlockContext = createContext( null );
23 |
24 | addFilter(
25 | 'blocks.registerBlockType',
26 | 'wpGraphqlGutenberg.registerBlockType',
27 | ( blockType ) => {
28 | const result = {
29 | ...blockType,
30 | attributes: {
31 | ...blockType.attributes,
32 | wpGatsbyGutenbergUUID: {
33 | type: 'string',
34 | },
35 | },
36 | };
37 |
38 | return result;
39 | }
40 | );
41 |
42 | addFilter(
43 | 'blocks.getBlockAttributes',
44 | 'wpGraphqlGutenberg.getBlockAttributes',
45 | ( attributes ) => {
46 | if ( ! attributes.wpGatsbyGutenbergUUID ) {
47 | attributes.wpGatsbyGutenbergUUID = v4();
48 | }
49 |
50 | return attributes;
51 | }
52 | );
53 |
54 | addFilter(
55 | `editor.BlockEdit`,
56 | `plugin-wp-gatsby-gutenberg-preview/BlockEdit`,
57 | ( Edit ) => {
58 | return ( props ) => {
59 | const { attributes, setAttributes } = props;
60 |
61 | useEffect( () => {
62 | if ( ! attributes.wpGatsbyGutenbergUUID ) {
63 | setAttributes( { wpGatsbyGutenbergUUID: v4() } );
64 | }
65 | }, [ attributes ] );
66 |
67 | const enabled =
68 | window.wpGatsbyGutenberg &&
69 | window.wpGatsbyGutenberg.settings.enable_live_preview;
70 |
71 | const [ minHeight, setMinHeight ] = useState( 0 );
72 | const [ isPreviewActive, setIsPreviewActive ] = useState( false );
73 |
74 | const coreBlock = useContext( CoreBlockContext );
75 |
76 | const postId = useSelect(
77 | ( select ) => select( `core/editor` ).getCurrentPostId(),
78 | []
79 | );
80 |
81 | const coreBlockId =
82 | ( coreBlock &&
83 | coreBlock.attributes.ref &&
84 | parseInt( coreBlock.attributes.ref, 10 ) ) ||
85 | null;
86 |
87 | const gatsbyBlockPreview = useGatsbyBlockPreview( {
88 | ...props,
89 | refresh: isPreviewActive,
90 | postId: coreBlockId || postId,
91 | previewPostId: postId,
92 | } );
93 |
94 | if ( props.name === `core/block` ) {
95 | return (
96 |
97 |
98 |
99 | );
100 | }
101 |
102 | if ( enabled ) {
103 | return (
104 | <>
105 | { isPreviewActive ? (
106 |
110 | ) : (
111 |
112 | ) }
113 |
114 |
115 | {
119 | if ( ! isPreviewActive ) {
120 | const el = document.querySelector(
121 | `div[data-block="${ props.clientId }"]`
122 | );
123 |
124 | if ( el ) {
125 | setMinHeight( el.clientHeight );
126 | }
127 | }
128 |
129 | setIsPreviewActive( ! isPreviewActive );
130 | } }
131 | >
132 |
133 |
134 |
135 |
136 | >
137 | );
138 | }
139 |
140 | return ;
141 | };
142 | }
143 | );
144 |
--------------------------------------------------------------------------------
/plugins/wp-gatsby-gutenberg/src/index.js:
--------------------------------------------------------------------------------
1 | import './Preview/preview';
2 |
--------------------------------------------------------------------------------
/plugins/wp-gatsby-gutenberg/vendor/autoload.php:
--------------------------------------------------------------------------------
1 |
7 | * Jordi Boggiano
8 | *
9 | * For the full copyright and license information, please view the LICENSE
10 | * file that was distributed with this source code.
11 | */
12 |
13 | namespace Composer\Autoload;
14 |
15 | /**
16 | * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
17 | *
18 | * $loader = new \Composer\Autoload\ClassLoader();
19 | *
20 | * // register classes with namespaces
21 | * $loader->add('Symfony\Component', __DIR__.'/component');
22 | * $loader->add('Symfony', __DIR__.'/framework');
23 | *
24 | * // activate the autoloader
25 | * $loader->register();
26 | *
27 | * // to enable searching the include path (eg. for PEAR packages)
28 | * $loader->setUseIncludePath(true);
29 | *
30 | * In this example, if you try to use a class in the Symfony\Component
31 | * namespace or one of its children (Symfony\Component\Console for instance),
32 | * the autoloader will first look for the class under the component/
33 | * directory, and it will then fallback to the framework/ directory if not
34 | * found before giving up.
35 | *
36 | * This class is loosely based on the Symfony UniversalClassLoader.
37 | *
38 | * @author Fabien Potencier
39 | * @author Jordi Boggiano
40 | * @see http://www.php-fig.org/psr/psr-0/
41 | * @see http://www.php-fig.org/psr/psr-4/
42 | */
43 | class ClassLoader
44 | {
45 | // PSR-4
46 | private $prefixLengthsPsr4 = array();
47 | private $prefixDirsPsr4 = array();
48 | private $fallbackDirsPsr4 = array();
49 |
50 | // PSR-0
51 | private $prefixesPsr0 = array();
52 | private $fallbackDirsPsr0 = array();
53 |
54 | private $useIncludePath = false;
55 | private $classMap = array();
56 | private $classMapAuthoritative = false;
57 | private $missingClasses = array();
58 | private $apcuPrefix;
59 |
60 | public function getPrefixes()
61 | {
62 | if (!empty($this->prefixesPsr0)) {
63 | return call_user_func_array('array_merge', $this->prefixesPsr0);
64 | }
65 |
66 | return array();
67 | }
68 |
69 | public function getPrefixesPsr4()
70 | {
71 | return $this->prefixDirsPsr4;
72 | }
73 |
74 | public function getFallbackDirs()
75 | {
76 | return $this->fallbackDirsPsr0;
77 | }
78 |
79 | public function getFallbackDirsPsr4()
80 | {
81 | return $this->fallbackDirsPsr4;
82 | }
83 |
84 | public function getClassMap()
85 | {
86 | return $this->classMap;
87 | }
88 |
89 | /**
90 | * @param array $classMap Class to filename map
91 | */
92 | public function addClassMap(array $classMap)
93 | {
94 | if ($this->classMap) {
95 | $this->classMap = array_merge($this->classMap, $classMap);
96 | } else {
97 | $this->classMap = $classMap;
98 | }
99 | }
100 |
101 | /**
102 | * Registers a set of PSR-0 directories for a given prefix, either
103 | * appending or prepending to the ones previously set for this prefix.
104 | *
105 | * @param string $prefix The prefix
106 | * @param array|string $paths The PSR-0 root directories
107 | * @param bool $prepend Whether to prepend the directories
108 | */
109 | public function add($prefix, $paths, $prepend = false)
110 | {
111 | if (!$prefix) {
112 | if ($prepend) {
113 | $this->fallbackDirsPsr0 = array_merge(
114 | (array) $paths,
115 | $this->fallbackDirsPsr0
116 | );
117 | } else {
118 | $this->fallbackDirsPsr0 = array_merge(
119 | $this->fallbackDirsPsr0,
120 | (array) $paths
121 | );
122 | }
123 |
124 | return;
125 | }
126 |
127 | $first = $prefix[0];
128 | if (!isset($this->prefixesPsr0[$first][$prefix])) {
129 | $this->prefixesPsr0[$first][$prefix] = (array) $paths;
130 |
131 | return;
132 | }
133 | if ($prepend) {
134 | $this->prefixesPsr0[$first][$prefix] = array_merge(
135 | (array) $paths,
136 | $this->prefixesPsr0[$first][$prefix]
137 | );
138 | } else {
139 | $this->prefixesPsr0[$first][$prefix] = array_merge(
140 | $this->prefixesPsr0[$first][$prefix],
141 | (array) $paths
142 | );
143 | }
144 | }
145 |
146 | /**
147 | * Registers a set of PSR-4 directories for a given namespace, either
148 | * appending or prepending to the ones previously set for this namespace.
149 | *
150 | * @param string $prefix The prefix/namespace, with trailing '\\'
151 | * @param array|string $paths The PSR-4 base directories
152 | * @param bool $prepend Whether to prepend the directories
153 | *
154 | * @throws \InvalidArgumentException
155 | */
156 | public function addPsr4($prefix, $paths, $prepend = false)
157 | {
158 | if (!$prefix) {
159 | // Register directories for the root namespace.
160 | if ($prepend) {
161 | $this->fallbackDirsPsr4 = array_merge(
162 | (array) $paths,
163 | $this->fallbackDirsPsr4
164 | );
165 | } else {
166 | $this->fallbackDirsPsr4 = array_merge(
167 | $this->fallbackDirsPsr4,
168 | (array) $paths
169 | );
170 | }
171 | } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
172 | // Register directories for a new namespace.
173 | $length = strlen($prefix);
174 | if ('\\' !== $prefix[$length - 1]) {
175 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
176 | }
177 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
178 | $this->prefixDirsPsr4[$prefix] = (array) $paths;
179 | } elseif ($prepend) {
180 | // Prepend directories for an already registered namespace.
181 | $this->prefixDirsPsr4[$prefix] = array_merge(
182 | (array) $paths,
183 | $this->prefixDirsPsr4[$prefix]
184 | );
185 | } else {
186 | // Append directories for an already registered namespace.
187 | $this->prefixDirsPsr4[$prefix] = array_merge(
188 | $this->prefixDirsPsr4[$prefix],
189 | (array) $paths
190 | );
191 | }
192 | }
193 |
194 | /**
195 | * Registers a set of PSR-0 directories for a given prefix,
196 | * replacing any others previously set for this prefix.
197 | *
198 | * @param string $prefix The prefix
199 | * @param array|string $paths The PSR-0 base directories
200 | */
201 | public function set($prefix, $paths)
202 | {
203 | if (!$prefix) {
204 | $this->fallbackDirsPsr0 = (array) $paths;
205 | } else {
206 | $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
207 | }
208 | }
209 |
210 | /**
211 | * Registers a set of PSR-4 directories for a given namespace,
212 | * replacing any others previously set for this namespace.
213 | *
214 | * @param string $prefix The prefix/namespace, with trailing '\\'
215 | * @param array|string $paths The PSR-4 base directories
216 | *
217 | * @throws \InvalidArgumentException
218 | */
219 | public function setPsr4($prefix, $paths)
220 | {
221 | if (!$prefix) {
222 | $this->fallbackDirsPsr4 = (array) $paths;
223 | } else {
224 | $length = strlen($prefix);
225 | if ('\\' !== $prefix[$length - 1]) {
226 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
227 | }
228 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
229 | $this->prefixDirsPsr4[$prefix] = (array) $paths;
230 | }
231 | }
232 |
233 | /**
234 | * Turns on searching the include path for class files.
235 | *
236 | * @param bool $useIncludePath
237 | */
238 | public function setUseIncludePath($useIncludePath)
239 | {
240 | $this->useIncludePath = $useIncludePath;
241 | }
242 |
243 | /**
244 | * Can be used to check if the autoloader uses the include path to check
245 | * for classes.
246 | *
247 | * @return bool
248 | */
249 | public function getUseIncludePath()
250 | {
251 | return $this->useIncludePath;
252 | }
253 |
254 | /**
255 | * Turns off searching the prefix and fallback directories for classes
256 | * that have not been registered with the class map.
257 | *
258 | * @param bool $classMapAuthoritative
259 | */
260 | public function setClassMapAuthoritative($classMapAuthoritative)
261 | {
262 | $this->classMapAuthoritative = $classMapAuthoritative;
263 | }
264 |
265 | /**
266 | * Should class lookup fail if not found in the current class map?
267 | *
268 | * @return bool
269 | */
270 | public function isClassMapAuthoritative()
271 | {
272 | return $this->classMapAuthoritative;
273 | }
274 |
275 | /**
276 | * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
277 | *
278 | * @param string|null $apcuPrefix
279 | */
280 | public function setApcuPrefix($apcuPrefix)
281 | {
282 | $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
283 | }
284 |
285 | /**
286 | * The APCu prefix in use, or null if APCu caching is not enabled.
287 | *
288 | * @return string|null
289 | */
290 | public function getApcuPrefix()
291 | {
292 | return $this->apcuPrefix;
293 | }
294 |
295 | /**
296 | * Registers this instance as an autoloader.
297 | *
298 | * @param bool $prepend Whether to prepend the autoloader or not
299 | */
300 | public function register($prepend = false)
301 | {
302 | spl_autoload_register(array($this, 'loadClass'), true, $prepend);
303 | }
304 |
305 | /**
306 | * Unregisters this instance as an autoloader.
307 | */
308 | public function unregister()
309 | {
310 | spl_autoload_unregister(array($this, 'loadClass'));
311 | }
312 |
313 | /**
314 | * Loads the given class or interface.
315 | *
316 | * @param string $class The name of the class
317 | * @return bool|null True if loaded, null otherwise
318 | */
319 | public function loadClass($class)
320 | {
321 | if ($file = $this->findFile($class)) {
322 | includeFile($file);
323 |
324 | return true;
325 | }
326 | }
327 |
328 | /**
329 | * Finds the path to the file where the class is defined.
330 | *
331 | * @param string $class The name of the class
332 | *
333 | * @return string|false The path if found, false otherwise
334 | */
335 | public function findFile($class)
336 | {
337 | // class map lookup
338 | if (isset($this->classMap[$class])) {
339 | return $this->classMap[$class];
340 | }
341 | if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
342 | return false;
343 | }
344 | if (null !== $this->apcuPrefix) {
345 | $file = apcu_fetch($this->apcuPrefix.$class, $hit);
346 | if ($hit) {
347 | return $file;
348 | }
349 | }
350 |
351 | $file = $this->findFileWithExtension($class, '.php');
352 |
353 | // Search for Hack files if we are running on HHVM
354 | if (false === $file && defined('HHVM_VERSION')) {
355 | $file = $this->findFileWithExtension($class, '.hh');
356 | }
357 |
358 | if (null !== $this->apcuPrefix) {
359 | apcu_add($this->apcuPrefix.$class, $file);
360 | }
361 |
362 | if (false === $file) {
363 | // Remember that this class does not exist.
364 | $this->missingClasses[$class] = true;
365 | }
366 |
367 | return $file;
368 | }
369 |
370 | private function findFileWithExtension($class, $ext)
371 | {
372 | // PSR-4 lookup
373 | $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
374 |
375 | $first = $class[0];
376 | if (isset($this->prefixLengthsPsr4[$first])) {
377 | $subPath = $class;
378 | while (false !== $lastPos = strrpos($subPath, '\\')) {
379 | $subPath = substr($subPath, 0, $lastPos);
380 | $search = $subPath . '\\';
381 | if (isset($this->prefixDirsPsr4[$search])) {
382 | $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
383 | foreach ($this->prefixDirsPsr4[$search] as $dir) {
384 | if (file_exists($file = $dir . $pathEnd)) {
385 | return $file;
386 | }
387 | }
388 | }
389 | }
390 | }
391 |
392 | // PSR-4 fallback dirs
393 | foreach ($this->fallbackDirsPsr4 as $dir) {
394 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
395 | return $file;
396 | }
397 | }
398 |
399 | // PSR-0 lookup
400 | if (false !== $pos = strrpos($class, '\\')) {
401 | // namespaced class name
402 | $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
403 | . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
404 | } else {
405 | // PEAR-like class name
406 | $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
407 | }
408 |
409 | if (isset($this->prefixesPsr0[$first])) {
410 | foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
411 | if (0 === strpos($class, $prefix)) {
412 | foreach ($dirs as $dir) {
413 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
414 | return $file;
415 | }
416 | }
417 | }
418 | }
419 | }
420 |
421 | // PSR-0 fallback dirs
422 | foreach ($this->fallbackDirsPsr0 as $dir) {
423 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
424 | return $file;
425 | }
426 | }
427 |
428 | // PSR-0 include paths.
429 | if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
430 | return $file;
431 | }
432 |
433 | return false;
434 | }
435 | }
436 |
437 | /**
438 | * Scope isolated include.
439 | *
440 | * Prevents access to $this/self from included files.
441 | */
442 | function includeFile($file)
443 | {
444 | include $file;
445 | }
446 |
--------------------------------------------------------------------------------
/plugins/wp-gatsby-gutenberg/vendor/composer/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Copyright (c) Nils Adermann, Jordi Boggiano
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is furnished
9 | to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in all
12 | copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 |
22 |
--------------------------------------------------------------------------------
/plugins/wp-gatsby-gutenberg/vendor/composer/autoload_classmap.php:
--------------------------------------------------------------------------------
1 | $baseDir . '/src/Admin/Editor.php',
10 | 'WPGatsbyGutenberg\\Admin\\Settings' => $baseDir . '/src/Admin/Settings.php',
11 | 'WPGatsbyGutenberg\\Preview\\Preview' => $baseDir . '/src/Preview/Preview.php',
12 | );
13 |
--------------------------------------------------------------------------------
/plugins/wp-gatsby-gutenberg/vendor/composer/autoload_namespaces.php:
--------------------------------------------------------------------------------
1 | array($baseDir . '/src'),
10 | );
11 |
--------------------------------------------------------------------------------
/plugins/wp-gatsby-gutenberg/vendor/composer/autoload_real.php:
--------------------------------------------------------------------------------
1 | = 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
30 | if ($useStaticLoader) {
31 | require_once __DIR__ . '/autoload_static.php';
32 |
33 | call_user_func(\Composer\Autoload\ComposerStaticInit0cfb58398052e50dda3e9dded49931ac::getInitializer($loader));
34 | } else {
35 | $map = require __DIR__ . '/autoload_namespaces.php';
36 | foreach ($map as $namespace => $path) {
37 | $loader->set($namespace, $path);
38 | }
39 |
40 | $map = require __DIR__ . '/autoload_psr4.php';
41 | foreach ($map as $namespace => $path) {
42 | $loader->setPsr4($namespace, $path);
43 | }
44 |
45 | $classMap = require __DIR__ . '/autoload_classmap.php';
46 | if ($classMap) {
47 | $loader->addClassMap($classMap);
48 | }
49 | }
50 |
51 | $loader->register(true);
52 |
53 | return $loader;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/plugins/wp-gatsby-gutenberg/vendor/composer/autoload_static.php:
--------------------------------------------------------------------------------
1 |
11 | array (
12 | 'GatsbyWordpressGutenberg\\' => 25,
13 | ),
14 | );
15 |
16 | public static $prefixDirsPsr4 = array (
17 | 'GatsbyWordpressGutenberg\\' =>
18 | array (
19 | 0 => __DIR__ . '/../..' . '/src',
20 | ),
21 | );
22 |
23 | public static $classMap = array (
24 | 'WPGatsbyGutenberg\\Admin\\Editor' => __DIR__ . '/../..' . '/src/Admin/Editor.php',
25 | 'WPGatsbyGutenberg\\Admin\\Settings' => __DIR__ . '/../..' . '/src/Admin/Settings.php',
26 | 'WPGatsbyGutenberg\\Preview\\Preview' => __DIR__ . '/../..' . '/src/Preview/Preview.php',
27 | );
28 |
29 | public static function getInitializer(ClassLoader $loader)
30 | {
31 | return \Closure::bind(function () use ($loader) {
32 | $loader->prefixLengthsPsr4 = ComposerStaticInit0cfb58398052e50dda3e9dded49931ac::$prefixLengthsPsr4;
33 | $loader->prefixDirsPsr4 = ComposerStaticInit0cfb58398052e50dda3e9dded49931ac::$prefixDirsPsr4;
34 | $loader->classMap = ComposerStaticInit0cfb58398052e50dda3e9dded49931ac::$classMap;
35 |
36 | }, null, ClassLoader::class);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------