├── .eslintignore ├── .eslintrc.json ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── support_request.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .npmrc ├── changelog.md ├── code-of-conduct.md ├── contributing.md ├── examples ├── 01-single-block │ ├── .editorconfig │ ├── .eslintignore │ ├── .eslintrc.json │ ├── .gitignore │ ├── README.md │ ├── dist │ │ ├── blocks.build.js │ │ ├── blocks.editor.build.css │ │ └── blocks.style.build.css │ ├── plugin.php │ └── src │ │ ├── block │ │ ├── block.js │ │ ├── editor.scss │ │ └── style.scss │ │ ├── blocks.js │ │ ├── common.scss │ │ └── init.php ├── 02-single-block-ejected │ ├── .editorconfig │ ├── .eslintignore │ ├── .eslintrc.json │ ├── .gitignore │ ├── README.md │ ├── config │ │ ├── paths.js │ │ ├── webpack.config.dev.js │ │ └── webpack.config.prod.js │ ├── dist │ │ ├── blocks.build.js │ │ ├── blocks.editor.build.css │ │ └── blocks.style.build.css │ ├── plugin.php │ ├── scripts │ │ ├── build.js │ │ └── start.js │ └── src │ │ ├── block │ │ ├── block.js │ │ ├── editor.scss │ │ └── style.scss │ │ ├── blocks.js │ │ ├── common.scss │ │ └── init.php ├── 03-multi-block │ ├── .editorconfig │ ├── .eslintignore │ ├── .eslintrc.json │ ├── .gitignore │ ├── README.md │ ├── dist │ │ ├── blocks.build.js │ │ ├── blocks.editor.build.css │ │ └── blocks.style.build.css │ ├── plugin.php │ └── src │ │ ├── block │ │ ├── block.js │ │ ├── editor.scss │ │ └── style.scss │ │ ├── block2 │ │ ├── block.js │ │ ├── editor.scss │ │ └── style.scss │ │ ├── blocks.js │ │ ├── common.scss │ │ └── init.php ├── 04-multi-block-ejected │ ├── .editorconfig │ ├── .eslintignore │ ├── .eslintrc.json │ ├── .gitignore │ ├── README.md │ ├── config │ │ ├── paths.js │ │ ├── webpack.config.dev.js │ │ └── webpack.config.prod.js │ ├── dist │ │ ├── blocks.build.js │ │ ├── blocks.editor.build.css │ │ └── blocks.style.build.css │ ├── plugin.php │ ├── scripts │ │ ├── build.js │ │ └── start.js │ └── src │ │ ├── block │ │ ├── block.js │ │ ├── editor.scss │ │ └── style.scss │ │ ├── block2 │ │ ├── block.js │ │ ├── editor.scss │ │ └── style.scss │ │ ├── blocks.js │ │ ├── common.scss │ │ └── init.php ├── 05-a11y-input │ ├── .editorconfig │ ├── .eslintignore │ ├── .eslintrc.json │ ├── .gitignore │ ├── README.md │ ├── dist │ │ ├── blocks.build.js │ │ ├── blocks.editor.build.css │ │ └── blocks.style.build.css │ ├── plugin.php │ └── src │ │ ├── block │ │ ├── block.js │ │ ├── editor.scss │ │ └── style.scss │ │ ├── blocks.js │ │ ├── common.scss │ │ └── init.php └── README.md ├── lerna.json ├── license ├── package.json ├── packages ├── babel-preset-cgb │ ├── .gitignore │ ├── .npmrc │ ├── README.md │ ├── index.js │ └── package.json ├── cgb-dev-utils │ ├── .babelrc │ ├── .gitignore │ ├── .npmrc │ ├── README.md │ ├── clearConsole.js │ ├── crossSpawn.js │ ├── formatWebpackMessages.js │ └── package.json ├── cgb-scripts │ ├── .gitignore │ ├── .npmrc │ ├── README.MD │ ├── bin │ │ └── cgb-scripts.js │ ├── config │ │ ├── externals.js │ │ ├── paths.js │ │ ├── webpack.config.dev.js │ │ └── webpack.config.prod.js │ ├── package.json │ ├── scripts │ │ ├── block.js │ │ ├── build.js │ │ ├── eject.js │ │ ├── init.js │ │ ├── start.js │ │ ├── test.js │ │ └── translate.js │ └── template │ │ ├── .editorconfig │ │ ├── .eslintignore │ │ ├── .eslintrc.json │ │ ├── .gitignore │ │ ├── dist │ │ ├── blocks.build.js │ │ ├── blocks.editor.build.css │ │ └── blocks.style.build.css │ │ ├── plugin.php │ │ ├── readme.md │ │ └── src │ │ ├── block │ │ ├── block.js │ │ ├── editor.scss │ │ └── style.scss │ │ ├── blocks.js │ │ ├── common.scss │ │ └── init.php └── create-guten-block │ ├── .eslintignore │ ├── .eslintrc.json │ ├── .gitignore │ ├── .npmrc │ ├── README.md │ ├── app │ ├── cli.js │ ├── consoleClear.js │ ├── createGitignore.js │ ├── createPluginDir.js │ ├── envInfo.js │ ├── getBlockDir.js │ ├── initBlock.js │ ├── invalidBlockName.js │ ├── noBlockName.js │ ├── npmInstallScripts.js │ ├── prePrint.js │ ├── run.js │ ├── test.js │ └── updateNotifier.js │ ├── index.js │ └── package.json ├── plugins.md ├── readme.md └── tasks ├── cgb.js ├── publish.sh └── replace-own-deps.js /.eslintignore: -------------------------------------------------------------------------------- 1 | **/node_modules/** 2 | **/vendor/** 3 | **/block.build.js 4 | **/*.min.js -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | # github: [ahmadawais] 4 | custom: ['https://Awais.dev/sponsor-USD-10-pm', 'https://Awais.dev/sponsor-USD-10', 'https://Awais.dev/sponsor-USD-100', 'https://Awais.dev/sponsor-USD-50'] 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🐛 BUG REPORT 3 | about: If something isn't working as expected. 🤔 4 | 5 | --- 6 | 7 | 16 | 17 | ## Bug Report 18 | 19 | ### Expected Behavior 20 | 21 | 26 | 27 | (Write what you thought would happen.) 28 | 29 | 30 | ### Actual Behavior 31 | 32 | 37 | 38 | (Write what happened. Please add screenshots!) 39 | 40 | 41 | ### Steps to Reproduce 42 | 43 | 47 | 48 | (Write your steps here:) 49 | 50 | 1. 51 | 2. 52 | 3. 53 | 54 | 57 | 58 | 1. `node -v`: 59 | 2. `npm -v`: 60 | 3. `yarn --version` (if you use Yarn): 61 | 4. `npm ls cgb-scripts` (if you haven’t ejected): 62 | 63 | Then, specify: 64 | 65 | 1. Operating system: 66 | 2. Browser and version (if relevant): 67 | 68 | **Possible Solution** 69 | 70 | 71 | ### Reproducible Demo 72 | 73 | 88 | 89 | (Paste the link to an example project and exact instructions to reproduce the issue.) 90 | 91 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🚀 FEATURE REQUEST 3 | about: I have a suggestion (and may want to implement it)! 🙂 4 | 5 | --- 6 | 7 | ## Feature Request 8 | 9 | **Is your feature request related to a problem? Please describe.** 10 | A clear and concise description of what the problem is. Ex. I have an issue when [...] 11 | 12 | **Describe the solution you'd like** 13 | A clear and concise description of what you want to happen. Add any considered drawbacks. 14 | 15 | **Describe alternatives you've considered** 16 | A clear and concise description of any alternative solutions or features you've considered. 17 | 18 | **Teachability, Documentation, Adoption, Migration Strategy** 19 | If you can, explain how users will be able to use this and possibly write out a version the docs. Maybe a screenshot or design? 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/support_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🤝 SUPPORT QUESTION 3 | about: If you have a support question! 💬 4 | 5 | --- 6 | 7 | -----------^ Click "Preview" for a nicer view! 8 | 9 | This is a FOSS (Free & Open Source Software) project. Providing support is a full-time job and so it's not provided for free. No promises there. 😇 10 | 11 | If you'd like to support this project or hire [Ahmad Awais](https://twitter.com/mrahmadawais/) (maker of `create-guten-block`) then feel free to contact here → https://AhmadAwais.com/contact/. 12 | 13 | 14 | --- 15 | 16 | If you'd like us to keep producing professional free and open source software (FOSS). Consider paying for an hour of our dev-time. We'll spend two hours on open source for each contribution. Yeah, that's right, you pay for one hour and get both of us (Awais & Maedah) to spend an hour as a thank you. 17 | 18 | 🚀 $99.99 — [Support for one hour or more →](https://pay.paddle.com/checkout/515568) 19 | 🔰 $49.99 — [Support half an hour maintenance →](https://pay.paddle.com/checkout/527253) 20 | ☕️ $9.99 — [Buy us lunch or coffee to keep us trucking #OpenSource →](https://pay.paddle.com/checkout/527254) -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Packages # 2 | ############ 3 | *.7z 4 | *.dmg 5 | *.gz 6 | *.bz2 7 | *.iso 8 | *.jar 9 | *.rar 10 | *.tar 11 | *.zip 12 | *.tgz 13 | *.map 14 | 15 | # Logs and databases # 16 | ###################### 17 | *.log 18 | *.sql 19 | 20 | # OS generated files # 21 | ###################### 22 | **.DS_Store* 23 | ehthumbs.db 24 | Icon? 25 | Thumbs.db 26 | ._* 27 | 28 | # Vim generated files # 29 | ###################### 30 | *.un~ 31 | 32 | # SASS # 33 | ########## 34 | **/.sass-cache 35 | **/.sass-cache/* 36 | **/.map 37 | 38 | # Composer # 39 | ########## 40 | vendors/composer/ 41 | !assets/js/vendor/ 42 | wpcs/ 43 | composer.lock 44 | 45 | # Bower # 46 | ########## 47 | assets/bower_components/* 48 | 49 | # Codekit # 50 | ########## 51 | /codekit-config.json 52 | *.codekit 53 | **.codekit-cache/* 54 | 55 | # NPM # 56 | ########## 57 | node_modules 58 | **/node_modules/** 59 | 60 | # Compiled Files and Build Dirs # 61 | ########## 62 | /README.html 63 | 64 | # PhpStrom Project Files # 65 | .idea/ 66 | library/vendors/composer 67 | assets/img/.DS_Store 68 | assets/sass/HTML 69 | assets/sass/Rails 70 | HTML 71 | Rails 72 | 73 | # CGB 74 | .idea/ 75 | .vscode/ 76 | node_modules/ 77 | .DS_Store 78 | *.tgz 79 | my-app* 80 | template/src/__tests__/__snapshots__/ 81 | lerna-debug.log 82 | npm-debug.log* 83 | yarn-debug.log* 84 | yarn-error.log* 85 | /.changelog 86 | /examples/**/package-lock.json 87 | settings.dat 88 | yarn.lock 89 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /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 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at me@AhmadAwais.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [https://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: https://contributor-covenant.org 74 | [version]: https://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /contributing.md: -------------------------------------------------------------------------------- 1 | # CONTRIBUTING to `create-guten-block` 2 | 3 | First of all, I'd like to welcome you for thinking about contributing to this project. I'd rather explain the flow of this project and explain all that in a later release. 4 | 5 | ## 🔥 TL;DR 6 | 7 | - Git Clone `git clone https://github.com/ahmadawais/create-guten-block/` 8 | - `yarn` 9 | - `yarn create-guten-block demo-block` 10 | - `yarn updated` 11 | 12 | ## 📖 Details 13 | 14 | - `git clone https://github.com/ahmadawais/create-guten-block/` 15 | - `yarn` or `sudo yarn` 16 | - Installs all the node packages and deps/devDeps in all the workspaces. 17 | - `yarn create-guten-block demo-block` 18 | - This will run `tasks/cgb.js` file 19 | - Which will run `./packages/create-guten-block/index.js` 20 | - And your new block plugin called `demo-block` gets added at the root of this project (which you should delete after testing). 21 | - Now go to `cd demo-block` 22 | - Run `npm start` or `yarn start` 23 | - This will compile your code in `dist` and you're good to go. 24 | - Run `yarn updated` to check which npm packages were updated 25 | - Finally publish with 'yarn publishNPM' since yarn has some issues with publishing with lerna not sure why. 26 | - Check caveats for publishing. 27 | 28 | ### 🤔 Caveats 29 | 30 | - Some issue with yarn not being able to publish via lerna 31 | - Use yarn with everything else but lerna 32 | - To publish always run via `npm` this command `npm run lerna` (Only for maintainers) 33 | 34 | 35 | ### 🐵 Other Stuff 36 | 37 | - Use `// @remove-file-on-eject` to do just that. 38 | - Use `// @remove-on-eject-begin` to do just that. 39 | - Use `// @remove-on-eject-end` to do just that. 40 | 41 | ### 🌟 Always use Emoji Log Messages 42 | 43 | What is that? I like emoji and I have invented a way to keep the git log clean and simple. Read this [Emoji-log](https://github.com/ahmadawais/Emoji-Log) to learn more. 44 | 45 | ### 🎯 New Workflow 46 | 47 | There's a new workflow for core developers of `create-guten-block`. 48 | 49 | - Git Clone `git clone https://github.com/ahmadawais/create-guten-block/` 50 | - You need to have both `yarn` and `npm` then run `yarn` in the root of `create-guten-block` folder 51 | - You also need publishing access to all the `npm` packages in CGB so ask for that from @AhmadAwais 52 | - Now create your branch `git checkout -b githubname/feaure` and commit all changes in it 53 | - Then publish all changes as `canary` changes which are not distrubted to production sites and are meant for testing while developing `npm` packages. 54 | - To publish canary package run `npm run releaseCanary` type `y` to confirm 55 | - Now you can test changes by using `-c` or `--canary` flag `npx create-guten-block blockName -c` 56 | - I recommend that you run the latest `create-guten-block` CLI if you changed anything there. You can do that by installing the latest `create-guten-block` that you published as canary e.g. `npx create-guten-block@1.12.0-alpha.148a0211 -c blockName` 57 | -------------------------------------------------------------------------------- /examples/01-single-block/.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs 2 | # editorconfig.org 3 | 4 | # WordPress Coding Standards 5 | # https://make.wordpress.org/core/handbook/coding-standards/ 6 | 7 | root = true 8 | 9 | [*] 10 | charset = utf-8 11 | end_of_line = lf 12 | insert_final_newline = true 13 | trim_trailing_whitespace = true 14 | indent_style = tab 15 | 16 | [*.yml] 17 | indent_style = space 18 | indent_size = 2 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | -------------------------------------------------------------------------------- /examples/01-single-block/.eslintignore: -------------------------------------------------------------------------------- 1 | **/*.min.js 2 | **/*.build.js 3 | **/node_modules/** 4 | **/vendor/** 5 | build 6 | coverage 7 | cypress 8 | node_modules 9 | vendor 10 | -------------------------------------------------------------------------------- /examples/01-single-block/.gitignore: -------------------------------------------------------------------------------- 1 | # Packages # 2 | ############ 3 | *.7z 4 | *.dmg 5 | *.gz 6 | *.bz2 7 | *.iso 8 | *.jar 9 | *.rar 10 | *.tar 11 | *.zip 12 | *.tgz 13 | *.map 14 | 15 | # Logs and databases # 16 | ###################### 17 | *.log 18 | *.sql 19 | 20 | # OS generated files # 21 | ###################### 22 | **.DS_Store* 23 | ehthumbs.db 24 | Icon? 25 | Thumbs.db 26 | ._* 27 | 28 | # Vim generated files # 29 | ###################### 30 | *.un~ 31 | 32 | # SASS # 33 | ########## 34 | **/.sass-cache 35 | **/.sass-cache/* 36 | **/.map 37 | 38 | # Composer # 39 | ########## 40 | vendors/composer/ 41 | !assets/js/vendor/ 42 | wpcs/ 43 | composer.lock 44 | 45 | # Bower # 46 | ########## 47 | assets/bower_components/* 48 | 49 | # Codekit # 50 | ########## 51 | /codekit-config.json 52 | *.codekit 53 | **.codekit-cache/* 54 | 55 | # NPM # 56 | ########## 57 | node_modules 58 | **/node_modules/** 59 | 60 | # Compiled Files and Build Dirs # 61 | ########## 62 | /README.html 63 | 64 | # PhpStrom Project Files # 65 | .idea/ 66 | library/vendors/composer 67 | assets/img/.DS_Store 68 | assets/sass/HTML 69 | assets/sass/Rails 70 | HTML 71 | Rails 72 | 73 | # CGB 74 | .idea/ 75 | .vscode/ 76 | node_modules/ 77 | .DS_Store 78 | *.tgz 79 | my-app* 80 | template/src/__tests__/__snapshots__/ 81 | lerna-debug.log 82 | npm-debug.log* 83 | yarn-debug.log* 84 | yarn-error.log* 85 | /.changelog -------------------------------------------------------------------------------- /examples/01-single-block/README.md: -------------------------------------------------------------------------------- 1 | # 🔰 EXAMPLE: Basic Single Block 2 | 3 | >This project was bootstrapped with [Create Guten Block](https://github.com/ahmadawais/create-guten-block). 4 | 5 |
6 | 7 | ![WHAT ICON](https://on.ahmda.ws/oy8W/c) 8 | 9 | ### What/How? 10 | 11 | This example includes a WordPress Gutenberg plugin called `single-block` which creates a Gutenberg block also called `single-block`. 12 | 13 | 👉 This example is created by running the following steps, that you can follow to build it on your own. 14 | 15 | - [Install `create-guten-block` →](https://github.com/ahmadawais/create-guten-block#getting-started) 16 | - Run `create-guten-block single-block` command. 17 | 18 | _That's about it._ 19 | 20 | >🌟 Star for updates [create-guten-block →](https://github.com/ahmadawais/create-guten-block) or to appreciate. 21 | 22 | 23 |
24 | 25 | ![ELSE ICON](https://on.ahmda.ws/oykk/c) 26 | 27 | ### Everything Else 28 | 29 | This project was bootstrapped with [Create Guten Block](https://github.com/ahmadawais/create-guten-block). 30 | 31 | Below you will find some information on how to run scripts. 32 | 33 | >You can find the most recent version of this guide [here](https://github.com/ahmadawais/create-guten-block). 34 | 35 | ## 👉 `npm start` 36 | - Use to compile and run the block in development mode. 37 | - Watches for any changes and reports back any errors in your code. 38 | 39 | ## 👉 `npm run build` 40 | - Use to build production code for your block inside `dist` folder. 41 | - Runs once and reports back the gzip file sizes of the produced code. 42 | 43 | ## 👉 `npm run eject` 44 | - Use to eject your plugin out of `create-guten-block`. 45 | - Provides all the configurations so you can customize the project as you want. 46 | - It's a one-way street, `eject` and you have to maintain everything yourself. 47 | - You don't normally have to `eject` a project because by ejecting you lose the connection with `create-guten-block` and from there onwards you have to update and maintain all the dependencies on your own. 48 | 49 | --- 50 | 51 | ###### — Feel free to tweet and say 👋 at me [@MrAhmadAwais](https://twitter.com/mrahmadawais/) 52 | 53 | [![npm](https://img.shields.io/npm/v/create-guten-block.svg?style=flat-square)](https://www.npmjs.com/package/create-guten-block) [![npm](https://img.shields.io/npm/dt/create-guten-block.svg?style=flat-square&label=downloads)](https://www.npmjs.com/package/create-guten-block) [![license](https://img.shields.io/github/license/mashape/apistatus.svg?style=flat-square)](https://github.com/ahmadawais/create-guten-block) [![Tweet for help](https://img.shields.io/twitter/follow/mrahmadawais.svg?style=social&label=Tweet%20@MrAhmadAwais)](https://twitter.com/mrahmadawais/) [![GitHub stars](https://img.shields.io/github/stars/ahmadawais/create-guten-block.svg?style=social&label=Stars)](https://github.com/ahmadawais/create-guten-block/stargazers) [![GitHub followers](https://img.shields.io/github/followers/ahmadawais.svg?style=social&label=Follow)](https://github.com/ahmadawais?tab=followers) 54 | -------------------------------------------------------------------------------- /examples/01-single-block/dist/blocks.editor.build.css: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Common SCSS 3 | * 4 | * Can include things like variables and mixins 5 | * that are used across the project. 6 | */ 7 | /** 8 | * #.# Editor Styles 9 | * 10 | * CSS for just Backend enqueued after style.scss 11 | * which makes it higher in priority. 12 | */ 13 | .wp-block-cgb-block-single-block { 14 | background: #bada55; 15 | border: 0.2rem solid #292929; 16 | color: #292929; 17 | margin: 0 auto; 18 | max-width: 740px; 19 | padding: 2rem; } 20 | -------------------------------------------------------------------------------- /examples/01-single-block/dist/blocks.style.build.css: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Common SCSS 3 | * 4 | * Can include things like variables and mixins 5 | * that are used across the project. 6 | */ 7 | /** 8 | * #.# Styles 9 | * 10 | * CSS for both Frontend+Backend. 11 | */ 12 | .wp-block-cgb-block-single-block { 13 | background: orangered; 14 | border: 0.2rem solid #292929; 15 | color: #292929; 16 | margin: 0 auto; 17 | max-width: 740px; 18 | padding: 2rem; } 19 | -------------------------------------------------------------------------------- /examples/01-single-block/plugin.php: -------------------------------------------------------------------------------- 1 |

. 41 | return ( 42 |
43 |

— Hello from the backend.

44 |

45 | CGB BLOCK: single-block is a new Gutenberg block 46 |

47 |

48 | It was created via{ ' ' } 49 | 50 | 51 | create-guten-block 52 | 53 | . 54 |

55 |
56 | ); 57 | }, 58 | 59 | // The "save" property must be specified and must be a valid function. 60 | save: function( props ) { 61 | return ( 62 |
63 |

— Hello from the frontend.

64 |

65 | CGB BLOCK: single-block is a new Gutenberg block. 66 |

67 |

68 | It was created via{ ' ' } 69 | 70 | 71 | create-guten-block 72 | 73 | . 74 |

75 |
76 | ); 77 | }, 78 | } ); 79 | -------------------------------------------------------------------------------- /examples/01-single-block/src/block/editor.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Editor Styles 3 | * 4 | * CSS for just Backend enqueued after style.scss 5 | * which makes it higher in priority. 6 | */ 7 | 8 | .wp-block-cgb-block-single-block { 9 | background: $green; 10 | border: 0.2rem solid $black; 11 | color: $black; 12 | margin: 0 auto; 13 | max-width: 740px; 14 | padding: 2rem; 15 | } 16 | -------------------------------------------------------------------------------- /examples/01-single-block/src/block/style.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Styles 3 | * 4 | * CSS for both Frontend+Backend. 5 | */ 6 | 7 | .wp-block-cgb-block-single-block { 8 | background: $red; 9 | border: 0.2rem solid $black; 10 | color: $black; 11 | margin: 0 auto; 12 | max-width: 740px; 13 | padding: 2rem; 14 | } 15 | -------------------------------------------------------------------------------- /examples/01-single-block/src/blocks.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Gutenberg Blocks 3 | * 4 | * All blocks related JavaScript. 5 | * You can create a new block folder in 6 | * this dir and include code for that block 7 | * here as well. 8 | * 9 | * All blocks should be included here since 10 | * this is the file that Webpack is compiling. 11 | */ 12 | 13 | import './block/block.js'; 14 | -------------------------------------------------------------------------------- /examples/01-single-block/src/common.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Common SCSS 3 | * 4 | * Can include things like variables and mixins 5 | * that are used across the project. 6 | */ 7 | 8 | // Colors. 9 | $black: rgb(41, 41, 41); 10 | $white: #f4f4f4; 11 | $gray: #dedede; 12 | $green: #bada55; 13 | $red: orangered; 14 | -------------------------------------------------------------------------------- /examples/01-single-block/src/init.php: -------------------------------------------------------------------------------- 1 | This project was bootstrapped with [Create Guten Block](https://github.com/ahmadawais/create-guten-block). 4 | 5 |
6 | 7 | ![WHAT ICON](https://on.ahmda.ws/oy8W/c) 8 | 9 | ### What/How? 10 | 11 | This example includes a WordPress Gutenberg plugin called `single-block` which creates a Gutenberg block also called `single-block`. 12 | 13 | 👉 This example is created by running the following steps, that you can follow to build it on your own. 14 | 15 | - [Install `create-guten-block` →](https://github.com/ahmadawais/create-guten-block#getting-started) 16 | - Run `create-guten-block single-block` command. 17 | - Finally, we ran `npm run eject` to eject the config in this plugin. 18 | 19 | _That's about it._ 20 | 21 | >🌟 Star for updates [create-guten-block →](https://github.com/ahmadawais/create-guten-block) or to appreciate. 22 | 23 | 24 |
25 | 26 | ![ELSE ICON](https://on.ahmda.ws/oykk/c) 27 | 28 | ### Everything Else 29 | 30 | This project was bootstrapped with [Create Guten Block](https://github.com/ahmadawais/create-guten-block). 31 | 32 | Below you will find some information on how to run scripts. 33 | 34 | >You can find the most recent version of this guide [here](https://github.com/ahmadawais/create-guten-block). 35 | 36 | ## 👉 `npm start` 37 | - Use to compile and run the block in development mode. 38 | - Watches for any changes and reports back any errors in your code. 39 | 40 | ## 👉 `npm run build` 41 | - Use to build production code for your block inside `dist` folder. 42 | - Runs once and reports back the gzip file sizes of the produced code. 43 | 44 | ## 👉 `npm run eject` 45 | - Use to eject your plugin out of `create-guten-block`. 46 | - Provides all the configurations so you can customize the project as you want. 47 | - It's a one-way street, `eject` and you have to maintain everything yourself. 48 | - You don't normally have to `eject` a project because by ejecting you lose the connection with `create-guten-block` and from there onwards you have to update and maintain all the dependencies on your own. 49 | 50 | --- 51 | 52 | ###### — Feel free to tweet and say 👋 at me [@MrAhmadAwais](https://twitter.com/mrahmadawais/) 53 | 54 | [![npm](https://img.shields.io/npm/v/create-guten-block.svg?style=flat-square)](https://www.npmjs.com/package/create-guten-block) [![npm](https://img.shields.io/npm/dt/create-guten-block.svg?style=flat-square&label=downloads)](https://www.npmjs.com/package/create-guten-block) [![license](https://img.shields.io/github/license/mashape/apistatus.svg?style=flat-square)](https://github.com/ahmadawais/create-guten-block) [![Tweet for help](https://img.shields.io/twitter/follow/mrahmadawais.svg?style=social&label=Tweet%20@MrAhmadAwais)](https://twitter.com/mrahmadawais/) [![GitHub stars](https://img.shields.io/github/stars/ahmadawais/create-guten-block.svg?style=social&label=Stars)](https://github.com/ahmadawais/create-guten-block/stargazers) [![GitHub followers](https://img.shields.io/github/followers/ahmadawais.svg?style=social&label=Follow)](https://github.com/ahmadawais?tab=followers) 55 | -------------------------------------------------------------------------------- /examples/02-single-block-ejected/config/paths.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Paths 3 | * 4 | * Project related paths. 5 | */ 6 | 7 | const path = require( 'path' ); 8 | const fs = require( 'fs' ); 9 | 10 | // Make sure any symlinks in the project folder are resolved: 11 | const pluginDir = fs.realpathSync( process.cwd() ); 12 | const resolveApp = relativePath => path.resolve( pluginDir, relativePath ); 13 | 14 | // Config after eject: we're in ./config/ 15 | module.exports = { 16 | dotenv: resolveApp( '.env' ), 17 | pluginBlocksJs: resolveApp( 'src/blocks.js' ), 18 | yarnLockFile: resolveApp( 'yarn.lock' ), 19 | pluginDist: resolveApp( '.' ), // We are in ./dist folder already so the path '.' resolves to ./dist/. 20 | }; 21 | -------------------------------------------------------------------------------- /examples/02-single-block-ejected/config/webpack.config.dev.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Webpack Configuration 3 | * 4 | * Working of a Webpack can be very simple or complex. This is an intenally simple 5 | * build configuration. 6 | * 7 | * Webpack basics — If you are new the Webpack here's all you need to know: 8 | * 1. Webpack is a module bundler. It bundles different JS modules together. 9 | * 2. It needs and entry point and an ouput to process file(s) and bundle them. 10 | * 3. By default it only understands common JavaScript but you can make it 11 | * understand other formats by way of adding a Webpack loader. 12 | * 4. In the file below you will find an entry point, an ouput, and a babel-loader 13 | * that tests all .js files excluding the ones in node_modules to process the 14 | * ESNext and make it compatible with older browsers i.e. it converts the 15 | * ESNext (new standards of JavaScript) into old JavaScript through a loader 16 | * by Babel. 17 | * 18 | * TODO: Instructions. 19 | * 20 | * @since 1.0.0 21 | */ 22 | 23 | const paths = require( './paths' ); 24 | const autoprefixer = require( 'autoprefixer' ); 25 | const ExtractTextPlugin = require( 'extract-text-webpack-plugin' ); 26 | 27 | // Extract style.css for both editor and frontend styles. 28 | const blocksCSSPlugin = new ExtractTextPlugin( { 29 | filename: './dist/blocks.style.build.css', 30 | } ); 31 | 32 | // Extract editor.css for editor styles. 33 | const editBlocksCSSPlugin = new ExtractTextPlugin( { 34 | filename: './dist/blocks.editor.build.css', 35 | } ); 36 | 37 | // Configuration for the ExtractTextPlugin — DRY rule. 38 | const extractConfig = { 39 | use: [ 40 | // "postcss" loader applies autoprefixer to our CSS. 41 | { loader: 'raw-loader' }, 42 | { 43 | loader: 'postcss-loader', 44 | options: { 45 | ident: 'postcss', 46 | plugins: [ 47 | autoprefixer( { 48 | browsers: [ 49 | '>1%', 50 | 'last 4 versions', 51 | 'Firefox ESR', 52 | 'not ie < 9', // React doesn't support IE8 anyway 53 | ], 54 | flexbox: 'no-2009', 55 | } ), 56 | ], 57 | }, 58 | }, 59 | // "sass" loader converts SCSS to CSS. 60 | { 61 | loader: 'sass-loader', 62 | options: { 63 | // Add common CSS file for variables and mixins. 64 | data: '@import "./src/common.scss";\n', 65 | outputStyle: 'nested', 66 | }, 67 | }, 68 | ], 69 | }; 70 | 71 | // Export configuration. 72 | module.exports = { 73 | entry: { 74 | './dist/blocks.build': paths.pluginBlocksJs, // 'name' : 'path/file.ext'. 75 | }, 76 | output: { 77 | // Add /* filename */ comments to generated require()s in the output. 78 | pathinfo: true, 79 | // The dist folder. 80 | path: paths.pluginDist, 81 | filename: '[name].js', // [name] = './dist/blocks.build' as defined above. 82 | }, 83 | // You may want 'eval' instead if you prefer to see the compiled output in DevTools. 84 | devtool: 'cheap-eval-source-map', 85 | module: { 86 | rules: [ 87 | { 88 | test: /\.(js|jsx|mjs)$/, 89 | exclude: /(node_modules|bower_components)/, 90 | use: { 91 | loader: 'babel-loader', 92 | options: { 93 | 94 | // This is a feature of `babel-loader` for webpack (not Babel itself). 95 | // It enables caching results in ./node_modules/.cache/babel-loader/ 96 | // directory for faster rebuilds. 97 | cacheDirectory: true, 98 | }, 99 | }, 100 | }, 101 | { 102 | test: /style\.s?css$/, 103 | exclude: /(node_modules|bower_components)/, 104 | use: blocksCSSPlugin.extract( extractConfig ), 105 | }, 106 | { 107 | test: /editor\.s?css$/, 108 | exclude: /(node_modules|bower_components)/, 109 | use: editBlocksCSSPlugin.extract( extractConfig ), 110 | }, 111 | ], 112 | }, 113 | // Add plugins. 114 | plugins: [ blocksCSSPlugin, editBlocksCSSPlugin ], 115 | stats: 'minimal', 116 | // stats: 'errors-only', 117 | }; 118 | -------------------------------------------------------------------------------- /examples/02-single-block-ejected/config/webpack.config.prod.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Webpack Configuration 3 | * 4 | * Working of a Webpack can be very simple or complex. This is an intenally simple 5 | * build configuration. 6 | * 7 | * Webpack basics — If you are new the Webpack here's all you need to know: 8 | * 1. Webpack is a module bundler. It bundles different JS modules together. 9 | * 2. It needs and entry point and an ouput to process file(s) and bundle them. 10 | * 3. By default it only understands common JavaScript but you can make it 11 | * understand other formats by way of adding a Webpack loader. 12 | * 4. In the file below you will find an entry point, an ouput, and a babel-loader 13 | * that tests all .js files excluding the ones in node_modules to process the 14 | * ESNext and make it compatible with older browsers i.e. it converts the 15 | * ESNext (new standards of JavaScript) into old JavaScript through a loader 16 | * by Babel. 17 | * 18 | * TODO: Instructions. 19 | * 20 | * @since 1.0.0 21 | */ 22 | 23 | const paths = require( './paths' ); 24 | const webpack = require( 'webpack' ); 25 | const autoprefixer = require( 'autoprefixer' ); 26 | const ExtractTextPlugin = require( 'extract-text-webpack-plugin' ); 27 | 28 | // Source maps are resource heavy and can cause out of memory issue for large source files. 29 | const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false'; 30 | 31 | // Extract style.css for both editor and frontend styles. 32 | const blocksCSSPlugin = new ExtractTextPlugin( { 33 | filename: './dist/blocks.style.build.css', 34 | } ); 35 | 36 | // Extract editor.css for editor styles. 37 | const editBlocksCSSPlugin = new ExtractTextPlugin( { 38 | filename: './dist/blocks.editor.build.css', 39 | } ); 40 | 41 | // Configuration for the ExtractTextPlugin — DRY rule. 42 | const extractConfig = { 43 | use: [ 44 | // "postcss" loader applies autoprefixer to our CSS. 45 | { loader: 'raw-loader' }, 46 | { 47 | loader: 'postcss-loader', 48 | options: { 49 | ident: 'postcss', 50 | plugins: [ 51 | autoprefixer( { 52 | browsers: [ 53 | '>1%', 54 | 'last 4 versions', 55 | 'Firefox ESR', 56 | 'not ie < 9', // React doesn't support IE8 anyway 57 | ], 58 | flexbox: 'no-2009', 59 | } ), 60 | ], 61 | }, 62 | }, 63 | // "sass" loader converts SCSS to CSS. 64 | { 65 | loader: 'sass-loader', 66 | options: { 67 | // Add common CSS file for variables and mixins. 68 | data: '@import "./src/common.scss";\n', 69 | outputStyle: 'compressed', 70 | }, 71 | }, 72 | ], 73 | }; 74 | 75 | // Export configuration. 76 | module.exports = { 77 | entry: { 78 | './dist/blocks.build': paths.pluginBlocksJs, // 'name' : 'path/file.ext'. 79 | }, 80 | output: { 81 | // Add /* filename */ comments to generated require()s in the output. 82 | pathinfo: true, 83 | // The dist folder. 84 | path: paths.pluginDist, 85 | filename: '[name].js', // [name] = './dist/blocks.build' as defined above. 86 | }, 87 | // You may want 'eval' instead if you prefer to see the compiled output in DevTools. 88 | devtool: 'cheap-eval-source-map', 89 | module: { 90 | rules: [ 91 | { 92 | test: /\.(js|jsx|mjs)$/, 93 | exclude: /(node_modules|bower_components)/, 94 | use: { 95 | loader: 'babel-loader', 96 | options: { 97 | 98 | // This is a feature of `babel-loader` for webpack (not Babel itself). 99 | // It enables caching results in ./node_modules/.cache/babel-loader/ 100 | // directory for faster rebuilds. 101 | cacheDirectory: true, 102 | }, 103 | }, 104 | }, 105 | { 106 | test: /style\.s?css$/, 107 | exclude: /(node_modules|bower_components)/, 108 | use: blocksCSSPlugin.extract( extractConfig ), 109 | }, 110 | { 111 | test: /editor\.s?css$/, 112 | exclude: /(node_modules|bower_components)/, 113 | use: editBlocksCSSPlugin.extract( extractConfig ), 114 | }, 115 | ], 116 | }, 117 | // Add plugins. 118 | plugins: [ 119 | blocksCSSPlugin, 120 | editBlocksCSSPlugin, 121 | // Minify the code. 122 | new webpack.optimize.UglifyJsPlugin( { 123 | compress: { 124 | warnings: false, 125 | // Disabled because of an issue with Uglify breaking seemingly valid code: 126 | // https://github.com/facebookincubator/create-react-app/issues/2376 127 | // Pending further investigation: 128 | // https://github.com/mishoo/UglifyJS2/issues/2011 129 | comparisons: false, 130 | }, 131 | mangle: { 132 | safari10: true, 133 | }, 134 | output: { 135 | comments: false, 136 | // Turned on because emoji and regex is not minified properly using default 137 | // https://github.com/facebookincubator/create-react-app/issues/2488 138 | ascii_only: true, 139 | }, 140 | sourceMap: shouldUseSourceMap, 141 | } ), 142 | ], 143 | stats: 'minimal', 144 | // stats: 'errors-only', 145 | }; 146 | -------------------------------------------------------------------------------- /examples/02-single-block-ejected/dist/blocks.editor.build.css: -------------------------------------------------------------------------------- 1 | .wp-block-cgb-block-single-block{background:#bada55;border:0.2rem solid #292929;color:#292929;margin:0 auto;max-width:740px;padding:2rem} 2 | -------------------------------------------------------------------------------- /examples/02-single-block-ejected/dist/blocks.style.build.css: -------------------------------------------------------------------------------- 1 | .wp-block-cgb-block-single-block{background:#ff4500;border:0.2rem solid #292929;color:#292929;margin:0 auto;max-width:740px;padding:2rem} 2 | -------------------------------------------------------------------------------- /examples/02-single-block-ejected/plugin.php: -------------------------------------------------------------------------------- 1 | { 20 | throw err; 21 | } ); 22 | 23 | // Modules. 24 | const fs = require( 'fs' ); 25 | const ora = require( 'ora' ); 26 | const path = require( 'path' ); 27 | const chalk = require( 'chalk' ); 28 | const webpack = require( 'webpack' ); 29 | const fileSize = require( 'filesize' ); 30 | const gzipSize = require( 'gzip-size' ); 31 | const resolvePkg = require( 'resolve-pkg' ); 32 | const config = require( '../config/webpack.config.prod' ); 33 | const cgbDevUtilsPath = resolvePkg( 'cgb-dev-utils', { cwd: __dirname } ); 34 | const clearConsole = require( cgbDevUtilsPath + '/clearConsole' ); 35 | const formatWebpackMessages = require( cgbDevUtilsPath + 36 | '/formatWebpackMessages' ); 37 | 38 | // Build file paths. 39 | const theCWD = process.cwd(); 40 | const fileBuildJS = path.resolve( theCWD, './dist/blocks.build.js' ); 41 | const fileEditorCSS = path.resolve( theCWD, './dist/blocks.editor.build.css' ); 42 | const fileStyleCSS = path.resolve( theCWD, './dist/blocks.style.build.css' ); 43 | 44 | /** 45 | * Get File Size 46 | * 47 | * Get filesizes of all the files. 48 | * 49 | * @param {string} filePath path. 50 | * @returns {string} then size result. 51 | */ 52 | const getFileSize = filePath => { 53 | return fileSize( gzipSize.sync( fs.readFileSync( filePath ) ) ); 54 | }; 55 | 56 | clearConsole(); 57 | 58 | // Init the spinner. 59 | const spinner = new ora( { text: '' } ); 60 | 61 | /** 62 | * Build function 63 | * 64 | * Create the production build and print the deployment instructions. 65 | * 66 | * @param {json} webpackConfig config 67 | */ 68 | async function build( webpackConfig ) { 69 | // Start the build. 70 | console.log( '\n' ); 71 | spinner.start( `${ chalk.dim( 'Building and compiling blocks...' ) }` ); 72 | 73 | // Compiler Instance. 74 | const compiler = await webpack( webpackConfig ); 75 | spinner.succeed(); 76 | 77 | // Run the compiler. 78 | compiler.run( ( err, stats ) => { 79 | if ( err ) { 80 | return console.log( err ); 81 | } 82 | 83 | // Get the messages formatted. 84 | const messages = formatWebpackMessages( stats.toJson( {}, true ) ); 85 | 86 | // If there are errors just show the errors. 87 | if ( messages.errors.length ) { 88 | // Only keep the first error. Others are often indicative 89 | // of the same problem, but confuse the reader with noise. 90 | if ( messages.errors.length > 1 ) { 91 | messages.errors.length = 1; 92 | } 93 | // Formatted errors. 94 | clearConsole(); 95 | console.log( '\n❌ ', chalk.black.bgRed( ' Failed to compile build. \n' ) ); 96 | const logErrors = console.log( '\n👉 ', messages.errors.join( '\n\n' ) ); 97 | return logErrors; 98 | } 99 | 100 | // CI. 101 | if ( 102 | process.env.CI && 103 | ( typeof process.env.CI !== 'string' || 104 | process.env.CI.toLowerCase() !== 'false' ) && 105 | messages.warnings.length 106 | ) { 107 | console.log( 108 | chalk.yellow( 109 | '\nTreating warnings as errors because process.env.CI = true.\n' + 110 | 'Most CI servers set it automatically.\n' 111 | ) 112 | ); 113 | return console.log( messages.warnings.join( '\n\n' ) ); 114 | } 115 | 116 | clearConsole(); 117 | console.log( '\n✅ ', chalk.black.bgGreen( ' Built successfully! \n' ) ); 118 | 119 | console.log( 120 | '\n\n', 121 | 'File sizes after gzip:', 122 | '\n\n', 123 | getFileSize( fileBuildJS ), 124 | `${ chalk.dim( '— ./dist/' ) }`, 125 | `${ chalk.green( 'blocks.build.js' ) }`, 126 | '\n', 127 | getFileSize( fileEditorCSS ), 128 | `${ chalk.dim( '— ./dist/' ) }`, 129 | `${ chalk.green( 'blocks.editor.build.css' ) }`, 130 | 131 | '\n', 132 | getFileSize( fileStyleCSS ), 133 | `${ chalk.dim( '— ./dist/' ) }`, 134 | `${ chalk.green( 'blocks.style.build.css' ) }`, 135 | 136 | '\n\n' 137 | ); 138 | 139 | return true; 140 | } ); 141 | } 142 | 143 | build( config ); 144 | -------------------------------------------------------------------------------- /examples/02-single-block-ejected/scripts/start.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Start 3 | * 4 | * The create-guten-block CLI starts here. 5 | * 6 | * TODO: 7 | * - checkRequiredFiles 8 | * - printBuildError 9 | */ 10 | 'use strict'; 11 | 12 | // Do this as the first thing so that any code reading it knows the right env. 13 | process.env.BABEL_ENV = 'development'; 14 | process.env.NODE_ENV = 'development'; 15 | 16 | // Makes the script crash on unhandled rejections instead of silently 17 | // ignoring them. In the future, promise rejections that are not handled will 18 | // terminate the Node.js process with a non-zero exit code. 19 | process.on( 'unhandledRejection', err => { 20 | throw err; 21 | } ); 22 | 23 | const ora = require( 'ora' ); 24 | const chalk = require( 'chalk' ); 25 | const webpack = require( 'webpack' ); 26 | const config = require( '../config/webpack.config.dev' ); 27 | const resolvePkg = require( 'resolve-pkg' ); 28 | const cgbDevUtilsPath = resolvePkg( 'cgb-dev-utils', { cwd: __dirname } ); 29 | const clearConsole = require( cgbDevUtilsPath + '/clearConsole' ); 30 | const formatWebpackMessages = require( cgbDevUtilsPath + 31 | '/formatWebpackMessages' ); 32 | 33 | // Don't run below node 8. 34 | const currentNodeVersion = process.versions.node; 35 | const semver = currentNodeVersion.split( '.' ); 36 | const major = semver[ 0 ]; 37 | 38 | // If below Node 8. 39 | if ( major < 8 ) { 40 | console.error( 41 | chalk.red( 42 | 'You are running Node ' + 43 | currentNodeVersion + 44 | '.\n' + 45 | 'Create Guten Block requires Node 8 or higher. \n' + 46 | 'Kindly, update your version of Node.' 47 | ) 48 | ); 49 | process.exit( 1 ); 50 | } 51 | 52 | clearConsole(); 53 | 54 | // Init the spinner. 55 | const spinner = new ora( { text: '' } ); 56 | 57 | // Create the production build and print the deployment instructions. 58 | async function build( webpackConfig ) { 59 | // Start the build. 60 | console.log( '\n' ); 61 | spinner.start( `${ chalk.dim( 'Building and compiling blocks...' ) }` ); 62 | 63 | // Compiler Instance. 64 | const compiler = await webpack( webpackConfig ); 65 | spinner.succeed(); 66 | 67 | // Run the compiler. 68 | compiler.watch( {}, ( err, stats ) => { 69 | if ( err ) { 70 | return console.log( err ); 71 | } 72 | 73 | // Get the messages formatted. 74 | const messages = formatWebpackMessages( stats.toJson( {}, true ) ); 75 | 76 | // If there are errors just show the errors. 77 | if ( messages.errors.length ) { 78 | // Only keep the first error. Others are often indicative 79 | // of the same problem, but confuse the reader with noise. 80 | if ( messages.errors.length > 1 ) { 81 | messages.errors.length = 1; 82 | } 83 | // Formatted errors. 84 | clearConsole(); 85 | console.log( '\n❌ ', chalk.black.bgRed( ' Failed to compile. \n' ) ); 86 | const logErrors = console.log( '\n👉 ', messages.errors.join( '\n\n' ) ); 87 | return logErrors; 88 | } 89 | 90 | // CI. 91 | if ( 92 | process.env.CI && 93 | ( typeof process.env.CI !== 'string' || 94 | process.env.CI.toLowerCase() !== 'false' ) && 95 | messages.warnings.length 96 | ) { 97 | console.log( 98 | chalk.yellow( 99 | '\nTreating warnings as errors because process.env.CI = true.\n' + 100 | 'Most CI servers set it automatically.\n' 101 | ) 102 | ); 103 | return console.log( messages.warnings.join( '\n\n' ) ); 104 | } 105 | 106 | clearConsole(); 107 | console.log( '\n✅ ', chalk.black.bgGreen( ' Compiled successfully! \n' ) ); 108 | console.log( 109 | chalk.dim( ' Watching for changes... (Press CTRL + C to stop). \n\n' ) 110 | ); 111 | return console.log( 112 | chalk.dim( ' Note that the development build is not optimized. \n' ), 113 | chalk.dim( 'To create a production build, use' ), 114 | chalk.green( 'npm' ), 115 | chalk.white( 'run build' ) 116 | ); 117 | } ); 118 | } 119 | 120 | build( config ); 121 | -------------------------------------------------------------------------------- /examples/02-single-block-ejected/src/block/block.js: -------------------------------------------------------------------------------- 1 | /** 2 | * BLOCK: single-block 3 | * 4 | * Registering a basic block with Gutenberg. 5 | * Simple block, renders and saves the same content without any interactivity. 6 | */ 7 | 8 | // Import CSS. 9 | import './style.scss'; 10 | import './editor.scss'; 11 | 12 | const { __ } = wp.i18n; // Import __() from wp.i18n 13 | const { registerBlockType } = wp.blocks; // Import registerBlockType() from wp.blocks 14 | 15 | /** 16 | * Register: aa Gutenberg Block. 17 | * 18 | * Registers a new block provided a unique name and an object defining its 19 | * behavior. Once registered, the block is made editor as an option to any 20 | * editor interface where blocks are implemented. 21 | * 22 | * @param {string} name Block name. 23 | * @param {Object} settings Block settings. 24 | * @return {?WPBlock} The block, if it has been successfully 25 | * registered; otherwise `undefined`. 26 | */ 27 | registerBlockType( 'cgb/block-single-block', { 28 | // Block name. Block names must be string that contains a namespace prefix. Example: my-plugin/my-custom-block. 29 | title: __( 'single-block - CGB Block', 'CGB' ), // Block title. 30 | icon: 'shield', // Block icon from Dashicons → https://developer.wordpress.org/resource/dashicons/. 31 | category: 'common', // Block category — Group blocks together based on common traits E.g. common, formatting, layout widgets, embed. 32 | keywords: [ 33 | __( 'single-block — CGB Block' ), 34 | __( 'CGB Example' ), 35 | __( 'create-guten-block' ), 36 | ], 37 | 38 | // The "edit" property must be a valid function. 39 | edit: function( props ) { 40 | // Creates a

. 41 | return ( 42 |
43 |

— Hello from the backend.

44 |

45 | CGB BLOCK: single-block is a new Gutenberg block 46 |

47 |

48 | It was created via{ ' ' } 49 | 50 | 51 | create-guten-block 52 | 53 | . 54 |

55 |
56 | ); 57 | }, 58 | 59 | // The "save" property must be specified and must be a valid function. 60 | save: function( props ) { 61 | return ( 62 |
63 |

— Hello from the frontend.

64 |

65 | CGB BLOCK: single-block is a new Gutenberg block. 66 |

67 |

68 | It was created via{ ' ' } 69 | 70 | 71 | create-guten-block 72 | 73 | . 74 |

75 |
76 | ); 77 | }, 78 | } ); 79 | -------------------------------------------------------------------------------- /examples/02-single-block-ejected/src/block/editor.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Editor Styles 3 | * 4 | * CSS for just Backend enqueued after style.scss 5 | * which makes it higher in priority. 6 | */ 7 | 8 | .wp-block-cgb-block-single-block { 9 | background: $green; 10 | border: 0.2rem solid $black; 11 | color: $black; 12 | margin: 0 auto; 13 | max-width: 740px; 14 | padding: 2rem; 15 | } 16 | -------------------------------------------------------------------------------- /examples/02-single-block-ejected/src/block/style.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Styles 3 | * 4 | * CSS for both Frontend+Backend. 5 | */ 6 | 7 | .wp-block-cgb-block-single-block { 8 | background: $red; 9 | border: 0.2rem solid $black; 10 | color: $black; 11 | margin: 0 auto; 12 | max-width: 740px; 13 | padding: 2rem; 14 | } 15 | -------------------------------------------------------------------------------- /examples/02-single-block-ejected/src/blocks.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Gutenberg Blocks 3 | * 4 | * All blocks related JavaScript. 5 | * You can create a new block folder in 6 | * this dir and include code for that block 7 | * here as well. 8 | * 9 | * All blocks should be included here since 10 | * this is the file that Webpack is compiling. 11 | */ 12 | 13 | import './block/block.js'; 14 | -------------------------------------------------------------------------------- /examples/02-single-block-ejected/src/common.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Common SCSS 3 | * 4 | * Can include things like variables and mixins 5 | * that are used across the project. 6 | */ 7 | 8 | // Colors. 9 | $black: rgb(41, 41, 41); 10 | $white: #f4f4f4; 11 | $gray: #dedede; 12 | $green: #bada55; 13 | $red: orangered; 14 | -------------------------------------------------------------------------------- /examples/02-single-block-ejected/src/init.php: -------------------------------------------------------------------------------- 1 | This project was bootstrapped with [Create Guten Block](https://github.com/ahmadawais/create-guten-block). 4 | 5 |
6 | 7 | ![WHAT ICON](https://on.ahmda.ws/oy8W/c) 8 | 9 | ### What/How? 10 | 11 | This example includes a WordPress Gutenberg plugin called `multi-block` which creates a Gutenberg block also called `multi-block`. 12 | 13 | 👉 This example is created by running the following steps, that you can follow to build it on your own. 14 | 15 | - [Install `create-guten-block` →](https://github.com/ahmadawais/create-guten-block#getting-started) 16 | - Run `create-guten-block multi-block` command. 17 | - Go to `./src/` and copy paste the `./src/block` directory as `./src/block2/` where our second block's code will live. 18 | - Open `./src/blocks.js` and import our new block from `./src/block2/block.js` file. 19 | - Go to `./block2/` directory and rename our block from `multi-block` to `multi-block-2` in both `.js` and `.scss` files. 20 | - Now you have two blocks run by a single plugin. 21 | - As you might have noticed all blocks should be imported in the `./src/blocks.js` files as that's the file which gets imported into our webpack config. 22 | 23 | _That's about it._ 24 | 25 | >🌟 Star for updates [create-guten-block →](https://github.com/ahmadawais/create-guten-block) or to appreciate. 26 | 27 | 28 |
29 | 30 | ![ELSE ICON](https://on.ahmda.ws/oykk/c) 31 | 32 | ### Everything Else 33 | 34 | This project was bootstrapped with [Create Guten Block](https://github.com/ahmadawais/create-guten-block). 35 | 36 | Below you will find some information on how to run scripts. 37 | 38 | >You can find the most recent version of this guide [here](https://github.com/ahmadawais/create-guten-block). 39 | 40 | ## 👉 `npm start` 41 | - Use to compile and run the block in development mode. 42 | - Watches for any changes and reports back any errors in your code. 43 | 44 | ## 👉 `npm run build` 45 | - Use to build production code for your block inside `dist` folder. 46 | - Runs once and reports back the gzip file sizes of the produced code. 47 | 48 | ## 👉 `npm run eject` 49 | - Use to eject your plugin out of `create-guten-block`. 50 | - Provides all the configurations so you can customize the project as you want. 51 | - It's a one-way street, `eject` and you have to maintain everything yourself. 52 | - You don't normally have to `eject` a project because by ejecting you lose the connection with `create-guten-block` and from there onwards you have to update and maintain all the dependencies on your own. 53 | 54 | --- 55 | 56 | ###### — Feel free to tweet and say 👋 at me [@MrAhmadAwais](https://twitter.com/mrahmadawais/) 57 | 58 | [![npm](https://img.shields.io/npm/v/create-guten-block.svg?style=flat-square)](https://www.npmjs.com/package/create-guten-block) [![npm](https://img.shields.io/npm/dt/create-guten-block.svg?style=flat-square&label=downloads)](https://www.npmjs.com/package/create-guten-block) [![license](https://img.shields.io/github/license/mashape/apistatus.svg?style=flat-square)](https://github.com/ahmadawais/create-guten-block) [![Tweet for help](https://img.shields.io/twitter/follow/mrahmadawais.svg?style=social&label=Tweet%20@MrAhmadAwais)](https://twitter.com/mrahmadawais/) [![GitHub stars](https://img.shields.io/github/stars/ahmadawais/create-guten-block.svg?style=social&label=Stars)](https://github.com/ahmadawais/create-guten-block/stargazers) [![GitHub followers](https://img.shields.io/github/followers/ahmadawais.svg?style=social&label=Follow)](https://github.com/ahmadawais?tab=followers) 59 | -------------------------------------------------------------------------------- /examples/03-multi-block/dist/blocks.editor.build.css: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Common SCSS 3 | * 4 | * Can include things like variables and mixins 5 | * that are used across the project. 6 | */ 7 | /** 8 | * #.# Editor Styles 9 | * 10 | * CSS for just Backend enqueued after style.scss 11 | * which makes it higher in priority. 12 | */ 13 | .wp-block-cgb-block-multi-block { 14 | background: #bada55; 15 | border: 0.2rem solid #292929; 16 | color: #292929; 17 | margin: 0 auto; 18 | max-width: 740px; 19 | padding: 2rem; } 20 | /** 21 | * #.# Common SCSS 22 | * 23 | * Can include things like variables and mixins 24 | * that are used across the project. 25 | */ 26 | /** 27 | * #.# Editor Styles 28 | * 29 | * CSS for just Backend enqueued after style.scss 30 | * which makes it higher in priority. 31 | */ 32 | .wp-block-cgb-block-multi-block-2 { 33 | background: #bada55; 34 | border: 0.2rem solid #292929; 35 | color: #292929; 36 | margin: 0 auto; 37 | max-width: 740px; 38 | padding: 2rem; } 39 | -------------------------------------------------------------------------------- /examples/03-multi-block/dist/blocks.style.build.css: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Common SCSS 3 | * 4 | * Can include things like variables and mixins 5 | * that are used across the project. 6 | */ 7 | /** 8 | * #.# Styles 9 | * 10 | * CSS for both Frontend+Backend. 11 | */ 12 | .wp-block-cgb-block-multi-block { 13 | background: orangered; 14 | border: 0.2rem solid #292929; 15 | color: #292929; 16 | margin: 0 auto; 17 | max-width: 740px; 18 | padding: 2rem; } 19 | /** 20 | * #.# Common SCSS 21 | * 22 | * Can include things like variables and mixins 23 | * that are used across the project. 24 | */ 25 | /** 26 | * #.# Styles 27 | * 28 | * CSS for both Frontend+Backend. 29 | */ 30 | .wp-block-cgb-block-multi-block-2 { 31 | background: orangered; 32 | border: 0.2rem solid #292929; 33 | color: #292929; 34 | margin: 0 auto; 35 | max-width: 740px; 36 | padding: 2rem; } 37 | -------------------------------------------------------------------------------- /examples/03-multi-block/plugin.php: -------------------------------------------------------------------------------- 1 |

. 41 | return ( 42 |
43 |

— Hello from the backend.

44 |

45 | CGB BLOCK: multi-block is a new Gutenberg block 46 |

47 |

48 | It was created via{ ' ' } 49 | 50 | 51 | create-guten-block 52 | 53 | . 54 |

55 |
56 | ); 57 | }, 58 | 59 | // The "save" property must be specified and must be a valid function. 60 | save: function( props ) { 61 | return ( 62 |
63 |

— Hello from the frontend.

64 |

65 | CGB BLOCK: multi-block is a new Gutenberg block. 66 |

67 |

68 | It was created via{ ' ' } 69 | 70 | 71 | create-guten-block 72 | 73 | . 74 |

75 |
76 | ); 77 | }, 78 | } ); 79 | -------------------------------------------------------------------------------- /examples/03-multi-block/src/block/editor.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Editor Styles 3 | * 4 | * CSS for just Backend enqueued after style.scss 5 | * which makes it higher in priority. 6 | */ 7 | 8 | .wp-block-cgb-block-multi-block { 9 | background: $green; 10 | border: 0.2rem solid $black; 11 | color: $black; 12 | margin: 0 auto; 13 | max-width: 740px; 14 | padding: 2rem; 15 | } 16 | -------------------------------------------------------------------------------- /examples/03-multi-block/src/block/style.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Styles 3 | * 4 | * CSS for both Frontend+Backend. 5 | */ 6 | 7 | .wp-block-cgb-block-multi-block { 8 | background: $red; 9 | border: 0.2rem solid $black; 10 | color: $black; 11 | margin: 0 auto; 12 | max-width: 740px; 13 | padding: 2rem; 14 | } 15 | -------------------------------------------------------------------------------- /examples/03-multi-block/src/block2/block.js: -------------------------------------------------------------------------------- 1 | /** 2 | * BLOCK: multi-block-2 3 | * 4 | * Registering a basic block with Gutenberg. 5 | * Simple block, renders and saves the same content without any interactivity. 6 | */ 7 | 8 | // Import CSS. 9 | import './style.scss'; 10 | import './editor.scss'; 11 | 12 | const { __ } = wp.i18n; // Import __() from wp.i18n 13 | const { registerBlockType } = wp.blocks; // Import registerBlockType() from wp.blocks 14 | 15 | /** 16 | * Register: aa Gutenberg Block. 17 | * 18 | * Registers a new block provided a unique name and an object defining its 19 | * behavior. Once registered, the block is made editor as an option to any 20 | * editor interface where blocks are implemented. 21 | * 22 | * @param {string} name Block name. 23 | * @param {Object} settings Block settings. 24 | * @return {?WPBlock} The block, if it has been successfully 25 | * registered; otherwise `undefined`. 26 | */ 27 | registerBlockType( 'cgb/block-multi-block-2', { 28 | // Block name. Block names must be string that contains a namespace prefix. Example: my-plugin/my-custom-block. 29 | title: __( 'multi-block-2 - CGB Block', 'CGB' ), // Block title. 30 | icon: 'shield', // Block icon from Dashicons → https://developer.wordpress.org/resource/dashicons/. 31 | category: 'common', // Block category — Group blocks together based on common traits E.g. common, formatting, layout widgets, embed. 32 | keywords: [ 33 | __( 'multi-block-2 — CGB Block' ), 34 | __( 'CGB Example' ), 35 | __( 'create-guten-block' ), 36 | ], 37 | 38 | // The "edit" property must be a valid function. 39 | edit: function( props ) { 40 | // Creates a

. 41 | return ( 42 |
43 |

— Hello from the backend.

44 |

45 | CGB BLOCK: multi-block-2 is a new Gutenberg block 46 |

47 |

48 | It was created via{ ' ' } 49 | 50 | 51 | create-guten-block 52 | 53 | . 54 |

55 |
56 | ); 57 | }, 58 | 59 | // The "save" property must be specified and must be a valid function. 60 | save: function( props ) { 61 | return ( 62 |
63 |

— Hello from the frontend.

64 |

65 | CGB BLOCK: multi-block-2 is a new Gutenberg block. 66 |

67 |

68 | It was created via{ ' ' } 69 | 70 | 71 | create-guten-block 72 | 73 | . 74 |

75 |
76 | ); 77 | }, 78 | } ); 79 | -------------------------------------------------------------------------------- /examples/03-multi-block/src/block2/editor.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Editor Styles 3 | * 4 | * CSS for just Backend enqueued after style.scss 5 | * which makes it higher in priority. 6 | */ 7 | 8 | .wp-block-cgb-block-multi-block-2 { 9 | background: $green; 10 | border: 0.2rem solid $black; 11 | color: $black; 12 | margin: 0 auto; 13 | max-width: 740px; 14 | padding: 2rem; 15 | } 16 | -------------------------------------------------------------------------------- /examples/03-multi-block/src/block2/style.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Styles 3 | * 4 | * CSS for both Frontend+Backend. 5 | */ 6 | 7 | .wp-block-cgb-block-multi-block-2 { 8 | background: $red; 9 | border: 0.2rem solid $black; 10 | color: $black; 11 | margin: 0 auto; 12 | max-width: 740px; 13 | padding: 2rem; 14 | } 15 | -------------------------------------------------------------------------------- /examples/03-multi-block/src/blocks.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Gutenberg Blocks 3 | * 4 | * All blocks related JavaScript. 5 | * You can create a new block folder in 6 | * this dir and include code for that block 7 | * here as well. 8 | * 9 | * All blocks should be included here since 10 | * this is the file that Webpack is compiling. 11 | */ 12 | 13 | import './block/block.js'; 14 | import './block2/block.js'; 15 | -------------------------------------------------------------------------------- /examples/03-multi-block/src/common.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Common SCSS 3 | * 4 | * Can include things like variables and mixins 5 | * that are used across the project. 6 | */ 7 | 8 | // Colors. 9 | $black: rgb(41, 41, 41); 10 | $white: #f4f4f4; 11 | $gray: #dedede; 12 | $green: #bada55; 13 | $red: orangered; 14 | -------------------------------------------------------------------------------- /examples/03-multi-block/src/init.php: -------------------------------------------------------------------------------- 1 | This project was bootstrapped with [Create Guten Block](https://github.com/ahmadawais/create-guten-block). 4 | 5 |
6 | 7 | ![WHAT ICON](https://on.ahmda.ws/oy8W/c) 8 | 9 | ### What/How? 10 | 11 | This example includes a WordPress Gutenberg plugin called `multi-block` which creates a Gutenberg block also called `multi-block`. 12 | 13 | 👉 This example is created by running the following steps, that you can follow to build it on your own. 14 | 15 | - [Install `create-guten-block` →](https://github.com/ahmadawais/create-guten-block#getting-started) 16 | - Run `create-guten-block multi-block` command. 17 | - Go to `./src/` and copy paste the `./src/block` directory as `./src/block2/` where our second block's code will live. 18 | - Open `./src/blocks.js` and import our new block from `./src/block2/block.js` file. 19 | - Go to `./block2/` directory and rename our block from `multi-block` to `multi-block-2` in both `.js` and `.scss` files. 20 | - Now you have two blocks run by a single plugin. 21 | - As you might have noticed all blocks should be imported in the `./src/blocks.js` files as that's the file which gets imported into our webpack config. 22 | - Finally, we ran `npm run eject` to eject the config in this plugin. 23 | 24 | _That's about it._ 25 | 26 | >🌟 Star for updates [create-guten-block →](https://github.com/ahmadawais/create-guten-block) or to appreciate. 27 | 28 | 29 |
30 | 31 | ![ELSE ICON](https://on.ahmda.ws/oykk/c) 32 | 33 | ### Everything Else 34 | 35 | This project was bootstrapped with [Create Guten Block](https://github.com/ahmadawais/create-guten-block). 36 | 37 | Below you will find some information on how to run scripts. 38 | 39 | >You can find the most recent version of this guide [here](https://github.com/ahmadawais/create-guten-block). 40 | 41 | ## 👉 `npm start` 42 | - Use to compile and run the block in development mode. 43 | - Watches for any changes and reports back any errors in your code. 44 | 45 | ## 👉 `npm run build` 46 | - Use to build production code for your block inside `dist` folder. 47 | - Runs once and reports back the gzip file sizes of the produced code. 48 | 49 | ## 👉 `npm run eject` 50 | - Use to eject your plugin out of `create-guten-block`. 51 | - Provides all the configurations so you can customize the project as you want. 52 | - It's a one-way street, `eject` and you have to maintain everything yourself. 53 | - You don't normally have to `eject` a project because by ejecting you lose the connection with `create-guten-block` and from there onwards you have to update and maintain all the dependencies on your own. 54 | 55 | --- 56 | 57 | ###### — Feel free to tweet and say 👋 at me [@MrAhmadAwais](https://twitter.com/mrahmadawais/) 58 | 59 | [![npm](https://img.shields.io/npm/v/create-guten-block.svg?style=flat-square)](https://www.npmjs.com/package/create-guten-block) [![npm](https://img.shields.io/npm/dt/create-guten-block.svg?style=flat-square&label=downloads)](https://www.npmjs.com/package/create-guten-block) [![license](https://img.shields.io/github/license/mashape/apistatus.svg?style=flat-square)](https://github.com/ahmadawais/create-guten-block) [![Tweet for help](https://img.shields.io/twitter/follow/mrahmadawais.svg?style=social&label=Tweet%20@MrAhmadAwais)](https://twitter.com/mrahmadawais/) [![GitHub stars](https://img.shields.io/github/stars/ahmadawais/create-guten-block.svg?style=social&label=Stars)](https://github.com/ahmadawais/create-guten-block/stargazers) [![GitHub followers](https://img.shields.io/github/followers/ahmadawais.svg?style=social&label=Follow)](https://github.com/ahmadawais?tab=followers) 60 | -------------------------------------------------------------------------------- /examples/04-multi-block-ejected/config/paths.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Paths 3 | * 4 | * Project related paths. 5 | */ 6 | 7 | const path = require( 'path' ); 8 | const fs = require( 'fs' ); 9 | 10 | // Make sure any symlinks in the project folder are resolved: 11 | const pluginDir = fs.realpathSync( process.cwd() ); 12 | const resolveApp = relativePath => path.resolve( pluginDir, relativePath ); 13 | 14 | // Config after eject: we're in ./config/ 15 | module.exports = { 16 | dotenv: resolveApp( '.env' ), 17 | pluginBlocksJs: resolveApp( 'src/blocks.js' ), 18 | yarnLockFile: resolveApp( 'yarn.lock' ), 19 | pluginDist: resolveApp( '.' ), // We are in ./dist folder already so the path '.' resolves to ./dist/. 20 | }; 21 | -------------------------------------------------------------------------------- /examples/04-multi-block-ejected/config/webpack.config.dev.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Webpack Configuration 3 | * 4 | * Working of a Webpack can be very simple or complex. This is an intenally simple 5 | * build configuration. 6 | * 7 | * Webpack basics — If you are new the Webpack here's all you need to know: 8 | * 1. Webpack is a module bundler. It bundles different JS modules together. 9 | * 2. It needs and entry point and an ouput to process file(s) and bundle them. 10 | * 3. By default it only understands common JavaScript but you can make it 11 | * understand other formats by way of adding a Webpack loader. 12 | * 4. In the file below you will find an entry point, an ouput, and a babel-loader 13 | * that tests all .js files excluding the ones in node_modules to process the 14 | * ESNext and make it compatible with older browsers i.e. it converts the 15 | * ESNext (new standards of JavaScript) into old JavaScript through a loader 16 | * by Babel. 17 | * 18 | * TODO: Instructions. 19 | * 20 | * @since 1.0.0 21 | */ 22 | 23 | const paths = require( './paths' ); 24 | const autoprefixer = require( 'autoprefixer' ); 25 | const ExtractTextPlugin = require( 'extract-text-webpack-plugin' ); 26 | 27 | // Extract style.css for both editor and frontend styles. 28 | const blocksCSSPlugin = new ExtractTextPlugin( { 29 | filename: './dist/blocks.style.build.css', 30 | } ); 31 | 32 | // Extract editor.css for editor styles. 33 | const editBlocksCSSPlugin = new ExtractTextPlugin( { 34 | filename: './dist/blocks.editor.build.css', 35 | } ); 36 | 37 | // Configuration for the ExtractTextPlugin — DRY rule. 38 | const extractConfig = { 39 | use: [ 40 | // "postcss" loader applies autoprefixer to our CSS. 41 | { loader: 'raw-loader' }, 42 | { 43 | loader: 'postcss-loader', 44 | options: { 45 | ident: 'postcss', 46 | plugins: [ 47 | autoprefixer( { 48 | browsers: [ 49 | '>1%', 50 | 'last 4 versions', 51 | 'Firefox ESR', 52 | 'not ie < 9', // React doesn't support IE8 anyway 53 | ], 54 | flexbox: 'no-2009', 55 | } ), 56 | ], 57 | }, 58 | }, 59 | // "sass" loader converts SCSS to CSS. 60 | { 61 | loader: 'sass-loader', 62 | options: { 63 | // Add common CSS file for variables and mixins. 64 | data: '@import "./src/common.scss";\n', 65 | outputStyle: 'nested', 66 | }, 67 | }, 68 | ], 69 | }; 70 | 71 | // Export configuration. 72 | module.exports = { 73 | entry: { 74 | './dist/blocks.build': paths.pluginBlocksJs, // 'name' : 'path/file.ext'. 75 | }, 76 | output: { 77 | // Add /* filename */ comments to generated require()s in the output. 78 | pathinfo: true, 79 | // The dist folder. 80 | path: paths.pluginDist, 81 | filename: '[name].js', // [name] = './dist/blocks.build' as defined above. 82 | }, 83 | // You may want 'eval' instead if you prefer to see the compiled output in DevTools. 84 | devtool: 'cheap-eval-source-map', 85 | module: { 86 | rules: [ 87 | { 88 | test: /\.(js|jsx|mjs)$/, 89 | exclude: /(node_modules|bower_components)/, 90 | use: { 91 | loader: 'babel-loader', 92 | options: { 93 | 94 | // This is a feature of `babel-loader` for webpack (not Babel itself). 95 | // It enables caching results in ./node_modules/.cache/babel-loader/ 96 | // directory for faster rebuilds. 97 | cacheDirectory: true, 98 | }, 99 | }, 100 | }, 101 | { 102 | test: /style\.s?css$/, 103 | exclude: /(node_modules|bower_components)/, 104 | use: blocksCSSPlugin.extract( extractConfig ), 105 | }, 106 | { 107 | test: /editor\.s?css$/, 108 | exclude: /(node_modules|bower_components)/, 109 | use: editBlocksCSSPlugin.extract( extractConfig ), 110 | }, 111 | ], 112 | }, 113 | // Add plugins. 114 | plugins: [ blocksCSSPlugin, editBlocksCSSPlugin ], 115 | stats: 'minimal', 116 | // stats: 'errors-only', 117 | }; 118 | -------------------------------------------------------------------------------- /examples/04-multi-block-ejected/config/webpack.config.prod.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Webpack Configuration 3 | * 4 | * Working of a Webpack can be very simple or complex. This is an intenally simple 5 | * build configuration. 6 | * 7 | * Webpack basics — If you are new the Webpack here's all you need to know: 8 | * 1. Webpack is a module bundler. It bundles different JS modules together. 9 | * 2. It needs and entry point and an ouput to process file(s) and bundle them. 10 | * 3. By default it only understands common JavaScript but you can make it 11 | * understand other formats by way of adding a Webpack loader. 12 | * 4. In the file below you will find an entry point, an ouput, and a babel-loader 13 | * that tests all .js files excluding the ones in node_modules to process the 14 | * ESNext and make it compatible with older browsers i.e. it converts the 15 | * ESNext (new standards of JavaScript) into old JavaScript through a loader 16 | * by Babel. 17 | * 18 | * TODO: Instructions. 19 | * 20 | * @since 1.0.0 21 | */ 22 | 23 | const paths = require( './paths' ); 24 | const webpack = require( 'webpack' ); 25 | const autoprefixer = require( 'autoprefixer' ); 26 | const ExtractTextPlugin = require( 'extract-text-webpack-plugin' ); 27 | 28 | // Source maps are resource heavy and can cause out of memory issue for large source files. 29 | const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false'; 30 | 31 | // Extract style.css for both editor and frontend styles. 32 | const blocksCSSPlugin = new ExtractTextPlugin( { 33 | filename: './dist/blocks.style.build.css', 34 | } ); 35 | 36 | // Extract editor.css for editor styles. 37 | const editBlocksCSSPlugin = new ExtractTextPlugin( { 38 | filename: './dist/blocks.editor.build.css', 39 | } ); 40 | 41 | // Configuration for the ExtractTextPlugin — DRY rule. 42 | const extractConfig = { 43 | use: [ 44 | // "postcss" loader applies autoprefixer to our CSS. 45 | { loader: 'raw-loader' }, 46 | { 47 | loader: 'postcss-loader', 48 | options: { 49 | ident: 'postcss', 50 | plugins: [ 51 | autoprefixer( { 52 | browsers: [ 53 | '>1%', 54 | 'last 4 versions', 55 | 'Firefox ESR', 56 | 'not ie < 9', // React doesn't support IE8 anyway 57 | ], 58 | flexbox: 'no-2009', 59 | } ), 60 | ], 61 | }, 62 | }, 63 | // "sass" loader converts SCSS to CSS. 64 | { 65 | loader: 'sass-loader', 66 | options: { 67 | // Add common CSS file for variables and mixins. 68 | data: '@import "./src/common.scss";\n', 69 | outputStyle: 'compressed', 70 | }, 71 | }, 72 | ], 73 | }; 74 | 75 | // Export configuration. 76 | module.exports = { 77 | entry: { 78 | './dist/blocks.build': paths.pluginBlocksJs, // 'name' : 'path/file.ext'. 79 | }, 80 | output: { 81 | // Add /* filename */ comments to generated require()s in the output. 82 | pathinfo: true, 83 | // The dist folder. 84 | path: paths.pluginDist, 85 | filename: '[name].js', // [name] = './dist/blocks.build' as defined above. 86 | }, 87 | // You may want 'eval' instead if you prefer to see the compiled output in DevTools. 88 | devtool: 'cheap-eval-source-map', 89 | module: { 90 | rules: [ 91 | { 92 | test: /\.(js|jsx|mjs)$/, 93 | exclude: /(node_modules|bower_components)/, 94 | use: { 95 | loader: 'babel-loader', 96 | options: { 97 | 98 | // This is a feature of `babel-loader` for webpack (not Babel itself). 99 | // It enables caching results in ./node_modules/.cache/babel-loader/ 100 | // directory for faster rebuilds. 101 | cacheDirectory: true, 102 | }, 103 | }, 104 | }, 105 | { 106 | test: /style\.s?css$/, 107 | exclude: /(node_modules|bower_components)/, 108 | use: blocksCSSPlugin.extract( extractConfig ), 109 | }, 110 | { 111 | test: /editor\.s?css$/, 112 | exclude: /(node_modules|bower_components)/, 113 | use: editBlocksCSSPlugin.extract( extractConfig ), 114 | }, 115 | ], 116 | }, 117 | // Add plugins. 118 | plugins: [ 119 | blocksCSSPlugin, 120 | editBlocksCSSPlugin, 121 | // Minify the code. 122 | new webpack.optimize.UglifyJsPlugin( { 123 | compress: { 124 | warnings: false, 125 | // Disabled because of an issue with Uglify breaking seemingly valid code: 126 | // https://github.com/facebookincubator/create-react-app/issues/2376 127 | // Pending further investigation: 128 | // https://github.com/mishoo/UglifyJS2/issues/2011 129 | comparisons: false, 130 | }, 131 | mangle: { 132 | safari10: true, 133 | }, 134 | output: { 135 | comments: false, 136 | // Turned on because emoji and regex is not minified properly using default 137 | // https://github.com/facebookincubator/create-react-app/issues/2488 138 | ascii_only: true, 139 | }, 140 | sourceMap: shouldUseSourceMap, 141 | } ), 142 | ], 143 | stats: 'minimal', 144 | // stats: 'errors-only', 145 | }; 146 | -------------------------------------------------------------------------------- /examples/04-multi-block-ejected/dist/blocks.editor.build.css: -------------------------------------------------------------------------------- 1 | .wp-block-cgb-block-multi-block{background:#bada55;border:0.2rem solid #292929;color:#292929;margin:0 auto;max-width:740px;padding:2rem} 2 | .wp-block-cgb-block-multi-block-2{background:#bada55;border:0.2rem solid #292929;color:#292929;margin:0 auto;max-width:740px;padding:2rem} 3 | -------------------------------------------------------------------------------- /examples/04-multi-block-ejected/dist/blocks.style.build.css: -------------------------------------------------------------------------------- 1 | .wp-block-cgb-block-multi-block{background:#ff4500;border:0.2rem solid #292929;color:#292929;margin:0 auto;max-width:740px;padding:2rem} 2 | .wp-block-cgb-block-multi-block-2{background:#ff4500;border:0.2rem solid #292929;color:#292929;margin:0 auto;max-width:740px;padding:2rem} 3 | -------------------------------------------------------------------------------- /examples/04-multi-block-ejected/plugin.php: -------------------------------------------------------------------------------- 1 | { 20 | throw err; 21 | } ); 22 | 23 | // Modules. 24 | const fs = require( 'fs' ); 25 | const ora = require( 'ora' ); 26 | const path = require( 'path' ); 27 | const chalk = require( 'chalk' ); 28 | const webpack = require( 'webpack' ); 29 | const fileSize = require( 'filesize' ); 30 | const gzipSize = require( 'gzip-size' ); 31 | const resolvePkg = require( 'resolve-pkg' ); 32 | const config = require( '../config/webpack.config.prod' ); 33 | const cgbDevUtilsPath = resolvePkg( 'cgb-dev-utils', { cwd: __dirname } ); 34 | const clearConsole = require( cgbDevUtilsPath + '/clearConsole' ); 35 | const formatWebpackMessages = require( cgbDevUtilsPath + 36 | '/formatWebpackMessages' ); 37 | 38 | // Build file paths. 39 | const theCWD = process.cwd(); 40 | const fileBuildJS = path.resolve( theCWD, './dist/blocks.build.js' ); 41 | const fileEditorCSS = path.resolve( theCWD, './dist/blocks.editor.build.css' ); 42 | const fileStyleCSS = path.resolve( theCWD, './dist/blocks.style.build.css' ); 43 | 44 | /** 45 | * Get File Size 46 | * 47 | * Get filesizes of all the files. 48 | * 49 | * @param {string} filePath path. 50 | * @returns {string} then size result. 51 | */ 52 | const getFileSize = filePath => { 53 | return fileSize( gzipSize.sync( fs.readFileSync( filePath ) ) ); 54 | }; 55 | 56 | clearConsole(); 57 | 58 | // Init the spinner. 59 | const spinner = new ora( { text: '' } ); 60 | 61 | /** 62 | * Build function 63 | * 64 | * Create the production build and print the deployment instructions. 65 | * 66 | * @param {json} webpackConfig config 67 | */ 68 | async function build( webpackConfig ) { 69 | // Start the build. 70 | console.log( '\n' ); 71 | spinner.start( `${ chalk.dim( 'Building and compiling blocks...' ) }` ); 72 | 73 | // Compiler Instance. 74 | const compiler = await webpack( webpackConfig ); 75 | spinner.succeed(); 76 | 77 | // Run the compiler. 78 | compiler.run( ( err, stats ) => { 79 | if ( err ) { 80 | return console.log( err ); 81 | } 82 | 83 | // Get the messages formatted. 84 | const messages = formatWebpackMessages( stats.toJson( {}, true ) ); 85 | 86 | // If there are errors just show the errors. 87 | if ( messages.errors.length ) { 88 | // Only keep the first error. Others are often indicative 89 | // of the same problem, but confuse the reader with noise. 90 | if ( messages.errors.length > 1 ) { 91 | messages.errors.length = 1; 92 | } 93 | // Formatted errors. 94 | clearConsole(); 95 | console.log( '\n❌ ', chalk.black.bgRed( ' Failed to compile build. \n' ) ); 96 | const logErrors = console.log( '\n👉 ', messages.errors.join( '\n\n' ) ); 97 | return logErrors; 98 | } 99 | 100 | // CI. 101 | if ( 102 | process.env.CI && 103 | ( typeof process.env.CI !== 'string' || 104 | process.env.CI.toLowerCase() !== 'false' ) && 105 | messages.warnings.length 106 | ) { 107 | console.log( 108 | chalk.yellow( 109 | '\nTreating warnings as errors because process.env.CI = true.\n' + 110 | 'Most CI servers set it automatically.\n' 111 | ) 112 | ); 113 | return console.log( messages.warnings.join( '\n\n' ) ); 114 | } 115 | 116 | clearConsole(); 117 | console.log( '\n✅ ', chalk.black.bgGreen( ' Built successfully! \n' ) ); 118 | 119 | console.log( 120 | '\n\n', 121 | 'File sizes after gzip:', 122 | '\n\n', 123 | getFileSize( fileBuildJS ), 124 | `${ chalk.dim( '— ./dist/' ) }`, 125 | `${ chalk.green( 'blocks.build.js' ) }`, 126 | '\n', 127 | getFileSize( fileEditorCSS ), 128 | `${ chalk.dim( '— ./dist/' ) }`, 129 | `${ chalk.green( 'blocks.editor.build.css' ) }`, 130 | 131 | '\n', 132 | getFileSize( fileStyleCSS ), 133 | `${ chalk.dim( '— ./dist/' ) }`, 134 | `${ chalk.green( 'blocks.style.build.css' ) }`, 135 | 136 | '\n\n' 137 | ); 138 | 139 | return true; 140 | } ); 141 | } 142 | 143 | build( config ); 144 | -------------------------------------------------------------------------------- /examples/04-multi-block-ejected/scripts/start.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Start 3 | * 4 | * The create-guten-block CLI starts here. 5 | * 6 | * TODO: 7 | * - checkRequiredFiles 8 | * - printBuildError 9 | */ 10 | 'use strict'; 11 | 12 | // Do this as the first thing so that any code reading it knows the right env. 13 | process.env.BABEL_ENV = 'development'; 14 | process.env.NODE_ENV = 'development'; 15 | 16 | // Makes the script crash on unhandled rejections instead of silently 17 | // ignoring them. In the future, promise rejections that are not handled will 18 | // terminate the Node.js process with a non-zero exit code. 19 | process.on( 'unhandledRejection', err => { 20 | throw err; 21 | } ); 22 | 23 | const ora = require( 'ora' ); 24 | const chalk = require( 'chalk' ); 25 | const webpack = require( 'webpack' ); 26 | const config = require( '../config/webpack.config.dev' ); 27 | const resolvePkg = require( 'resolve-pkg' ); 28 | const cgbDevUtilsPath = resolvePkg( 'cgb-dev-utils', { cwd: __dirname } ); 29 | const clearConsole = require( cgbDevUtilsPath + '/clearConsole' ); 30 | const formatWebpackMessages = require( cgbDevUtilsPath + 31 | '/formatWebpackMessages' ); 32 | 33 | // Don't run below node 8. 34 | const currentNodeVersion = process.versions.node; 35 | const semver = currentNodeVersion.split( '.' ); 36 | const major = semver[ 0 ]; 37 | 38 | // If below Node 8. 39 | if ( major < 8 ) { 40 | console.error( 41 | chalk.red( 42 | 'You are running Node ' + 43 | currentNodeVersion + 44 | '.\n' + 45 | 'Create Guten Block requires Node 8 or higher. \n' + 46 | 'Kindly, update your version of Node.' 47 | ) 48 | ); 49 | process.exit( 1 ); 50 | } 51 | 52 | clearConsole(); 53 | 54 | // Init the spinner. 55 | const spinner = new ora( { text: '' } ); 56 | 57 | // Create the production build and print the deployment instructions. 58 | async function build( webpackConfig ) { 59 | // Start the build. 60 | console.log( '\n' ); 61 | spinner.start( `${ chalk.dim( 'Building and compiling blocks...' ) }` ); 62 | 63 | // Compiler Instance. 64 | const compiler = await webpack( webpackConfig ); 65 | spinner.succeed(); 66 | 67 | // Run the compiler. 68 | compiler.watch( {}, ( err, stats ) => { 69 | if ( err ) { 70 | return console.log( err ); 71 | } 72 | 73 | // Get the messages formatted. 74 | const messages = formatWebpackMessages( stats.toJson( {}, true ) ); 75 | 76 | // If there are errors just show the errors. 77 | if ( messages.errors.length ) { 78 | // Only keep the first error. Others are often indicative 79 | // of the same problem, but confuse the reader with noise. 80 | if ( messages.errors.length > 1 ) { 81 | messages.errors.length = 1; 82 | } 83 | // Formatted errors. 84 | clearConsole(); 85 | console.log( '\n❌ ', chalk.black.bgRed( ' Failed to compile. \n' ) ); 86 | const logErrors = console.log( '\n👉 ', messages.errors.join( '\n\n' ) ); 87 | return logErrors; 88 | } 89 | 90 | // CI. 91 | if ( 92 | process.env.CI && 93 | ( typeof process.env.CI !== 'string' || 94 | process.env.CI.toLowerCase() !== 'false' ) && 95 | messages.warnings.length 96 | ) { 97 | console.log( 98 | chalk.yellow( 99 | '\nTreating warnings as errors because process.env.CI = true.\n' + 100 | 'Most CI servers set it automatically.\n' 101 | ) 102 | ); 103 | return console.log( messages.warnings.join( '\n\n' ) ); 104 | } 105 | 106 | clearConsole(); 107 | console.log( '\n✅ ', chalk.black.bgGreen( ' Compiled successfully! \n' ) ); 108 | console.log( 109 | chalk.dim( ' Watching for changes... (Press CTRL + C to stop). \n\n' ) 110 | ); 111 | return console.log( 112 | chalk.dim( ' Note that the development build is not optimized. \n' ), 113 | chalk.dim( 'To create a production build, use' ), 114 | chalk.green( 'npm' ), 115 | chalk.white( 'run build' ) 116 | ); 117 | } ); 118 | } 119 | 120 | build( config ); 121 | -------------------------------------------------------------------------------- /examples/04-multi-block-ejected/src/block/block.js: -------------------------------------------------------------------------------- 1 | /** 2 | * BLOCK: multi-block 3 | * 4 | * Registering a basic block with Gutenberg. 5 | * Simple block, renders and saves the same content without any interactivity. 6 | */ 7 | 8 | // Import CSS. 9 | import './style.scss'; 10 | import './editor.scss'; 11 | 12 | const { __ } = wp.i18n; // Import __() from wp.i18n 13 | const { registerBlockType } = wp.blocks; // Import registerBlockType() from wp.blocks 14 | 15 | /** 16 | * Register: aa Gutenberg Block. 17 | * 18 | * Registers a new block provided a unique name and an object defining its 19 | * behavior. Once registered, the block is made editor as an option to any 20 | * editor interface where blocks are implemented. 21 | * 22 | * @param {string} name Block name. 23 | * @param {Object} settings Block settings. 24 | * @return {?WPBlock} The block, if it has been successfully 25 | * registered; otherwise `undefined`. 26 | */ 27 | registerBlockType( 'cgb/block-multi-block', { 28 | // Block name. Block names must be string that contains a namespace prefix. Example: my-plugin/my-custom-block. 29 | title: __( 'multi-block - CGB Block', 'CGB' ), // Block title. 30 | icon: 'shield', // Block icon from Dashicons → https://developer.wordpress.org/resource/dashicons/. 31 | category: 'common', // Block category — Group blocks together based on common traits E.g. common, formatting, layout widgets, embed. 32 | keywords: [ 33 | __( 'multi-block — CGB Block' ), 34 | __( 'CGB Example' ), 35 | __( 'create-guten-block' ), 36 | ], 37 | 38 | // The "edit" property must be a valid function. 39 | edit: function( props ) { 40 | // Creates a

. 41 | return ( 42 |
43 |

— Hello from the backend.

44 |

45 | CGB BLOCK: multi-block is a new Gutenberg block 46 |

47 |

48 | It was created via{ ' ' } 49 | 50 | 51 | create-guten-block 52 | 53 | . 54 |

55 |
56 | ); 57 | }, 58 | 59 | // The "save" property must be specified and must be a valid function. 60 | save: function( props ) { 61 | return ( 62 |
63 |

— Hello from the frontend.

64 |

65 | CGB BLOCK: multi-block is a new Gutenberg block. 66 |

67 |

68 | It was created via{ ' ' } 69 | 70 | 71 | create-guten-block 72 | 73 | . 74 |

75 |
76 | ); 77 | }, 78 | } ); 79 | -------------------------------------------------------------------------------- /examples/04-multi-block-ejected/src/block/editor.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Editor Styles 3 | * 4 | * CSS for just Backend enqueued after style.scss 5 | * which makes it higher in priority. 6 | */ 7 | 8 | .wp-block-cgb-block-multi-block { 9 | background: $green; 10 | border: 0.2rem solid $black; 11 | color: $black; 12 | margin: 0 auto; 13 | max-width: 740px; 14 | padding: 2rem; 15 | } 16 | -------------------------------------------------------------------------------- /examples/04-multi-block-ejected/src/block/style.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Styles 3 | * 4 | * CSS for both Frontend+Backend. 5 | */ 6 | 7 | .wp-block-cgb-block-multi-block { 8 | background: $red; 9 | border: 0.2rem solid $black; 10 | color: $black; 11 | margin: 0 auto; 12 | max-width: 740px; 13 | padding: 2rem; 14 | } 15 | -------------------------------------------------------------------------------- /examples/04-multi-block-ejected/src/block2/block.js: -------------------------------------------------------------------------------- 1 | /** 2 | * BLOCK: multi-block-2 3 | * 4 | * Registering a basic block with Gutenberg. 5 | * Simple block, renders and saves the same content without any interactivity. 6 | */ 7 | 8 | // Import CSS. 9 | import './style.scss'; 10 | import './editor.scss'; 11 | 12 | const { __ } = wp.i18n; // Import __() from wp.i18n 13 | const { registerBlockType } = wp.blocks; // Import registerBlockType() from wp.blocks 14 | 15 | /** 16 | * Register: aa Gutenberg Block. 17 | * 18 | * Registers a new block provided a unique name and an object defining its 19 | * behavior. Once registered, the block is made editor as an option to any 20 | * editor interface where blocks are implemented. 21 | * 22 | * @param {string} name Block name. 23 | * @param {Object} settings Block settings. 24 | * @return {?WPBlock} The block, if it has been successfully 25 | * registered; otherwise `undefined`. 26 | */ 27 | registerBlockType( 'cgb/block-multi-block-2', { 28 | // Block name. Block names must be string that contains a namespace prefix. Example: my-plugin/my-custom-block. 29 | title: __( 'multi-block-2 - CGB Block', 'CGB' ), // Block title. 30 | icon: 'shield', // Block icon from Dashicons → https://developer.wordpress.org/resource/dashicons/. 31 | category: 'common', // Block category — Group blocks together based on common traits E.g. common, formatting, layout widgets, embed. 32 | keywords: [ 33 | __( 'multi-block-2 — CGB Block' ), 34 | __( 'CGB Example' ), 35 | __( 'create-guten-block' ), 36 | ], 37 | 38 | // The "edit" property must be a valid function. 39 | edit: function( props ) { 40 | // Creates a

. 41 | return ( 42 |
43 |

— Hello from the backend.

44 |

45 | CGB BLOCK: multi-block-2 is a new Gutenberg block 46 |

47 |

48 | It was created via{ ' ' } 49 | 50 | 51 | create-guten-block 52 | 53 | . 54 |

55 |
56 | ); 57 | }, 58 | 59 | // The "save" property must be specified and must be a valid function. 60 | save: function( props ) { 61 | return ( 62 |
63 |

— Hello from the frontend.

64 |

65 | CGB BLOCK: multi-block-2 is a new Gutenberg block. 66 |

67 |

68 | It was created via{ ' ' } 69 | 70 | 71 | create-guten-block 72 | 73 | . 74 |

75 |
76 | ); 77 | }, 78 | } ); 79 | -------------------------------------------------------------------------------- /examples/04-multi-block-ejected/src/block2/editor.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Editor Styles 3 | * 4 | * CSS for just Backend enqueued after style.scss 5 | * which makes it higher in priority. 6 | */ 7 | 8 | .wp-block-cgb-block-multi-block-2 { 9 | background: $green; 10 | border: 0.2rem solid $black; 11 | color: $black; 12 | margin: 0 auto; 13 | max-width: 740px; 14 | padding: 2rem; 15 | } 16 | -------------------------------------------------------------------------------- /examples/04-multi-block-ejected/src/block2/style.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Styles 3 | * 4 | * CSS for both Frontend+Backend. 5 | */ 6 | 7 | .wp-block-cgb-block-multi-block-2 { 8 | background: $red; 9 | border: 0.2rem solid $black; 10 | color: $black; 11 | margin: 0 auto; 12 | max-width: 740px; 13 | padding: 2rem; 14 | } 15 | -------------------------------------------------------------------------------- /examples/04-multi-block-ejected/src/blocks.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Gutenberg Blocks 3 | * 4 | * All blocks related JavaScript. 5 | * You can create a new block folder in 6 | * this dir and include code for that block 7 | * here as well. 8 | * 9 | * All blocks should be included here since 10 | * this is the file that Webpack is compiling. 11 | */ 12 | 13 | import './block/block.js'; 14 | import './block2/block.js'; 15 | -------------------------------------------------------------------------------- /examples/04-multi-block-ejected/src/common.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Common SCSS 3 | * 4 | * Can include things like variables and mixins 5 | * that are used across the project. 6 | */ 7 | 8 | // Colors. 9 | $black: rgb(41, 41, 41); 10 | $white: #f4f4f4; 11 | $gray: #dedede; 12 | $green: #bada55; 13 | $red: orangered; 14 | -------------------------------------------------------------------------------- /examples/04-multi-block-ejected/src/init.php: -------------------------------------------------------------------------------- 1 |

. 57 | return ( 58 | 59 | ); 60 | }, 61 | 62 | /** 63 | * The save function defines the way in which the different attributes should be combined 64 | * into the final markup, which is then serialized by Gutenberg into post_content. 65 | * 66 | * The "save" property must be specified and must be a valid function. 67 | * 68 | * @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/ 69 | * @return {Mixed} Mixed HTML. 70 | */ 71 | save: function() { 72 | // Creates a

. 73 | return ( 74 | 75 | ); 76 | }, 77 | } ); 78 | -------------------------------------------------------------------------------- /examples/05-a11y-input/src/block/editor.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Editor Styles 3 | * 4 | * CSS for just Backend enqueued after style.scss 5 | * which makes it higher in priority. 6 | */ 7 | 8 | .wp-block-cgb-block-a11y-input { 9 | background: $green; 10 | border: 0.2rem solid $black; 11 | color: $black; 12 | margin: 0 auto; 13 | max-width: 740px; 14 | padding: 2rem; 15 | } 16 | -------------------------------------------------------------------------------- /examples/05-a11y-input/src/block/style.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Styles 3 | * 4 | * CSS for both Frontend+Backend. 5 | */ 6 | 7 | .wp-block-cgb-block-a11y-input { 8 | background: $red; 9 | border: 0.2rem solid $black; 10 | color: $black; 11 | margin: 0 auto; 12 | max-width: 740px; 13 | padding: 2rem; 14 | } 15 | -------------------------------------------------------------------------------- /examples/05-a11y-input/src/blocks.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Gutenberg Blocks 3 | * 4 | * All blocks related JavaScript files should be imported here. 5 | * You can create a new block folder in this dir and include code 6 | * for that block here as well. 7 | * 8 | * All blocks should be included here since this is the file that 9 | * Webpack is compiling as the input file. 10 | */ 11 | 12 | import './block/block.js'; 13 | -------------------------------------------------------------------------------- /examples/05-a11y-input/src/common.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Common SCSS 3 | * 4 | * Can include things like variables and mixins 5 | * that are used across the project. 6 | */ 7 | 8 | // Colors. 9 | $black: rgb(41, 41, 41); 10 | $white: #f4f4f4; 11 | $gray: #dedede; 12 | $green: #bada55; 13 | $red: orangered; 14 | -------------------------------------------------------------------------------- /examples/05-a11y-input/src/init.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Example Plugins via `create-guten-block` 5 | 6 | 7 | 8 | Find different examples of WordPress Gutenberg block plugins (#Gutenblocks) created with [Create Guten Block](https://github.com/ahmadawais/create-guten-block). 9 | 10 | - Every folder you see here is a separate WordPress plugin. 11 | - Browse any plugin folder above and read the `README.md` for instructions 12 | 13 | 14 | _Happy Hacking!_ 15 | 16 | _🌟 Star for updates or to appreciate [Create Guten Block →](https://github.com/ahmadawais/create-guten-block)_ 17 | 18 |

19 | 20 | --- 21 | 22 | ###### — Feel free to tweet and say 👋 at me [@MrAhmadAwais](https://twitter.com/mrahmadawais/) 23 | 24 | [![npm](https://img.shields.io/npm/v/create-guten-block.svg?style=flat-square)](https://www.npmjs.com/package/create-guten-block) [![npm](https://img.shields.io/npm/dt/create-guten-block.svg?style=flat-square&label=downloads)](https://www.npmjs.com/package/create-guten-block) [![license](https://img.shields.io/github/license/mashape/apistatus.svg?style=flat-square)](https://github.com/ahmadawais/create-guten-block) [![Tweet for help](https://img.shields.io/twitter/follow/mrahmadawais.svg?style=social&label=Tweet%20@MrAhmadAwais)](https://twitter.com/mrahmadawais/) [![GitHub stars](https://img.shields.io/github/stars/ahmadawais/create-guten-block.svg?style=social&label=Stars)](https://github.com/ahmadawais/create-guten-block/stargazers) [![GitHub followers](https://img.shields.io/github/followers/ahmadawais.svg?style=social&label=Follow)](https://github.com/ahmadawais?tab=followers) 25 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "lerna": "2.8.0", 3 | "packages": ["packages/*"], 4 | "version": "independent", 5 | "npmClient": "yarn", 6 | "useWorkspaces": true, 7 | "commands": { 8 | "publish": { 9 | "message": "🚀 RELEASE: New version!" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 [Ahmad Awais](https://AhmadAwais.com/) ⚡️ 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 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "workspaces": [ 4 | "packages/*" 5 | ], 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/ahmadawais/create-guten-block.git" 9 | }, 10 | "author": "AhmadAwais", 11 | "bugs": { 12 | "url": "https://github.com/ahmadawais/create-guten-block/issues" 13 | }, 14 | "homepage": "https://github.com/ahmadawais/create-guten-block#readme", 15 | "devDependencies": { 16 | "babel-eslint": "^8.2.1", 17 | "chalk": "^2.4.2", 18 | "eslint": "^4.17.0", 19 | "eslint-config-wordpress": "^2.0.0", 20 | "eslint-plugin-jest": "^21.7.0", 21 | "eslint-plugin-jsx-a11y": "^6.2.1", 22 | "eslint-plugin-react": "^7.13.0", 23 | "eslint-plugin-wordpress": "^0.1.0", 24 | "execa": "^1.0.0", 25 | "lerna": "^2.8.0", 26 | "ora": "^1.3.0", 27 | "shelljs": "^0.8.3", 28 | "update-notifier": "^3.0.0" 29 | }, 30 | "scripts": { 31 | "create-guten-block": "node tasks/cgb.js", 32 | "demo": "node tasks/cgb.js demo", 33 | "cgb": "node packages/create-guten-block/index.js", 34 | "startCGB": "node packages/cgb-scripts/scripts/start.js", 35 | "changelog": "lerna-changelog", 36 | "updated": "lerna updated", 37 | "beforepublish": "lerna bootstrap", 38 | "publishScript": "bash tasks/publish.sh && echo 'Now update dependency packages.'", 39 | "publishNPM": "bash tasks/publish.sh --npm-client=npm", 40 | "lerna": "yarn && lerna updated && lerna bootstrap && lerna publish --independent --npm-client=npm", 41 | "publishCanary": "yarn && lerna bootstrap && lerna publish --independent --npm-client=npm --canary", 42 | "release": "yarn && lerna updated && lerna bootstrap && lerna publish --independent --npm-client=npm", 43 | "release-npm": "lerna updated && lerna bootstrap && lerna publish --independent --npm-client=npm", 44 | "release-canary": "yarn && lerna updated && lerna bootstrap && lerna publish --independent --npm-client=npm --canary" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/babel-preset-cgb/.gitignore: -------------------------------------------------------------------------------- 1 | # Packages # 2 | ############ 3 | *.7z 4 | *.dmg 5 | *.gz 6 | *.bz2 7 | *.iso 8 | *.jar 9 | *.rar 10 | *.tar 11 | *.zip 12 | *.tgz 13 | *.map 14 | 15 | # Logs and databases # 16 | ###################### 17 | *.log 18 | *.sql 19 | 20 | # OS generated files # 21 | ###################### 22 | **.DS_Store* 23 | ehthumbs.db 24 | Icon? 25 | Thumbs.db 26 | ._* 27 | 28 | # Vim generated files # 29 | ###################### 30 | *.un~ 31 | 32 | # SASS # 33 | ########## 34 | **/.sass-cache 35 | **/.sass-cache/* 36 | **/.map 37 | 38 | # Composer # 39 | ########## 40 | vendors/composer/ 41 | !assets/js/vendor/ 42 | wpcs/ 43 | composer.lock 44 | 45 | # Bower # 46 | ########## 47 | assets/bower_components/* 48 | 49 | # Codekit # 50 | ########## 51 | /codekit-config.json 52 | *.codekit 53 | **.codekit-cache/* 54 | 55 | # NPM # 56 | ########## 57 | node_modules 58 | **/node_modules/** 59 | 60 | # Compiled Files and Build Dirs # 61 | ########## 62 | /README.html 63 | 64 | # PhpStrom Project Files # 65 | .idea/ 66 | library/vendors/composer 67 | assets/img/.DS_Store 68 | assets/sass/HTML 69 | assets/sass/Rails 70 | HTML 71 | Rails 72 | 73 | # CGB 74 | .idea/ 75 | .vscode/ 76 | node_modules/ 77 | .DS_Store 78 | *.tgz 79 | my-app* 80 | template/src/__tests__/__snapshots__/ 81 | lerna-debug.log 82 | npm-debug.log* 83 | yarn-debug.log* 84 | yarn-error.log* 85 | /.changelog -------------------------------------------------------------------------------- /packages/babel-preset-cgb/.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /packages/babel-preset-cgb/README.md: -------------------------------------------------------------------------------- 1 | # Babel Preset CGB 2 | 3 | > The Babel Preset for Create Guten Block — to help transpile your next-gen WordPress Gutenberg plugins.. 4 | 5 | [![npm](https://img.shields.io/npm/v/babel-preset-cgb.svg?style=flat-square)](https://www.npmjs.com/package/create-guten-block) [![npm](https://img.shields.io/npm/dt/babel-preset-cgb.svg?style=flat-square&label=downloads)](https://www.npmjs.com/package/create-guten-block) [![license](https://img.shields.io/github/license/mashape/apistatus.svg?style=flat-square)](https://github.com/ahmadawais/create-guten-block) [![Tweet for help](https://img.shields.io/twitter/follow/mrahmadawais.svg?style=social&label=Tweet%20@MrAhmadAwais)](https://twitter.com/mrahmadawais/) [![GitHub stars](https://img.shields.io/github/stars/ahmadawais/create-guten-block.svg?style=social&label=Stars)](https://github.com/ahmadawais/create-guten-block/stargazers) [![GitHub followers](https://img.shields.io/github/followers/ahmadawais.svg?style=social&label=Follow)](https://github.com/ahmadawais?tab=followers) 6 | 7 | 🙌 This package includes babel preset used by [Create Guten Block](https://github.com/ahmadawais/create-guten-block). 8 |
Kindly, refer to its documentation. 9 | 10 | 11 | CGB Create Guten Block by Ahmad Awais 12 | 13 |
14 | 15 | Create Guten Block 16 | 17 |
18 | 19 | 20 | 21 | 25 | 26 | 27 | 30 | 35 | 36 | 37 |
22 | create-guten-block
23 | A zero-configuration developer toolkit for building WordPress Gutenberg block plugins. 24 |
28 | A FOSS (Free & Open Source Software) project developed by Ahmad Awais. 29 | 31 | 32 | 33 | 34 |
Follow Ahmad's #FOSS work on GitHub @AhmadAwais — Say Hi on Twitter @MrAhmadAwais👋
38 |
39 | 40 | # 📦 `create-guten-block` 41 | 42 | >`create-guten-block` is _zero configuration dev-toolkit_ (#0CJS) to develop WordPress Gutenberg blocks in a matter of minutes without configuring `React`, `Webpack`, `ES6/7/8/Next`, `ESLint`, `Babel`, etc. 43 | 44 | 👉 This package includes the global command for [Create Guten Block](https://github.com/ahmadawais/create-guten-block). 45 | 46 |
47 | 48 | 👉 Kindly, read the up to date documentation at this link → [Create Guten Block](https://github.com/ahmadawais/create-guten-block) 49 | -------------------------------------------------------------------------------- /packages/babel-preset-cgb/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Basically the .babelrc file. 3 | */ 4 | 5 | // Update notifier. 6 | const updateNotifier = require( 'update-notifier' ); 7 | const pkg = require( './package.json' ); 8 | updateNotifier( { pkg } ).notify(); 9 | 10 | module.exports = { 11 | presets: [ 12 | [ 13 | // 'env', 14 | require.resolve( 'babel-preset-env' ), 15 | { 16 | // Do not transform modules to CJS. 17 | modules: false, 18 | targets: { 19 | browsers: [ 20 | 'last 2 Chrome versions', 21 | 'last 2 Firefox versions', 22 | 'last 2 Safari versions', 23 | 'last 2 iOS versions', 24 | 'last 1 Android version', 25 | 'last 1 ChromeAndroid version', 26 | 'ie 11', 27 | ], 28 | }, 29 | }, 30 | ], 31 | ], 32 | plugins: [ 33 | // class { handleClick = () => { } }. 34 | [ require.resolve( 'babel-plugin-transform-class-properties' ) ], 35 | // The following two plugins use Object.assign directly, instead of Babel's 36 | // extends helper. Note that this assumes `Object.assign` is available. 37 | // { ...todo, completed: true } 38 | [ 39 | require.resolve( 'babel-plugin-transform-object-rest-spread' ), 40 | { 41 | useBuiltIns: true, 42 | }, 43 | ], 44 | [ 45 | // Transforms JSX Syntax. 46 | // 'transform-react-jsx', 47 | require.resolve( 'babel-plugin-transform-react-jsx' ), 48 | { 49 | pragma: 'wp.element.createElement', 50 | }, 51 | ], 52 | // Async/Await awesomeness https://babeljs.io/docs/en/babel-plugin-syntax-async-functions/. 53 | [ require.resolve( 'babel-plugin-syntax-async-functions' ) ], 54 | // Polyfills the runtime needed for async/await and generators. 55 | [ 56 | require.resolve( 'babel-plugin-transform-runtime' ), 57 | { 58 | helpers: false, 59 | polyfill: false, 60 | regenerator: true, 61 | }, 62 | ], 63 | ], 64 | }; 65 | -------------------------------------------------------------------------------- /packages/babel-preset-cgb/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "babel-preset-cgb", 3 | "version": "1.7.0", 4 | "description": "Babel preset used by Create Guten Block.", 5 | "repository": "ahmadawais/create-guten-block", 6 | "license": "MIT", 7 | "keywords": [ 8 | "gutenberg", 9 | "create-gutenberg-block", 10 | "create-gutenberg-blocks", 11 | "wp", 12 | "wordpress", 13 | "cgb", 14 | "wp webpack", 15 | "react", 16 | "ESLint", 17 | "Webpack", 18 | "wp-scripts", 19 | "cgb-scripts", 20 | "guten-scripts", 21 | "babel", 22 | "cgb-dev-utils", 23 | "babel-preset-cgb" 24 | ], 25 | "author": "Ahmad Awais (https://AhmadAwais.com/)", 26 | "bugs": { 27 | "url": "https://github.com/ahmadawais/create-guten-block/issues" 28 | }, 29 | "files": [ 30 | "index.js" 31 | ], 32 | "dependencies": { 33 | "@scarf/scarf": "^1.0.6", 34 | "babel-plugin-syntax-async-functions": "^6.13.0", 35 | "babel-plugin-transform-class-properties": "6.24.1", 36 | "babel-plugin-transform-object-rest-spread": "^6.26.0", 37 | "babel-plugin-transform-react-jsx": "^6.24.1", 38 | "babel-plugin-transform-runtime": "^6.23.0", 39 | "babel-preset-env": "^1.6.0", 40 | "update-notifier": "^2.3.0" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/cgb-dev-utils/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "env", 5 | { 6 | "modules": false, 7 | "targets": { 8 | "browsers": [ 9 | "last 2 Chrome versions", 10 | "last 2 Firefox versions", 11 | "last 2 Safari versions", 12 | "last 2 iOS versions", 13 | "last 1 Android version", 14 | "last 1 ChromeAndroid version", 15 | "ie 11" 16 | ] 17 | } 18 | } 19 | ] 20 | ], 21 | "plugins": [ 22 | [ 23 | "transform-react-jsx", 24 | { 25 | "pragma": "wp.element.createElement" 26 | } 27 | ] 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /packages/cgb-dev-utils/.gitignore: -------------------------------------------------------------------------------- 1 | # Packages # 2 | ############ 3 | *.7z 4 | *.dmg 5 | *.gz 6 | *.bz2 7 | *.iso 8 | *.jar 9 | *.rar 10 | *.tar 11 | *.zip 12 | *.tgz 13 | *.map 14 | 15 | # Logs and databases # 16 | ###################### 17 | *.log 18 | *.sql 19 | 20 | # OS generated files # 21 | ###################### 22 | **.DS_Store* 23 | ehthumbs.db 24 | Icon? 25 | Thumbs.db 26 | ._* 27 | 28 | # Vim generated files # 29 | ###################### 30 | *.un~ 31 | 32 | # SASS # 33 | ########## 34 | **/.sass-cache 35 | **/.sass-cache/* 36 | **/.map 37 | 38 | # Composer # 39 | ########## 40 | vendors/composer/ 41 | !assets/js/vendor/ 42 | wpcs/ 43 | composer.lock 44 | 45 | # Bower # 46 | ########## 47 | assets/bower_components/* 48 | 49 | # Codekit # 50 | ########## 51 | /codekit-config.json 52 | *.codekit 53 | **.codekit-cache/* 54 | 55 | # NPM # 56 | ########## 57 | node_modules 58 | **/node_modules/** 59 | 60 | # Compiled Files and Build Dirs # 61 | ########## 62 | /README.html 63 | 64 | # PhpStrom Project Files # 65 | .idea/ 66 | library/vendors/composer 67 | assets/img/.DS_Store 68 | assets/sass/HTML 69 | assets/sass/Rails 70 | HTML 71 | Rails 72 | 73 | # CGB 74 | .idea/ 75 | .vscode/ 76 | node_modules/ 77 | .DS_Store 78 | *.tgz 79 | my-app* 80 | template/src/__tests__/__snapshots__/ 81 | lerna-debug.log 82 | npm-debug.log* 83 | yarn-debug.log* 84 | yarn-error.log* 85 | /.changelog -------------------------------------------------------------------------------- /packages/cgb-dev-utils/.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /packages/cgb-dev-utils/README.md: -------------------------------------------------------------------------------- 1 | # CGB Dev Utils 2 | 3 | > Create Guten Block Developer Utilities for your next-gen WordPress Gutenberg plugins.. 4 | 5 | [![npm](https://img.shields.io/npm/v/cgb-dev-utils.svg?style=flat-square)](https://www.npmjs.com/package/create-guten-block) [![npm](https://img.shields.io/npm/dt/cgb-dev-utils.svg?style=flat-square&label=downloads)](https://www.npmjs.com/package/create-guten-block) [![license](https://img.shields.io/github/license/mashape/apistatus.svg?style=flat-square)](https://github.com/ahmadawais/create-guten-block) [![Tweet for help](https://img.shields.io/twitter/follow/mrahmadawais.svg?style=social&label=Tweet%20@MrAhmadAwais)](https://twitter.com/mrahmadawais/) [![GitHub stars](https://img.shields.io/github/stars/ahmadawais/create-guten-block.svg?style=social&label=Stars)](https://github.com/ahmadawais/create-guten-block/stargazers) [![GitHub followers](https://img.shields.io/github/followers/ahmadawais.svg?style=social&label=Follow)](https://github.com/ahmadawais?tab=followers) 6 | 7 | 🙌 This package includes scripts and developer utilities used by [Create Guten Block](https://github.com/ahmadawais/create-guten-block).
Kindly, refer to its documentation. 8 | 9 | CGB Create Guten Block by Ahmad Awais 10 | 11 |
12 | 13 | Create Guten Block 14 | 15 |
16 | 17 | 18 | 19 | 23 | 24 | 25 | 28 | 33 | 34 | 35 |
20 | create-guten-block
21 | A zero-configuration developer toolkit for building WordPress Gutenberg block plugins. 22 |
26 | A FOSS (Free & Open Source Software) project developed by Ahmad Awais. 27 | 29 | 30 | 31 | 32 |
Follow Ahmad's #FOSS work on GitHub @AhmadAwais — Say Hi on Twitter @MrAhmadAwais👋
36 |
37 | 38 | # 📦 `create-guten-block` 39 | 40 | >`create-guten-block` is _zero configuration dev-toolkit_ (#0CJS) to develop WordPress Gutenberg blocks in a matter of minutes without configuring `React`, `Webpack`, `ES6/7/8/Next`, `ESLint`, `Babel`, etc. 41 | 42 | 👉 This package includes the global command for [Create Guten Block](https://github.com/ahmadawais/create-guten-block). 43 | 44 |
45 | 46 | 👉 Kindly, read the up to date documentation at this link → [Create Guten Block](https://github.com/ahmadawais/create-guten-block) 47 | -------------------------------------------------------------------------------- /packages/cgb-dev-utils/clearConsole.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Clear console 3 | * 4 | * Cross platform clear console. 5 | * TODO: 6 | * @credits CRA 7 | */ 8 | 9 | 'use strict'; 10 | 11 | // Update notifier. 12 | const updateNotifier = require( 'update-notifier' ); 13 | const pkg = require( './package.json' ); 14 | updateNotifier( { pkg } ).notify(); 15 | 16 | /** 17 | * Cross platform clear console. 18 | */ 19 | function clearConsole() { 20 | process.stdout.write( 21 | process.platform === 'win32' ? '\x1B[2J\x1B[0f' : '\x1B[2J\x1B[3J\x1B[H' 22 | ); 23 | } 24 | 25 | module.exports = clearConsole; 26 | -------------------------------------------------------------------------------- /packages/cgb-dev-utils/crossSpawn.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Cross Spwan 3 | * 4 | * TODO: 5 | * @credits CRA 6 | */ 7 | 8 | 'use strict'; 9 | 10 | // Update notifier. 11 | const updateNotifier = require( 'update-notifier' ); 12 | const pkg = require( './package.json' ); 13 | updateNotifier( { pkg } ).notify(); 14 | 15 | const crossSpawn = require( 'cross-spawn' ); 16 | 17 | module.exports = crossSpawn; 18 | -------------------------------------------------------------------------------- /packages/cgb-dev-utils/formatWebpackMessages.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Webpack Format Messages 3 | * 4 | * TODO: 5 | * @credits CRA 6 | */ 7 | 8 | 'use strict'; 9 | 10 | // Update notifier. 11 | const updateNotifier = require( 'update-notifier' ); 12 | const pkg = require( './package.json' ); 13 | updateNotifier( { pkg } ).notify(); 14 | 15 | // WARNING: this code is untranspiled and is used in browser too. 16 | // Please make sure any changes are in ES5 or contribute a Babel compile step. 17 | 18 | // Some custom utilities to prettify Webpack output. 19 | // This is quite hacky and hopefully won't be needed when Webpack fixes this. 20 | // https://github.com/webpack/webpack/issues/2878 21 | 22 | const chalk = require( 'chalk' ); 23 | const friendlySyntaxErrorLabel = 'Syntax error:'; 24 | 25 | function isLikelyASyntaxError( message ) { 26 | return message.indexOf( friendlySyntaxErrorLabel ) !== -1; 27 | } 28 | 29 | // Cleans up webpack error messages. 30 | // eslint-disable-next-line no-unused-vars 31 | function formatMessage( message, isError ) { 32 | let lines = message.split( '\n' ); 33 | 34 | if ( lines.length > 2 && lines[ 1 ] === '' ) { 35 | // Remove extra newline. 36 | lines.splice( 1, 1 ); 37 | } 38 | 39 | // Remove webpack-specific loader notation from filename. 40 | // Before: 41 | // ./~/css-loader!./~/postcss-loader!./src/App.css 42 | // After: 43 | // ./src/App.css 44 | if ( lines[ 0 ].lastIndexOf( '!' ) !== -1 ) { 45 | lines[ 0 ] = lines[ 0 ].substr( lines[ 0 ].lastIndexOf( '!' ) + 1 ); 46 | } 47 | 48 | lines = lines.filter( function( line ) { 49 | // Webpack adds a list of entry points to warning messages: 50 | // @ ./src/index.js 51 | // @ multi react-scripts/~/react-dev-utils/webpackHotDevClient.js ... 52 | // It is misleading (and unrelated to the warnings) so we clean it up. 53 | // It is only useful for syntax errors but we have beautiful frames for them. 54 | return line.indexOf( ' @ ' ) !== 0; 55 | } ); 56 | 57 | // line #0 is filename 58 | // line #1 is the main error message 59 | if ( ! lines[ 0 ] || ! lines[ 1 ] ) { 60 | return lines.join( '\n' ); 61 | } 62 | 63 | // Cleans up verbose "module not found" messages for files and packages. 64 | if ( lines[ 1 ].indexOf( 'Module not found: ' ) === 0 ) { 65 | lines = [ 66 | lines[ 0 ], 67 | // Clean up message because "Module not found: " is descriptive enough. 68 | lines[ 1 ] 69 | .replace( 'Cannot resolve \'file\' or \'directory\' ', '' ) 70 | .replace( 'Cannot resolve module ', '' ) 71 | .replace( 'Error: ', '' ) 72 | .replace( '[CaseSensitivePathsPlugin] ', '' ), 73 | ]; 74 | } 75 | 76 | // Cleans up syntax error messages. 77 | if ( lines[ 1 ].indexOf( 'Module build failed: ' ) === 0 ) { 78 | lines[ 1 ] = lines[ 1 ].replace( 79 | 'Module build failed: SyntaxError:', 80 | friendlySyntaxErrorLabel 81 | ); 82 | } 83 | 84 | // Clean up export errors. 85 | // TODO: we should really send a PR to Webpack for this. 86 | const exportError = /\s*(.+?)\s*(")?export '(.+?)' was not found in '(.+?)'/; 87 | if ( lines[ 1 ].match( exportError ) ) { 88 | lines[ 1 ] = lines[ 1 ].replace( 89 | exportError, 90 | '$1 \'$4\' does not contain an export named \'$3\'.' 91 | ); 92 | } 93 | 94 | lines[ 0 ] = chalk.inverse( lines[ 0 ] ); 95 | 96 | // Reassemble the message. 97 | message = lines.join( '\n' ); 98 | // Internal stacks are generally useless so we strip them... with the 99 | // exception of stacks containing `webpack:` because they're normally 100 | // from user code generated by WebPack. For more information see 101 | // https://github.com/facebookincubator/create-react-app/pull/1050 102 | message = message.replace( 103 | /^\s*at\s((?!webpack:).)*:\d+:\d+[\s)]*(\n|$)/gm, 104 | '' 105 | ); // at ... ...:x:y 106 | 107 | return message.trim(); 108 | } 109 | 110 | function formatWebpackMessages( json ) { 111 | const formattedErrors = json.errors.map( function( message ) { 112 | return formatMessage( message, true ); 113 | } ); 114 | const formattedWarnings = json.warnings.map( function( message ) { 115 | return formatMessage( message, false ); 116 | } ); 117 | const result = { 118 | errors: formattedErrors, 119 | warnings: formattedWarnings, 120 | }; 121 | if ( result.errors.some( isLikelyASyntaxError ) ) { 122 | // If there are any syntax errors, show just them. 123 | // This prevents a confusing ESLint parsing error 124 | // preceding a much more useful Babel syntax error. 125 | result.errors = result.errors.filter( isLikelyASyntaxError ); 126 | } 127 | return result; 128 | } 129 | 130 | module.exports = formatWebpackMessages; 131 | -------------------------------------------------------------------------------- /packages/cgb-dev-utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cgb-dev-utils", 3 | "version": "1.6.0", 4 | "description": "Developer utilities used by Create Guten Block.", 5 | "repository": "ahmadawais/create-guten-block", 6 | "keywords": [ 7 | "gutenberg", 8 | "create-gutenberg-block", 9 | "create-gutenberg-blocks", 10 | "wp", 11 | "wordpress", 12 | "cgb", 13 | "wp webpack", 14 | "react", 15 | "ESLint", 16 | "Webpack", 17 | "wp-scripts", 18 | "cgb-scripts", 19 | "guten-scripts", 20 | "babel", 21 | "cgb-dev-utils", 22 | "babel-preset-cgb" 23 | ], 24 | "author": "Ahmad Awais (https://AhmadAwais.com/)", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/ahmadawais/create-guten-block/issues" 28 | }, 29 | "dependencies": { 30 | "@scarf/scarf": "^1.0.6", 31 | "chalk": "2.3.0", 32 | "cross-spawn": "5.1.0", 33 | "update-notifier": "^2.3.0" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/cgb-scripts/.gitignore: -------------------------------------------------------------------------------- 1 | # Packages # 2 | ############ 3 | *.7z 4 | *.dmg 5 | *.gz 6 | *.bz2 7 | *.iso 8 | *.jar 9 | *.rar 10 | *.tar 11 | *.zip 12 | *.tgz 13 | *.map 14 | 15 | # Logs and databases # 16 | ###################### 17 | *.log 18 | *.sql 19 | 20 | # OS generated files # 21 | ###################### 22 | **.DS_Store* 23 | ehthumbs.db 24 | Icon? 25 | Thumbs.db 26 | ._* 27 | 28 | # Vim generated files # 29 | ###################### 30 | *.un~ 31 | 32 | # SASS # 33 | ########## 34 | **/.sass-cache 35 | **/.sass-cache/* 36 | **/.map 37 | 38 | # Composer # 39 | ########## 40 | vendors/composer/ 41 | !assets/js/vendor/ 42 | wpcs/ 43 | composer.lock 44 | 45 | # Bower # 46 | ########## 47 | assets/bower_components/* 48 | 49 | # Codekit # 50 | ########## 51 | /codekit-config.json 52 | *.codekit 53 | **.codekit-cache/* 54 | 55 | # NPM # 56 | ########## 57 | node_modules 58 | **/node_modules/** 59 | 60 | # Compiled Files and Build Dirs # 61 | ########## 62 | /README.html 63 | 64 | # PhpStrom Project Files # 65 | .idea/ 66 | library/vendors/composer 67 | assets/img/.DS_Store 68 | assets/sass/HTML 69 | assets/sass/Rails 70 | HTML 71 | Rails 72 | 73 | # CGB 74 | .idea/ 75 | .vscode/ 76 | node_modules/ 77 | .DS_Store 78 | *.tgz 79 | my-app* 80 | template/src/__tests__/__snapshots__/ 81 | lerna-debug.log 82 | npm-debug.log* 83 | yarn-debug.log* 84 | yarn-error.log* 85 | /.changelog -------------------------------------------------------------------------------- /packages/cgb-scripts/.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /packages/cgb-scripts/README.MD: -------------------------------------------------------------------------------- 1 | # CGB Scripts 2 | 3 | > Create Guten Block Scripts to init, start, build your next-gen WordPress Gutenberg plugins. 4 | 5 | [![npm](https://img.shields.io/npm/v/cgb-scripts.svg?style=flat-square)](https://www.npmjs.com/package/create-guten-block) [![npm](https://img.shields.io/npm/dt/cgb-scripts.svg?style=flat-square&label=downloads)](https://www.npmjs.com/package/create-guten-block) [![license](https://img.shields.io/github/license/mashape/apistatus.svg?style=flat-square)](https://github.com/ahmadawais/create-guten-block) [![Tweet for help](https://img.shields.io/twitter/follow/mrahmadawais.svg?style=social&label=Tweet%20@MrAhmadAwais)](https://twitter.com/mrahmadawais/) [![GitHub stars](https://img.shields.io/github/stars/ahmadawais/create-guten-block.svg?style=social&label=Stars)](https://github.com/ahmadawais/create-guten-block/stargazers) [![GitHub followers](https://img.shields.io/github/followers/ahmadawais.svg?style=social&label=Follow)](https://github.com/ahmadawais?tab=followers) 6 | 7 | 🙌 This package includes scripts and configuration used by [Create Guten Block](https://github.com/ahmadawais/create-guten-block).
Kindly, refer to its documentation. 8 | 9 | 10 | 11 | CGB Create Guten Block by Ahmad Awais 12 | 13 |
14 | 15 | Create Guten Block 16 | 17 |
18 | 19 | 20 | 21 | 25 | 26 | 27 | 30 | 35 | 36 | 37 |
22 | create-guten-block
23 | A zero-configuration developer toolkit for building WordPress Gutenberg block plugins. 24 |
28 | A FOSS (Free & Open Source Software) project developed by Ahmad Awais. 29 | 31 | 32 | 33 | 34 |
Follow Ahmad's #FOSS work on GitHub @AhmadAwais — Say Hi on Twitter @MrAhmadAwais👋
38 |
39 | 40 | # 📦 `create-guten-block` 41 | 42 | >`create-guten-block` is _zero configuration dev-toolkit_ (#0CJS) to develop WordPress Gutenberg blocks in a matter of minutes without configuring `React`, `Webpack`, `ES6/7/8/Next`, `ESLint`, `Babel`, etc. 43 | 44 | 👉 This package includes the global command for [Create Guten Block](https://github.com/ahmadawais/create-guten-block). 45 | 46 |
47 | 48 | 👉 Kindly, read the up to date documentation at this link → [Create Guten Block](https://github.com/ahmadawais/create-guten-block) 49 | -------------------------------------------------------------------------------- /packages/cgb-scripts/bin/cgb-scripts.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict'; 3 | 4 | // Update notifier. 5 | const updateNotifier = require( 'update-notifier' ); 6 | const pkg = require( '../package.json' ); 7 | updateNotifier( { pkg } ).notify(); 8 | 9 | const spawn = require( 'cgb-dev-utils/crossSpawn' ); 10 | const args = process.argv.slice( 2 ); 11 | 12 | const scriptIndex = args.findIndex( 13 | // x => x === 'build' || x === 'eject' || x === 'start' || x === 'test' 14 | x => x === 'start' || x === 'build' || x === 'eject' || x === 'test' 15 | ); 16 | const script = scriptIndex === -1 ? args[ 0 ] : args[ scriptIndex ]; 17 | const nodeArgs = scriptIndex > 0 ? args.slice( 0, scriptIndex ) : []; 18 | 19 | switch ( script ) { 20 | case 'build': 21 | case 'eject': 22 | case 'start': 23 | case 'test': { 24 | const result = spawn.sync( 25 | 'node', 26 | nodeArgs 27 | .concat( require.resolve( '../scripts/' + script ) ) 28 | .concat( args.slice( scriptIndex + 1 ) ), 29 | { stdio: 'inherit' } 30 | ); 31 | if ( result.signal ) { 32 | if ( result.signal === 'SIGKILL' ) { 33 | console.log( 34 | 'The build failed because the process exited too early. ' + 35 | 'This probably means the system ran out of memory or someone called ' + 36 | '`kill -9` on the process.' 37 | ); 38 | } else if ( result.signal === 'SIGTERM' ) { 39 | console.log( 40 | 'The build failed because the process exited too early. ' + 41 | 'Someone might have called `kill` or `killall`, or the system could ' + 42 | 'be shutting down.' 43 | ); 44 | } 45 | process.exit( 1 ); 46 | } 47 | process.exit( result.status ); 48 | break; 49 | } 50 | default: 51 | console.log( 'Unknown script "' + script + '".' ); 52 | console.log( 'Perhaps you need to update cgb-scripts?' ); 53 | console.log( 54 | 'Update via: npm install -g create-guten-block or npm install cgb-scripts' 55 | ); 56 | break; 57 | } 58 | -------------------------------------------------------------------------------- /packages/cgb-scripts/config/externals.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Utility methods for use when generating build configuration objects. 3 | */ 4 | const { join } = require( 'path' ); 5 | 6 | /** 7 | * Given a string, returns a new string with dash separators converted to 8 | * camel-case equivalent. This is not as aggressive as `_.camelCase`, which 9 | * which would also upper-case letters following numbers. 10 | * 11 | * @param {string} string Input dash-delimited string. 12 | * 13 | * @return {string} Camel-cased string. 14 | */ 15 | const camelCaseDash = string => string.replace( /-([a-z])/g, ( match, letter ) => letter.toUpperCase() ); 16 | 17 | /** 18 | * Define externals to load components through the wp global. 19 | */ 20 | const externals = [ 21 | 'components', 22 | 'api-fetch', 23 | 'edit-post', 24 | 'element', 25 | 'plugins', 26 | 'editor', 27 | 'block-editor', 28 | 'blocks', 29 | 'hooks', 30 | 'utils', 31 | 'date', 32 | 'data', 33 | 'i18n', 34 | ].reduce( 35 | ( externals, name ) => ( { 36 | ...externals, 37 | [ `@wordpress/${ name }` ]: `wp.${ camelCaseDash( name ) }`, 38 | } ), 39 | { 40 | wp: 'wp', 41 | ga: 'ga', // Old Google Analytics. 42 | gtag: 'gtag', // New Google Analytics. 43 | react: 'React', // React itself is there in Gutenberg. 44 | jquery: 'jQuery', // import $ from 'jquery'; // Use jQuery from WP after enqueuing it. 45 | 'react-dom': 'ReactDOM', 46 | lodash: 'lodash', // Lodash is there in Gutenberg. 47 | cgbGlobal: 'cgbGlobal', // import globals from 'cgbGlobal'; // Localized data. 48 | } 49 | ); 50 | 51 | module.exports = externals; 52 | -------------------------------------------------------------------------------- /packages/cgb-scripts/config/paths.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Paths 3 | * 4 | * Project related paths. 5 | */ 6 | 7 | const path = require( 'path' ); 8 | const fs = require( 'fs' ); 9 | 10 | // Make sure any symlinks in the project folder are resolved: 11 | const pluginDir = fs.realpathSync( process.cwd() ); 12 | const resolvePlugin = relativePath => path.resolve( pluginDir, relativePath ); 13 | 14 | // Config after eject: we're in ./config/ 15 | module.exports = { 16 | dotenv: resolvePlugin( '.env' ), 17 | pluginSrc: resolvePlugin( 'src' ), // Plugin src folder path. 18 | pluginBlocksJs: resolvePlugin( 'src/blocks.js' ), 19 | yarnLockFile: resolvePlugin( 'yarn.lock' ), 20 | pluginDist: resolvePlugin( '.' ), // We are in ./dist folder already so the path '.' resolves to ./dist/. 21 | }; 22 | 23 | // @remove-on-eject-begin 24 | const resolveOwn = relativePath => path.resolve( __dirname, '..', relativePath ); 25 | 26 | // config before eject: we're in ./node_modules/react-scripts/config/ 27 | module.exports = { 28 | dotenv: resolvePlugin( '.env' ), 29 | pluginSrc: resolvePlugin( 'src' ), 30 | pluginBlocksJs: resolvePlugin( 'src/blocks.js' ), 31 | pluginDist: resolvePlugin( '.' ), // We are in ./dist folder already so the path '.' resolves to ./dist/. 32 | yarnLockFile: resolvePlugin( 'yarn.lock' ), 33 | appPath: resolvePlugin( '.' ), 34 | // These properties only exist before ejecting: 35 | ownPath: resolveOwn( '.' ), 36 | }; 37 | // @remove-on-eject-end 38 | -------------------------------------------------------------------------------- /packages/cgb-scripts/config/webpack.config.dev.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Webpack Configuration 3 | * 4 | * Working of a Webpack can be very simple or complex. This is an intenally simple 5 | * build configuration. 6 | * 7 | * Webpack basics — If you are new the Webpack here's all you need to know: 8 | * 1. Webpack is a module bundler. It bundles different JS modules together. 9 | * 2. It needs and entry point and an ouput to process file(s) and bundle them. 10 | * 3. By default it only understands common JavaScript but you can make it 11 | * understand other formats by way of adding a Webpack loader. 12 | * 4. In the file below you will find an entry point, an ouput, and a babel-loader 13 | * that tests all .js files excluding the ones in node_modules to process the 14 | * ESNext and make it compatible with older browsers i.e. it converts the 15 | * ESNext (new standards of JavaScript) into old JavaScript through a loader 16 | * by Babel. 17 | * 18 | * TODO: Instructions. 19 | * 20 | * @since 1.0.0 21 | */ 22 | 23 | const paths = require( './paths' ); 24 | const externals = require( './externals' ); 25 | const autoprefixer = require( 'autoprefixer' ); 26 | const ExtractTextPlugin = require( 'extract-text-webpack-plugin' ); 27 | 28 | // Extract style.css for both editor and frontend styles. 29 | const blocksCSSPlugin = new ExtractTextPlugin( { 30 | filename: './dist/blocks.style.build.css', 31 | } ); 32 | 33 | // Extract editor.css for editor styles. 34 | const editBlocksCSSPlugin = new ExtractTextPlugin( { 35 | filename: './dist/blocks.editor.build.css', 36 | } ); 37 | 38 | // Configuration for the ExtractTextPlugin — DRY rule. 39 | const extractConfig = { 40 | use: [ 41 | // "postcss" loader applies autoprefixer to our CSS. 42 | { loader: 'raw-loader' }, 43 | { 44 | loader: 'postcss-loader', 45 | options: { 46 | ident: 'postcss', 47 | plugins: [ 48 | autoprefixer( { 49 | browsers: [ 50 | '>1%', 51 | 'last 4 versions', 52 | 'Firefox ESR', 53 | 'not ie < 9', // React doesn't support IE8 anyway 54 | ], 55 | flexbox: 'no-2009', 56 | } ), 57 | ], 58 | }, 59 | }, 60 | // "sass" loader converts SCSS to CSS. 61 | { 62 | loader: 'sass-loader', 63 | options: { 64 | // Add common CSS file for variables and mixins. 65 | data: '@import "./src/common.scss";\n', 66 | outputStyle: 'nested', 67 | }, 68 | }, 69 | ], 70 | }; 71 | 72 | // Export configuration. 73 | module.exports = { 74 | entry: { 75 | './dist/blocks.build': paths.pluginBlocksJs, // 'name' : 'path/file.ext'. 76 | }, 77 | output: { 78 | // Add /* filename */ comments to generated require()s in the output. 79 | pathinfo: true, 80 | // The dist folder. 81 | path: paths.pluginDist, 82 | filename: '[name].js', // [name] = './dist/blocks.build' as defined above. 83 | }, 84 | // You may want 'eval' instead if you prefer to see the compiled output in DevTools. 85 | devtool: 'cheap-eval-source-map', 86 | module: { 87 | rules: [ 88 | { 89 | test: /\.(js|jsx|mjs)$/, 90 | exclude: /(node_modules|bower_components)/, 91 | use: { 92 | loader: 'babel-loader', 93 | options: { 94 | // @remove-on-eject-begin 95 | babelrc: false, 96 | presets: [ require.resolve( 'babel-preset-cgb' ) ], 97 | // @remove-on-eject-end 98 | // This is a feature of `babel-loader` for webpack (not Babel itself). 99 | // It enables caching results in ./node_modules/.cache/babel-loader/ 100 | // directory for faster rebuilds. 101 | cacheDirectory: true, 102 | }, 103 | }, 104 | }, 105 | { 106 | test: /style\.s?css$/, 107 | exclude: /(node_modules|bower_components)/, 108 | use: blocksCSSPlugin.extract( extractConfig ), 109 | }, 110 | { 111 | test: /editor\.s?css$/, 112 | exclude: /(node_modules|bower_components)/, 113 | use: editBlocksCSSPlugin.extract( extractConfig ), 114 | }, 115 | ], 116 | }, 117 | // Add plugins. 118 | plugins: [ blocksCSSPlugin, editBlocksCSSPlugin ], 119 | stats: 'minimal', 120 | // stats: 'errors-only', 121 | // Add externals. 122 | externals: externals, 123 | }; 124 | -------------------------------------------------------------------------------- /packages/cgb-scripts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cgb-scripts", 3 | "version": "1.23.0", 4 | "description": "Configuration and scripts for Create Guten Blocks which help you create a WordPress Gutenberg Block plugin with Zero-Config #OCJS, Webpack, React, ES6/7/8/Next, ESLint, Babel, and more", 5 | "repository": "ahmadawais/create-guten-block", 6 | "keywords": [ 7 | "gutenberg", 8 | "create-gutenberg-block", 9 | "create-gutenberg-blocks", 10 | "wp", 11 | "wordpress", 12 | "cgb", 13 | "wp webpack", 14 | "react", 15 | "ESLint", 16 | "Webpack", 17 | "wp-scripts", 18 | "cgb-scripts", 19 | "guten-scripts", 20 | "babel", 21 | "cgb-dev-utils", 22 | "babel-preset-cgb" 23 | ], 24 | "author": "Ahmad Awais (https://AhmadAwais.com/)", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/ahmadawais/create-guten-block/issues" 28 | }, 29 | "bin": { 30 | "cgb-scripts": "./bin/cgb-scripts.js" 31 | }, 32 | "dependencies": { 33 | "@scarf/scarf": "^1.0.6", 34 | "autoprefixer": "^7.2.4", 35 | "babel-core": "^6.25.0", 36 | "babel-eslint": "^8.2.1", 37 | "babel-loader": "^7.1.1", 38 | "babel-preset-cgb": "^1.7.0", 39 | "cgb-dev-utils": "^1.6.0", 40 | "chalk": "^2.3.0", 41 | "cross-env": "^5.0.1", 42 | "cross-spawn": "^5.1.0", 43 | "eslint": "^4.15.0", 44 | "eslint-config-wordpress": "^2.0.0", 45 | "eslint-plugin-jest": "^21.6.1", 46 | "eslint-plugin-jsx-a11y": "^6.0.3", 47 | "eslint-plugin-react": "^7.5.1", 48 | "eslint-plugin-wordpress": "^0.1.0", 49 | "extract-text-webpack-plugin": "^3.0.2", 50 | "filesize": "^3.5.11", 51 | "fs-extra": "^5.0.0", 52 | "gzip-size": "^4.1.0", 53 | "inquirer": "^5.0.0", 54 | "node-sass": "^4.7.2", 55 | "ora": "^1.3.0", 56 | "postcss-loader": "^2.0.10", 57 | "raw-loader": "^0.5.1", 58 | "resolve-pkg": "^1.0.0", 59 | "sass-loader": "^6.0.6", 60 | "shelljs": "^0.8.0", 61 | "style-loader": "^0.23.1", 62 | "update-notifier": "^2.3.0", 63 | "webpack": "^3.1.0" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /packages/cgb-scripts/scripts/block.js: -------------------------------------------------------------------------------- 1 | /** 2 | * New Block plugin intializer 3 | * 4 | * TODO 5 | * - Work in progress 6 | * - First pass 7 | * 8 | * - Copies the templates. 9 | * - Prints final instructions. 10 | */ 11 | // @remove-file-on-eject 12 | 13 | 'use strict'; 14 | 15 | const ora = require( 'ora' ); 16 | const path = require( 'path' ); 17 | const fs = require( 'fs-extra' ); 18 | const chalk = require( 'chalk' ); 19 | const shell = require( 'shelljs' ); 20 | 21 | // Makes the script crash on unhandled rejections instead of silently 22 | // ignoring them. In the future, promise rejections that are not handled will 23 | // terminate the Node.js process with a non-zero exit code. 24 | process.on( 'unhandledRejection', err => { 25 | throw err; 26 | } ); 27 | 28 | /** 29 | * Copy template to the plugin dir. 30 | * 31 | * @param {string} blockName The block name. 32 | * @param {string} blockDir The block directory. 33 | * @param {string} blockNamePHPLower The block name for PHP files in lowercase. 34 | * @param {string} blockNamePHPUpper The block name for PHP files in uppercase. 35 | */ 36 | const copyTemplateFiles = ( 37 | blockName, 38 | blockDir, 39 | blockNamePHPLower, 40 | blockNamePHPUpper 41 | ) => { 42 | // Since we ran npm install cgb-scripts we have it in the node_modules now. 43 | const template = path.join( 44 | blockDir, 45 | 'node_modules', 46 | 'cgb-scripts', 47 | 'template' 48 | ); 49 | 50 | const templatePromise = new Promise( resolve => { 51 | shell.cd( blockDir ); 52 | 53 | // Copy the files into the plugin blockDir. 54 | if ( fs.existsSync( template ) ) { 55 | fs.copySync( template, blockDir ); 56 | } else { 57 | console.error( 58 | `Could not locate supplied template: ${ chalk.green( template ) }` 59 | ); 60 | return; 61 | } 62 | 63 | // Build a list of files we added. 64 | const files = [ ...shell.ls( blockDir + '/src/block/**.*' ) ]; 65 | 66 | // Replace dynamic content for block name in the code. 67 | files.forEach( function( file ) { 68 | shell.sed( '-i', '<% blockName %>', `${ blockName }`, file ); 69 | shell.sed( '-i', '<% blockName % >', `${ blockName }`, file ); 70 | shell.sed( '-i', '<% blockNamePHPLower %>', `${ blockNamePHPLower }`, file ); 71 | shell.sed( '-i', '<% blockNamePHPLower % >', `${ blockNamePHPLower }`, file ); 72 | shell.sed( '-i', '<% blockNamePHPUpper %>', `${ blockNamePHPUpper }`, file ); 73 | shell.sed( '-i', '<% blockNamePHPUpper % >', `${ blockNamePHPUpper }`, file ); 74 | } ); 75 | 76 | resolve( true ); 77 | } ); 78 | 79 | templatePromise.catch( err => { 80 | console.log( 'ERROR on templatePromise →', err ); 81 | process.exit( 1 ); 82 | } ); 83 | }; 84 | 85 | /** 86 | * Prints next steps. 87 | * 88 | * @param {string} blockName The block name. 89 | * @param {string} blockDir The block directory. 90 | */ 91 | const printNextSteps = blockName => { 92 | console.log( 93 | '\n\n✅ ', 94 | chalk.black.bgGreen( ` Created a new block at .src/${ blockName }. ` ), 95 | '\n\n' 96 | ); 97 | }; 98 | 99 | /** 100 | * Initializer function. 101 | * 102 | * - Copy templates to the appPath 103 | * - Print final instructions. 104 | * 105 | * @param {string} root The process.cwd() of where the cgb ran. 106 | * @param {string} blockName The block name. 107 | * @param {string} blockDir The block directory. 108 | */ 109 | // Define blockName 110 | // Define blockDir 111 | module.exports = async( root, blockName, blockDir ) => { 112 | // 0. Create block name for PHP functions. 113 | const blockNamePHPLower = blockName 114 | .toLowerCase() 115 | .split( '-' ) 116 | .join( '_' ); 117 | 118 | // 0. Create block name for PHP functions. 119 | const blockNamePHPUpper = blockNamePHPLower.toUpperCase(); 120 | 121 | // 1.Copy template to the plugin dir. 122 | // Init the spinner. 123 | const spinner = new ora( { text: '' } ); 124 | spinner.start( 'Creating a new block in ./src/...' ); 125 | await copyTemplateFiles( 126 | blockName, 127 | blockDir, 128 | blockNamePHPLower, 129 | blockNamePHPUpper 130 | ); 131 | spinner.succeed(); 132 | 133 | // 2. Prints next steps. 134 | await printNextSteps( blockName ); 135 | }; 136 | -------------------------------------------------------------------------------- /packages/cgb-scripts/scripts/build.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Build 3 | * 4 | * The create-guten-block CLI builds here. 5 | */ 6 | 7 | 'use strict'; 8 | 9 | // Do this as the first thing so that any code reading it knows the right env. 10 | process.env.BABEL_ENV = 'production'; 11 | process.env.NODE_ENV = 'production'; 12 | 13 | // Makes the script crash on unhandled rejections instead of silently 14 | // ignoring them. In the future, promise rejections that are not handled will 15 | // terminate the Node.js process with a non-zero exit code. 16 | process.on( 'unhandledRejection', err => { 17 | throw err; 18 | } ); 19 | 20 | // Modules. 21 | const fs = require( 'fs' ); 22 | const ora = require( 'ora' ); 23 | const path = require( 'path' ); 24 | const chalk = require( 'chalk' ); 25 | const webpack = require( 'webpack' ); 26 | const fileSize = require( 'filesize' ); 27 | const gzipSize = require( 'gzip-size' ); 28 | const resolvePkg = require( 'resolve-pkg' ); 29 | const config = require( '../config/webpack.config.prod' ); 30 | const cgbDevUtilsPath = resolvePkg( 'cgb-dev-utils', { cwd: __dirname } ); 31 | const clearConsole = require( cgbDevUtilsPath + '/clearConsole' ); 32 | const formatWebpackMessages = require( cgbDevUtilsPath + '/formatWebpackMessages' ); 33 | 34 | // Build file paths. 35 | const theCWD = process.cwd(); 36 | const fileBuildJS = path.resolve( theCWD, './dist/blocks.build.js' ); 37 | const fileEditorCSS = path.resolve( theCWD, './dist/blocks.editor.build.css' ); 38 | const fileStyleCSS = path.resolve( theCWD, './dist/blocks.style.build.css' ); 39 | 40 | /** 41 | * Get File Size 42 | * 43 | * Get filesizes of all the files. 44 | * 45 | * @param {string} filePath path. 46 | * @returns {string} then size result. 47 | */ 48 | const getFileSize = filePath => { 49 | return fileSize( gzipSize.sync( fs.readFileSync( filePath ) ) ); 50 | }; 51 | 52 | clearConsole(); 53 | 54 | // Init the spinner. 55 | const spinner = new ora( { text: '' } ); 56 | 57 | /** 58 | * Build function 59 | * 60 | * Create the production build and print the deployment instructions. 61 | * 62 | * @param {json} webpackConfig config 63 | */ 64 | async function build( webpackConfig ) { 65 | // Compiler Instance. 66 | const compiler = await webpack( webpackConfig ); 67 | 68 | // Run the compiler. 69 | compiler.run( ( err, stats ) => { 70 | clearConsole(); 71 | 72 | if ( err ) { 73 | return console.log( err ); 74 | } 75 | 76 | // Get the messages formatted. 77 | const messages = formatWebpackMessages( stats.toJson( {}, true ) ); 78 | 79 | // If there are errors just show the errors. 80 | if ( messages.errors.length ) { 81 | // Only keep the first error. Others are often indicative 82 | // of the same problem, but confuse the reader with noise. 83 | if ( messages.errors.length > 1 ) { 84 | messages.errors.length = 1; 85 | } 86 | // Formatted errors. 87 | clearConsole(); 88 | console.log( '\n❌ ', chalk.black.bgRed( ' Failed to compile build. \n' ) ); 89 | console.log( '\n👉 ', messages.errors.join( '\n\n' ) ); 90 | 91 | // Don't go beyond this point at this time. 92 | return; 93 | } 94 | 95 | // CI. 96 | if ( 97 | process.env.CI && 98 | ( typeof process.env.CI !== 'string' || process.env.CI.toLowerCase() !== 'false' ) && 99 | messages.warnings.length 100 | ) { 101 | console.log( 102 | chalk.yellow( 103 | '\nTreating warnings as errors because process.env.CI = true.\n' + 104 | 'Most CI servers set it automatically.\n' 105 | ) 106 | ); 107 | console.log( messages.warnings.join( '\n\n' ) ); 108 | } 109 | 110 | // Start the build. 111 | console.log( `\n ${ chalk.dim( 'Let\'s build and compile the files...' ) }` ); 112 | console.log( '\n✅ ', chalk.black.bgGreen( ' Built successfully! \n' ) ); 113 | 114 | console.log( 115 | '\n\n', 116 | 'File sizes after gzip:', 117 | '\n\n', 118 | getFileSize( fileBuildJS ), 119 | `${ chalk.dim( '— ./dist/' ) }`, 120 | `${ chalk.green( 'blocks.build.js' ) }`, 121 | '\n', 122 | getFileSize( fileEditorCSS ), 123 | `${ chalk.dim( '— ./dist/' ) }`, 124 | `${ chalk.green( 'blocks.editor.build.css' ) }`, 125 | 126 | '\n', 127 | getFileSize( fileStyleCSS ), 128 | `${ chalk.dim( '— ./dist/' ) }`, 129 | `${ chalk.green( 'blocks.style.build.css' ) }`, 130 | '\n\n' 131 | ); 132 | 133 | console.log( '\n👌 ', chalk.dim( ' Support Awais via VSCode Power User at https://VSCode.pro → \n' ) ); 134 | 135 | return true; 136 | } ); 137 | } 138 | 139 | build( config ); 140 | -------------------------------------------------------------------------------- /packages/cgb-scripts/scripts/start.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Start 3 | * 4 | * The create-guten-block CLI starts here. 5 | * 6 | * TODO: 7 | * - checkRequiredFiles 8 | * - printBuildError 9 | */ 10 | 'use strict'; 11 | 12 | // Do this as the first thing so that any code reading it knows the right env. 13 | process.env.BABEL_ENV = 'development'; 14 | process.env.NODE_ENV = 'development'; 15 | 16 | // Makes the script crash on unhandled rejections instead of silently 17 | // ignoring them. In the future, promise rejections that are not handled will 18 | // terminate the Node.js process with a non-zero exit code. 19 | process.on( 'unhandledRejection', err => { 20 | throw err; 21 | } ); 22 | 23 | const ora = require( 'ora' ); 24 | const chalk = require( 'chalk' ); 25 | const webpack = require( 'webpack' ); 26 | const config = require( '../config/webpack.config.dev' ); 27 | const resolvePkg = require( 'resolve-pkg' ); 28 | const cgbDevUtilsPath = resolvePkg( 'cgb-dev-utils', { cwd: __dirname } ); 29 | const clearConsole = require( cgbDevUtilsPath + '/clearConsole' ); 30 | const formatWebpackMessages = require( cgbDevUtilsPath + '/formatWebpackMessages' ); 31 | 32 | // Don't run below node 8. 33 | const currentNodeVersion = process.versions.node; 34 | const semver = currentNodeVersion.split( '.' ); 35 | const major = semver[ 0 ]; 36 | 37 | // If below Node 8. 38 | if ( major < 8 ) { 39 | console.error( 40 | chalk.red( 41 | 'You are running Node ' + 42 | currentNodeVersion + 43 | '.\n' + 44 | 'Create Guten Block requires Node 8 or higher. \n' + 45 | 'Kindly, update your version of Node.' 46 | ) 47 | ); 48 | process.exit( 1 ); 49 | } 50 | 51 | clearConsole(); 52 | 53 | // Init the spinner. 54 | const spinner = new ora( { text: '' } ); 55 | 56 | // Create the production build and print the deployment instructions. 57 | async function build( webpackConfig ) { 58 | // Compiler Instance. 59 | const compiler = await webpack( webpackConfig ); 60 | 61 | // Run the compiler. 62 | compiler.watch( {}, ( err, stats ) => { 63 | clearConsole(); 64 | 65 | if ( err ) { 66 | return console.log( err ); 67 | } 68 | 69 | // Get the messages formatted. 70 | const messages = formatWebpackMessages( stats.toJson( {}, true ) ); 71 | 72 | // If there are errors just show the errors. 73 | if ( messages.errors.length ) { 74 | // Only keep the first error. Others are often indicative 75 | // of the same problem, but confuse the reader with noise. 76 | if ( messages.errors.length > 1 ) { 77 | messages.errors.length = 1; 78 | } 79 | 80 | // Clear success messages. 81 | clearConsole(); 82 | 83 | // Formatted errors. 84 | console.log( '\n❌ ', chalk.black.bgRed( ' Failed to compile. \n' ) ); 85 | const logErrors = console.log( '\n👉 ', messages.errors.join( '\n\n' ) ); 86 | console.log( '\n' ); 87 | spinner.start( chalk.dim( 'Watching for changes... let\'s fix this... (Press CTRL + C to stop).' ) ); 88 | return logErrors; 89 | } 90 | 91 | // CI. 92 | if ( 93 | process.env.CI && 94 | ( typeof process.env.CI !== 'string' || process.env.CI.toLowerCase() !== 'false' ) && 95 | messages.warnings.length 96 | ) { 97 | console.log( 98 | chalk.yellow( 99 | '\nTreating warnings as errors because process.env.CI = true.\n' + 100 | 'Most CI servers set it automatically.\n' 101 | ) 102 | ); 103 | return console.log( messages.warnings.join( '\n\n' ) ); 104 | } 105 | 106 | // Start the build. 107 | console.log( `\n${ chalk.dim( 'Let\'s build and compile the files...' ) }` ); 108 | console.log( '\n✅ ', chalk.black.bgGreen( ' Compiled successfully! \n' ) ); 109 | console.log( 110 | chalk.dim( ' Note that the development build is not optimized. \n' ), 111 | chalk.dim( ' To create a production build, use' ), 112 | chalk.green( 'npm' ), 113 | chalk.white( 'run build\n\n' ), 114 | chalk.dim( '👌 Support Awais via VSCode Power User at https://VSCode.pro →\n\n' ) 115 | ); 116 | return spinner.start( `${ chalk.dim( 'Watching for changes... (Press CTRL + C to stop).' ) }` ); 117 | } ); 118 | } 119 | 120 | build( config ); 121 | -------------------------------------------------------------------------------- /packages/cgb-scripts/scripts/test.js: -------------------------------------------------------------------------------- 1 | // @remove-file-on-eject 2 | 3 | const chalk = require( 'chalk' ); 4 | 5 | console.clear(); 6 | console.log( '\n👌 ', chalk.dim( ' Support Awais via VSCode Power User at' ), 'https://VSCode.pro' ); 7 | -------------------------------------------------------------------------------- /packages/cgb-scripts/template/.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs 2 | # editorconfig.org 3 | 4 | # WordPress Coding Standards 5 | # https://make.wordpress.org/core/handbook/coding-standards/ 6 | 7 | root = true 8 | 9 | [*] 10 | charset = utf-8 11 | end_of_line = lf 12 | insert_final_newline = true 13 | trim_trailing_whitespace = true 14 | indent_style = tab 15 | 16 | [*.yml] 17 | indent_style = space 18 | indent_size = 2 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | -------------------------------------------------------------------------------- /packages/cgb-scripts/template/.eslintignore: -------------------------------------------------------------------------------- 1 | **/*.min.js 2 | **/*.build.js 3 | **/node_modules/** 4 | **/vendor/** 5 | build 6 | coverage 7 | cypress 8 | node_modules 9 | vendor 10 | -------------------------------------------------------------------------------- /packages/cgb-scripts/template/.gitignore: -------------------------------------------------------------------------------- 1 | # Packages # 2 | ############ 3 | *.7z 4 | *.dmg 5 | *.gz 6 | *.bz2 7 | *.iso 8 | *.jar 9 | *.rar 10 | *.tar 11 | *.zip 12 | *.tgz 13 | *.map 14 | 15 | # Logs and databases # 16 | ###################### 17 | *.log 18 | *.sql 19 | 20 | # OS generated files # 21 | ###################### 22 | **.DS_Store* 23 | ehthumbs.db 24 | Icon? 25 | Thumbs.db 26 | ._* 27 | 28 | # Vim generated files # 29 | ###################### 30 | *.un~ 31 | 32 | # SASS # 33 | ########## 34 | **/.sass-cache 35 | **/.sass-cache/* 36 | **/.map 37 | 38 | # Composer # 39 | ########## 40 | vendors/composer/ 41 | !assets/js/vendor/ 42 | wpcs/ 43 | composer.lock 44 | 45 | # Bower # 46 | ########## 47 | assets/bower_components/* 48 | 49 | # Codekit # 50 | ########## 51 | /codekit-config.json 52 | *.codekit 53 | **.codekit-cache/* 54 | 55 | # NPM # 56 | ########## 57 | node_modules 58 | 59 | # Compiled Files and Build Dirs # 60 | ########## 61 | /README.html 62 | /build/ 63 | 64 | # PhpStrom Project Files # 65 | .idea/ 66 | library/vendors/composer 67 | assets/img/.DS_Store 68 | assets/sass/HTML 69 | assets/sass/Rails 70 | HTML 71 | Rails 72 | -------------------------------------------------------------------------------- /packages/cgb-scripts/template/dist/blocks.editor.build.css: -------------------------------------------------------------------------------- 1 | .wp-block-cgb-block-cgb{color:#292929;background:#bada55;border:0.2rem solid #292929;padding:2rem} 2 | -------------------------------------------------------------------------------- /packages/cgb-scripts/template/dist/blocks.style.build.css: -------------------------------------------------------------------------------- 1 | .wp-block-cgb-block-cgb{color:#292929;background:#ff4500;border:0.2rem solid #292929;padding:2rem} 2 | -------------------------------------------------------------------------------- /packages/cgb-scripts/template/plugin.php: -------------------------------------------------------------------------------- 1 | — CGB Gutenberg Block Plugin 4 | * Plugin URI: https://github.com/ahmadawais/create-guten-block/ 5 | * Description: <% blockName %> — is a Gutenberg plugin created via create-guten-block. 6 | * Author: mrahmadawais, maedahbatool 7 | * Author URI: https://AhmadAwais.com/ 8 | * Version: 1.0.0 9 | * License: GPL2+ 10 | * License URI: https://www.gnu.org/licenses/gpl-2.0.txt 11 | * 12 | * @package CGB 13 | */ 14 | 15 | // Exit if accessed directly. 16 | if ( ! defined( 'ABSPATH' ) ) { 17 | exit; 18 | } 19 | 20 | /** 21 | * Block Initializer. 22 | */ 23 | require_once plugin_dir_path( __FILE__ ) . 'src/init.php'; 24 | -------------------------------------------------------------------------------- /packages/cgb-scripts/template/readme.md: -------------------------------------------------------------------------------- 1 | This project was bootstrapped with [Create Guten Block](https://github.com/ahmadawais/create-guten-block). 2 | 3 | Below you will find some information on how to run scripts. 4 | 5 | >You can find the most recent version of this guide [here](https://github.com/ahmadawais/create-guten-block). 6 | 7 | ## 👉 `npm start` 8 | - Use to compile and run the block in development mode. 9 | - Watches for any changes and reports back any errors in your code. 10 | 11 | ## 👉 `npm run build` 12 | - Use to build production code for your block inside `dist` folder. 13 | - Runs once and reports back the gzip file sizes of the produced code. 14 | 15 | ## 👉 `npm run eject` 16 | - Use to eject your plugin out of `create-guten-block`. 17 | - Provides all the configurations so you can customize the project as you want. 18 | - It's a one-way street, `eject` and you have to maintain everything yourself. 19 | - You don't normally have to `eject` a project because by ejecting you lose the connection with `create-guten-block` and from there onwards you have to update and maintain all the dependencies on your own. 20 | 21 | --- 22 | 23 | ###### Feel free to tweet and say 👋 at me [@MrAhmadAwais](https://twitter.com/mrahmadawais/) 24 | 25 | [![npm](https://img.shields.io/npm/v/create-guten-block.svg?style=flat-square)](https://www.npmjs.com/package/create-guten-block) [![npm](https://img.shields.io/npm/dt/create-guten-block.svg?style=flat-square&label=downloads)](https://www.npmjs.com/package/create-guten-block) [![license](https://img.shields.io/github/license/mashape/apistatus.svg?style=flat-square)](https://github.com/ahmadawais/create-guten-block) [![Tweet for help](https://img.shields.io/twitter/follow/mrahmadawais.svg?style=social&label=Tweet%20@MrAhmadAwais)](https://twitter.com/mrahmadawais/) [![GitHub stars](https://img.shields.io/github/stars/ahmadawais/create-guten-block.svg?style=social&label=Stars)](https://github.com/ahmadawais/create-guten-block/stargazers) [![GitHub followers](https://img.shields.io/github/followers/ahmadawais.svg?style=social&label=Follow)](https://github.com/ahmadawais?tab=followers) -------------------------------------------------------------------------------- /packages/cgb-scripts/template/src/block/block.js: -------------------------------------------------------------------------------- 1 | /** 2 | * BLOCK: <% blockName %> 3 | * 4 | * Registering a basic block with Gutenberg. 5 | * Simple block, renders and saves the same content without any interactivity. 6 | */ 7 | 8 | // Import CSS. 9 | import './editor.scss'; 10 | import './style.scss'; 11 | 12 | const { __ } = wp.i18n; // Import __() from wp.i18n 13 | const { registerBlockType } = wp.blocks; // Import registerBlockType() from wp.blocks 14 | 15 | /** 16 | * Register: aa Gutenberg Block. 17 | * 18 | * Registers a new block provided a unique name and an object defining its 19 | * behavior. Once registered, the block is made editor as an option to any 20 | * editor interface where blocks are implemented. 21 | * 22 | * @link https://wordpress.org/gutenberg/handbook/block-api/ 23 | * @param {string} name Block name. 24 | * @param {Object} settings Block settings. 25 | * @return {?WPBlock} The block, if it has been successfully 26 | * registered; otherwise `undefined`. 27 | */ 28 | registerBlockType( 'cgb/block-<% blockName %>', { 29 | // Block name. Block names must be string that contains a namespace prefix. Example: my-plugin/my-custom-block. 30 | title: __( '<% blockName %> - CGB Block' ), // Block title. 31 | icon: 'shield', // Block icon from Dashicons → https://developer.wordpress.org/resource/dashicons/. 32 | category: 'common', // Block category — Group blocks together based on common traits E.g. common, formatting, layout widgets, embed. 33 | keywords: [ 34 | __( '<% blockName %> — CGB Block' ), 35 | __( 'CGB Example' ), 36 | __( 'create-guten-block' ), 37 | ], 38 | 39 | /** 40 | * The edit function describes the structure of your block in the context of the editor. 41 | * This represents what the editor will render when the block is used. 42 | * 43 | * The "edit" property must be a valid function. 44 | * 45 | * @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/ 46 | * 47 | * @param {Object} props Props. 48 | * @returns {Mixed} JSX Component. 49 | */ 50 | edit: ( props ) => { 51 | // Creates a

. 52 | return ( 53 |
54 |

— Hello from the backend.

55 |

56 | CGB BLOCK: <% blockName %> is a new Gutenberg block 57 |

58 |

59 | It was created via{ ' ' } 60 | 61 | 62 | create-guten-block 63 | 64 | . 65 |

66 |
67 | ); 68 | }, 69 | 70 | /** 71 | * The save function defines the way in which the different attributes should be combined 72 | * into the final markup, which is then serialized by Gutenberg into post_content. 73 | * 74 | * The "save" property must be specified and must be a valid function. 75 | * 76 | * @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/ 77 | * 78 | * @param {Object} props Props. 79 | * @returns {Mixed} JSX Frontend HTML. 80 | */ 81 | save: ( props ) => { 82 | return ( 83 |
84 |

— Hello from the frontend.

85 |

86 | CGB BLOCK: <% blockName %> is a new Gutenberg block. 87 |

88 |

89 | It was created via{ ' ' } 90 | 91 | 92 | create-guten-block 93 | 94 | . 95 |

96 |
97 | ); 98 | }, 99 | } ); 100 | -------------------------------------------------------------------------------- /packages/cgb-scripts/template/src/block/editor.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Editor Styles 3 | * 4 | * CSS for just Backend enqueued after style.scss 5 | * which makes it higher in priority. 6 | */ 7 | 8 | .wp-block-cgb-block-<% blockName % > { 9 | background: $green; 10 | border: 0.2rem solid $black; 11 | color: $black; 12 | margin: 0 auto; 13 | max-width: 740px; 14 | padding: 2rem; 15 | } 16 | -------------------------------------------------------------------------------- /packages/cgb-scripts/template/src/block/style.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Styles 3 | * 4 | * CSS for both Frontend+Backend. 5 | */ 6 | 7 | .wp-block-cgb-block-<% blockName % > { 8 | background: $red; 9 | border: 0.2rem solid $black; 10 | color: $black; 11 | margin: 0 auto; 12 | max-width: 740px; 13 | padding: 2rem; 14 | } 15 | -------------------------------------------------------------------------------- /packages/cgb-scripts/template/src/blocks.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Gutenberg Blocks 3 | * 4 | * All blocks related JavaScript files should be imported here. 5 | * You can create a new block folder in this dir and include code 6 | * for that block here as well. 7 | * 8 | * All blocks should be included here since this is the file that 9 | * Webpack is compiling as the input file. 10 | */ 11 | 12 | import './block/block.js'; 13 | -------------------------------------------------------------------------------- /packages/cgb-scripts/template/src/common.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Common SCSS 3 | * 4 | * Can include things like variables and mixins 5 | * that are used across the project. 6 | */ 7 | 8 | // Colors. 9 | $black: rgb(41, 41, 41); 10 | $white: #f4f4f4; 11 | $gray: #dedede; 12 | $green: #bada55; 13 | $red: orangered; 14 | -------------------------------------------------------------------------------- /packages/cgb-scripts/template/src/init.php: -------------------------------------------------------------------------------- 1 | _cgb_block_assets() { // phpcs:ignore 31 | // Register block styles for both frontend + backend. 32 | wp_register_style( 33 | '<% blockNamePHPLower %>-cgb-style-css', // Handle. 34 | plugins_url( 'dist/blocks.style.build.css', dirname( __FILE__ ) ), // Block style CSS. 35 | is_admin() ? array( 'wp-editor' ) : null, // Dependency to include the CSS after it. 36 | null // filemtime( plugin_dir_path( __DIR__ ) . 'dist/blocks.style.build.css' ) // Version: File modification time. 37 | ); 38 | 39 | // Register block editor script for backend. 40 | wp_register_script( 41 | '<% blockNamePHPLower %>-cgb-block-js', // Handle. 42 | plugins_url( '/dist/blocks.build.js', dirname( __FILE__ ) ), // Block.build.js: We register the block here. Built with Webpack. 43 | array( 'wp-blocks', 'wp-i18n', 'wp-element', 'wp-editor' ), // Dependencies, defined above. 44 | null, // filemtime( plugin_dir_path( __DIR__ ) . 'dist/blocks.build.js' ), // Version: filemtime — Gets file modification time. 45 | true // Enqueue the script in the footer. 46 | ); 47 | 48 | // Register block editor styles for backend. 49 | wp_register_style( 50 | '<% blockNamePHPLower %>-cgb-block-editor-css', // Handle. 51 | plugins_url( 'dist/blocks.editor.build.css', dirname( __FILE__ ) ), // Block editor CSS. 52 | array( 'wp-edit-blocks' ), // Dependency to include the CSS after it. 53 | null // filemtime( plugin_dir_path( __DIR__ ) . 'dist/blocks.editor.build.css' ) // Version: File modification time. 54 | ); 55 | 56 | // WP Localized globals. Use dynamic PHP stuff in JavaScript via `cgbGlobal` object. 57 | wp_localize_script( 58 | '<% blockNamePHPLower %>-cgb-block-js', 59 | 'cgbGlobal', // Array containing dynamic data for a JS Global. 60 | [ 61 | 'pluginDirPath' => plugin_dir_path( __DIR__ ), 62 | 'pluginDirUrl' => plugin_dir_url( __DIR__ ), 63 | // Add more data here that you want to access from `cgbGlobal` object. 64 | ] 65 | ); 66 | 67 | /** 68 | * Register Gutenberg block on server-side. 69 | * 70 | * Register the block on server-side to ensure that the block 71 | * scripts and styles for both frontend and backend are 72 | * enqueued when the editor loads. 73 | * 74 | * @link https://wordpress.org/gutenberg/handbook/blocks/writing-your-first-block-type#enqueuing-block-scripts 75 | * @since 1.16.0 76 | */ 77 | register_block_type( 78 | 'cgb/block-<% blockName %>', array( 79 | // Enqueue blocks.style.build.css on both frontend & backend. 80 | 'style' => '<% blockNamePHPLower %>-cgb-style-css', 81 | // Enqueue blocks.build.js in the editor only. 82 | 'editor_script' => '<% blockNamePHPLower %>-cgb-block-js', 83 | // Enqueue blocks.editor.build.css in the editor only. 84 | 'editor_style' => '<% blockNamePHPLower %>-cgb-block-editor-css', 85 | ) 86 | ); 87 | } 88 | 89 | // Hook: Block assets. 90 | add_action( 'init', '<% blockNamePHPLower %>_cgb_block_assets' ); 91 | -------------------------------------------------------------------------------- /packages/create-guten-block/.eslintignore: -------------------------------------------------------------------------------- 1 | **/node_modules/** 2 | **/vendor/** 3 | **/block.build.js 4 | **/*.min.js -------------------------------------------------------------------------------- /packages/create-guten-block/.gitignore: -------------------------------------------------------------------------------- 1 | # Packages # 2 | ############ 3 | *.7z 4 | *.dmg 5 | *.gz 6 | *.bz2 7 | *.iso 8 | *.jar 9 | *.rar 10 | *.tar 11 | *.zip 12 | *.tgz 13 | *.map 14 | 15 | # Logs and databases # 16 | ###################### 17 | *.log 18 | *.sql 19 | 20 | # OS generated files # 21 | ###################### 22 | **.DS_Store* 23 | ehthumbs.db 24 | Icon? 25 | Thumbs.db 26 | ._* 27 | 28 | # Vim generated files # 29 | ###################### 30 | *.un~ 31 | 32 | # SASS # 33 | ########## 34 | **/.sass-cache 35 | **/.sass-cache/* 36 | **/.map 37 | 38 | # Composer # 39 | ########## 40 | vendors/composer/ 41 | !assets/js/vendor/ 42 | wpcs/ 43 | composer.lock 44 | 45 | # Bower # 46 | ########## 47 | assets/bower_components/* 48 | 49 | # Codekit # 50 | ########## 51 | /codekit-config.json 52 | *.codekit 53 | **.codekit-cache/* 54 | 55 | # NPM # 56 | ########## 57 | node_modules 58 | **/node_modules/** 59 | 60 | # Compiled Files and Build Dirs # 61 | ########## 62 | /README.html 63 | 64 | # PhpStrom Project Files # 65 | .idea/ 66 | library/vendors/composer 67 | assets/img/.DS_Store 68 | assets/sass/HTML 69 | assets/sass/Rails 70 | HTML 71 | Rails 72 | 73 | # CGB 74 | .idea/ 75 | .vscode/ 76 | .DS_Store 77 | *.tgz 78 | my-app* 79 | template/src/__tests__/__snapshots__/ 80 | lerna-debug.log 81 | npm-debug.log* 82 | yarn-debug.log* 83 | yarn-error.log* 84 | /.changelog -------------------------------------------------------------------------------- /packages/create-guten-block/.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /packages/create-guten-block/README.md: -------------------------------------------------------------------------------- 1 | CGB Create Guten Block by Ahmad Awais 2 | 3 |
4 | 5 | Create Guten Block 6 | 7 |
8 | 9 | [![npm](https://img.shields.io/npm/v/create-guten-block.svg?style=flat-square)](https://www.npmjs.com/package/create-guten-block) [![npm](https://img.shields.io/npm/dt/create-guten-block.svg?style=flat-square&label=downloads)](https://www.npmjs.com/package/create-guten-block) [![license](https://img.shields.io/github/license/mashape/apistatus.svg?style=flat-square)](https://github.com/ahmadawais/create-guten-block) [![Tweet for help](https://img.shields.io/twitter/follow/mrahmadawais.svg?style=social&label=Tweet%20@MrAhmadAwais)](https://twitter.com/mrahmadawais/) [![GitHub stars](https://img.shields.io/github/stars/ahmadawais/create-guten-block.svg?style=social&label=Stars)](https://github.com/ahmadawais/create-guten-block/stargazers) [![GitHub followers](https://img.shields.io/github/followers/ahmadawais.svg?style=social&label=Follow)](https://github.com/ahmadawais?tab=followers) 10 | 11 | 12 | 13 | 17 | 18 | 19 | 22 | 27 | 28 | 29 |
14 | create-guten-block
15 | A zero-configuration developer toolkit for building WordPress Gutenberg block plugins. 16 |
20 | A FOSS (Free & Open Source Software) project developed by Ahmad Awais. 21 | 23 | 24 | 25 | 26 |
Follow Ahmad's #FOSS work on GitHub @AhmadAwais — Say Hi on Twitter @MrAhmadAwais👋
30 |
31 | 32 | # 📦 `create-guten-block` 33 | 34 | >`create-guten-block` is _zero configuration dev-toolkit_ (#0CJS) to develop WordPress Gutenberg blocks in a matter of minutes without configuring `React`, `Webpack`, `ES6/7/8/Next`, `ESLint`, `Babel`, etc. 35 | 36 | 👉 This package includes the global command for [Create Guten Block](https://github.com/ahmadawais/create-guten-block). 37 | 38 |
39 | 40 | 👉 Kindly, read the up to date documentation at this link → [Create Guten Block](https://github.com/ahmadawais/create-guten-block) 41 | 42 | -------------------------------------------------------------------------------- /packages/create-guten-block/app/cli.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Commande.js CLI 3 | * 4 | * Set the options for -v --help etc. 5 | */ 6 | 7 | 'use strict'; 8 | 9 | const chalk = require( 'chalk' ); 10 | const commander = require( 'commander' ); 11 | const maybeEnvInfo = require( './envInfo' ); 12 | const noBlockName = require( './noBlockName' ); 13 | const invalidBlockName = require( './invalidBlockName' ); 14 | const packageJson = require( '../package.json' ); 15 | 16 | // Commander.js program. 17 | module.exports = () => { 18 | // Block's name 19 | let blockName; 20 | 21 | const program = new commander.Command( packageJson.name ) 22 | .arguments( '' ) 23 | .usage( `${ chalk.green( '' ) }` ) 24 | .action( name => { 25 | blockName = name; 26 | } ) 27 | .allowUnknownOption() 28 | .on( '--help', () => { 29 | console.log( `\n Only ${ chalk.green( '' ) } is required.\n` ); 30 | } ) 31 | .option( '-d, --debug', 'Prints envinfo for debugging' ) 32 | .option( '-c, --canary', 'To use latest canary version for dev-testing' ) 33 | .description( 34 | `CGB ${ chalk.dim( '(create-guten-block)' ) } is a Zero-Config #OCJS for builing WordPress Gutenberg Blocks.` 35 | ) 36 | .version( packageJson.version, '-v, --version' ) 37 | .parse( process.argv ); 38 | 39 | const isCanary = program.canary ? true : false; 40 | 41 | // If no blockName. 42 | if ( typeof blockName === 'undefined' ) { 43 | // Maybe user asked for debug info. 44 | maybeEnvInfo( program ); 45 | 46 | // If still running then tell user to provide blockName. 47 | noBlockName(); 48 | } // End. 49 | 50 | // We must have a blockName by now. 51 | 52 | // Format the blockName. 53 | const formatBlockName = blockName 54 | .toLowerCase() 55 | .split( ' ' ) 56 | .join( '-' ); 57 | 58 | // Check if block name is valid. 59 | const blockNameRegex = /^[a-z][a-z0-9-]/; 60 | if ( ! blockNameRegex.test( formatBlockName ) ) { 61 | invalidBlockName(); 62 | } 63 | 64 | return { blockName: formatBlockName, isCanary: isCanary }; 65 | }; 66 | -------------------------------------------------------------------------------- /packages/create-guten-block/app/consoleClear.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Cross platform clear console. 3 | * 4 | * Support for win32 and others. 5 | */ 6 | 7 | 'use strict'; 8 | 9 | module.exports = () => { 10 | process.stdout.write( 11 | process.platform === 'win32' ? '\x1B[2J\x1B[0f' : '\x1B[2J\x1B[3J\x1B[H' 12 | ); 13 | }; 14 | -------------------------------------------------------------------------------- /packages/create-guten-block/app/createGitignore.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Install a starter .gitignore 3 | */ 4 | 5 | 'use strict'; 6 | 7 | const path = require( 'path' ); 8 | const fs = require( 'fs-extra' ); 9 | const shell = require( 'shelljs' ); 10 | 11 | module.exports = (blockDir) => { 12 | shell.cd( blockDir ); 13 | shell.touch( '.gitignore' ); 14 | 15 | // Build a default .gitignore 16 | const ignore = [ 17 | 'node_modules\n', 18 | '## Uncomment line below if you prefer to', 19 | '## keep compiled files out of version control', 20 | '# dist/' 21 | ].join('\n'); 22 | 23 | return new Promise( async resolve => { 24 | await fs.writeFileSync( 25 | path.join( process.cwd(), '.gitignore' ), 26 | ignore + '\n' 27 | ); 28 | resolve( true ); 29 | } ); 30 | }; 31 | -------------------------------------------------------------------------------- /packages/create-guten-block/app/createPluginDir.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Create Plugin Directory. 3 | * 4 | * @param {string} blockName The block name. 5 | * @return {promise} promise resolved. 6 | */ 7 | 8 | 'use strict'; 9 | 10 | const chalk = require('chalk'); 11 | const shell = require('shelljs'); 12 | const clearConsole = require('./consoleClear'); 13 | const directoryExists = require('directory-exists'); 14 | const createGitignore = require('./createGitignore'); 15 | 16 | module.exports = (blockName, blockDir) => { 17 | // Check if the plugin dir is already presnet. 18 | const dirAlreadyExist = directoryExists.sync(`./${blockName}`); 19 | 20 | // If exists then exit. 21 | if (dirAlreadyExist) { 22 | clearConsole(); 23 | console.log('\n❌ ', chalk.black.bgRed(` A directory with this name already exists: ${blockName} \n`)); 24 | 25 | console.log( 26 | ` ${chalk.dim('Please move or delete it (maybe make a copy for backup) and run this command again.')}` 27 | ); 28 | console.log(` ${chalk.dim('Or provide a different name for your block.')}`); 29 | console.log(chalk.dim('\nFor example: \n')); 30 | console.log(` ${chalk.dim('create-guten-block')} ${chalk.green('new-block-name')}\n`); 31 | process.exit(1); 32 | } else { 33 | return new Promise(async resolve => { 34 | // Where user is at the moment. 35 | shell.mkdir('-p', blockName); 36 | await createGitignore(blockDir); 37 | resolve(true); 38 | }); 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /packages/create-guten-block/app/envInfo.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Environment Info 3 | * 4 | * Prints envinfo for debugging. 5 | */ 6 | 7 | 'use strict'; 8 | 9 | const chalk = require( 'chalk' ); 10 | const envinfo = require( 'envinfo' ); 11 | const clearConsole = require( './consoleClear' ); 12 | 13 | module.exports = program => { 14 | // Envinfo. 15 | if ( program.debug ) { 16 | clearConsole(); 17 | 18 | console.log( 19 | '\n🔰 ' + 20 | chalk.black.bgYellow( ' Printing the debug env info below: \n\n' ) + 21 | chalk.dim( ' This may take a couple of seconds...' ) 22 | ); 23 | 24 | // Print the envinfo. 25 | envinfo.print( { 26 | packages: [ 'cgb-scripts' ], 27 | cpu: true, 28 | duplicates: true, 29 | browsers: true, 30 | noNativeIDE: true, 31 | } ); 32 | 33 | console.log( 34 | '\n✅ ' + 35 | chalk.black.bgGreen( ' Done ' ) + 36 | chalk.dim( ' You can copy paste this info to share it...\n' ) 37 | ); 38 | // Let's end the process so the app doesn't continue. 39 | process.exit( 0 ); 40 | } // End Envinfo. 41 | }; 42 | -------------------------------------------------------------------------------- /packages/create-guten-block/app/getBlockDir.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get block directory. 3 | * 4 | * @param {string} blockName The block name. 5 | * @return {string} The block directory. 6 | */ 7 | 8 | 'use strict'; 9 | 10 | const path = require( 'path' ); 11 | 12 | module.exports = blockName => { 13 | return path.join( process.cwd(), blockName ); 14 | }; 15 | -------------------------------------------------------------------------------- /packages/create-guten-block/app/initBlock.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Initialize the block plugin. 3 | * 4 | * @param {string} blockName The block name. 5 | * @param {string} blockDir The block directory. 6 | */ 7 | 8 | 'use strict'; 9 | 10 | const path = require( 'path' ); 11 | 12 | module.exports = ( blockName, blockDir ) => { 13 | // Root path. 14 | const root = process.cwd(); 15 | 16 | // Get path to cgb-scripts. 17 | const scriptsPath = path.resolve( 18 | blockDir, 19 | 'node_modules', 20 | 'cgb-scripts', 21 | 'scripts', 22 | 'init.js' 23 | ); 24 | 25 | // Require cgb-scripts. 26 | const init = require( scriptsPath ); 27 | 28 | // Run the initializer function. 29 | init( root, blockName, blockDir ); 30 | }; 31 | -------------------------------------------------------------------------------- /packages/create-guten-block/app/invalidBlockName.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Handle if there's block name is not valid. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | const chalk = require( 'chalk' ); 8 | 9 | module.exports = () => { 10 | // Stop if given block name is not valid. 11 | console.log( 12 | '\n❌ ', 13 | chalk.black.bgRed( ' Please provide a valid block name: \n' ) 14 | ); 15 | console.log( 16 | `${ chalk.dim( 17 | '⚠️ A block name can only contain lowercase alphanumeric characters and dashes.' 18 | ) }` 19 | ); 20 | console.log( `${ chalk.dim( '⚠️ A block name must begin with a letter.' ) }` ); 21 | console.log(); 22 | process.exit( 1 ); 23 | }; 24 | -------------------------------------------------------------------------------- /packages/create-guten-block/app/noBlockName.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Handle if there's no block name. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | const chalk = require( 'chalk' ); 8 | 9 | module.exports = () => { 10 | // Stop if there's no block name to create the plugin dir. 11 | console.log( 12 | '\n❌ ', 13 | chalk.black.bgRed( ' You forgot to specify a block name: \n' ) 14 | ); 15 | console.log( 16 | ` ${ chalk.dim( 'create-guten-block' ) } ${ chalk.green( '' ) }` 17 | ); 18 | console.log( chalk.dim( '\nFor example: \n' ) ); 19 | console.log( 20 | ` ${ chalk.dim( 'create-guten-block' ) } ${ chalk.green( 'my-block' ) }\n` 21 | ); 22 | process.exit( 1 ); 23 | }; 24 | -------------------------------------------------------------------------------- /packages/create-guten-block/app/npmInstallScripts.js: -------------------------------------------------------------------------------- 1 | /** 2 | * NPM install cgb-scripts. 3 | * 4 | * - Build package.json file. 5 | * - NPM install the plugin block. 6 | * 7 | * @param {string} blockName The block name. 8 | * @param {string} blockDir The block directory. 9 | * @return {promise} promise resolved. 10 | */ 11 | 12 | 'use strict'; 13 | 14 | const path = require( 'path' ); 15 | const fs = require( 'fs-extra' ); 16 | const execa = require( 'execa' ); 17 | const shell = require( 'shelljs' ); 18 | 19 | module.exports = ( blockName, blockDir, isCanary ) => { 20 | shell.cd( blockDir ); 21 | shell.touch( 'package.json' ); 22 | 23 | // Build a package.json file since npm install needs it. 24 | const appPackage = { 25 | name: `${ blockName }-cgb-guten-block`, 26 | version: '1.0.0', 27 | private: true, 28 | scripts: { 29 | start: 'cgb-scripts start', 30 | build: 'cgb-scripts build', 31 | eject: 'cgb-scripts eject', 32 | }, 33 | }; 34 | 35 | // Write the package.json file. 36 | fs.writeFileSync( path.join( process.cwd(), 'package.json' ), JSON.stringify( appPackage, null, 2 ) + '\n' ); 37 | 38 | // Are we testing or not? 39 | if ( isCanary ) { 40 | // Install latest canary version of cgb-scripts for test in development of CGB. 41 | return new Promise( async resolve => { 42 | await execa( 'npm', [ 'install', 'cgb-scripts@canary', '--save', '--save-exact', '--silent' ] ); 43 | resolve( true ); 44 | } ); 45 | } 46 | // Install latest exact version of cgb-scripts. 47 | return new Promise( async resolve => { 48 | await execa( 'npm', [ 'install', 'cgb-scripts', '--save', '--save-exact', '--silent' ] ); 49 | resolve( true ); 50 | } ); 51 | }; 52 | -------------------------------------------------------------------------------- /packages/create-guten-block/app/prePrint.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Print anything in the start. 3 | * 4 | * @param {string} blockName The block name. 5 | * @param {string} blockDir The block directory. 6 | */ 7 | 8 | 'use strict'; 9 | 10 | const chalk = require( 'chalk' ); 11 | 12 | module.exports = ( blockName, blockDir ) => { 13 | console.log( '\n' ); 14 | console.log( 15 | '📦 ', 16 | chalk.black.bgYellow( 17 | ` Creating a WP Gutenberg Block plugin called: ${ chalk.bgGreen( 18 | ` ${ blockName } ` 19 | ) }\n` 20 | ), 21 | chalk.dim( `\n In the directory: ${ blockDir }\n` ), 22 | chalk.dim( 'This might take a couple of minutes.\n' ) 23 | ); 24 | }; 25 | -------------------------------------------------------------------------------- /packages/create-guten-block/app/run.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Run the entire program. 3 | * 4 | * Runs all the functions with async/await. 5 | */ 6 | 7 | 'use strict'; 8 | 9 | const ora = require( 'ora' ); 10 | const chalk = require( 'chalk' ); 11 | const cli = require( './cli' ); 12 | const prePrint = require( './prePrint' ); 13 | const initBlock = require( './initBlock' ); 14 | const getBlockDir = require( './getBlockDir' ); 15 | const clearConsole = require( './consoleClear' ); 16 | const updateNotifier = require( './updateNotifier' ); 17 | const createPluginDir = require( './createPluginDir' ); 18 | const npmInstallScripts = require( './npmInstallScripts' ); 19 | 20 | module.exports = async() => { 21 | clearConsole(); 22 | 23 | // 0. Update notifier. 24 | updateNotifier(); 25 | 26 | // 1. Set the CLI and get the blockName. 27 | const { blockName, isCanary } = cli(); 28 | 29 | // 1.1 If we are testing in dev mode then notify. 30 | if ( isCanary ) { 31 | console.log( '\n', '⚠️ ', chalk.black.bgYellow( ' CANARY MODE ' ), '\n' ); 32 | } 33 | 34 | // 2. Build the block directory path. 35 | const blockDir = await getBlockDir( blockName ); 36 | 37 | // 2. Pre print. 38 | await prePrint( blockName, blockDir ); 39 | 40 | // 3. Create the plugin directory. 41 | // Init the spinner. 42 | const spinner = ora( { text: '' } ); 43 | 44 | spinner.start( `1. Creating the plugin directory called → ${ chalk.black.bgWhite( ` ${ blockName } ` ) }` ); 45 | await createPluginDir( blockName, blockDir ); 46 | spinner.succeed(); 47 | 48 | // 4. NPM install cgb-scripts. 49 | spinner.start( '2. Installing npm packages...' ); 50 | await npmInstallScripts( blockName, blockDir, isCanary ); 51 | spinner.succeed(); 52 | 53 | // 5. Initialize the block. 54 | await initBlock( blockName, blockDir ); 55 | }; 56 | -------------------------------------------------------------------------------- /packages/create-guten-block/app/test.js: -------------------------------------------------------------------------------- 1 | const clearConsole = require( './consoleClear' ); 2 | const path = require( 'path' ); 3 | 4 | clearConsole(); 5 | 6 | const blockName = 'my-block'; 7 | console.log( `${ process.cwd() }/${ blockName }` ); 8 | 9 | console.log( path.join( process.cwd(), blockName ) ); 10 | -------------------------------------------------------------------------------- /packages/create-guten-block/app/updateNotifier.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Update notifier 3 | */ 4 | 5 | 'use strict'; 6 | 7 | const updateNotifier = require( 'update-notifier' ); 8 | const pkg = require( '../package.json' ); 9 | 10 | module.exports = () => { 11 | updateNotifier( { pkg } ).notify(); 12 | }; 13 | -------------------------------------------------------------------------------- /packages/create-guten-block/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /** 3 | * Main create-guten-block app 4 | * 5 | * Check the node version if above 8 then run the app. 6 | */ 7 | 8 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9 | // /!\ DO NOT MODIFY THIS FILE /!\ 10 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11 | // 12 | // create-guten-block is installed globally on people's computers. This means 13 | // that it is extremely difficult to have them upgrade the version and 14 | // because there's only one global version installed, it is very prone to 15 | // breaking changes. 16 | // 17 | // The only job of create-guten-block is to init the repository and then 18 | // forward all the commands to the local version of create-guten-block. 19 | // 20 | // If you need to add a new command, please add it to the scripts/ folder. 21 | // 22 | // The only reason to modify this file is to add more warnings and 23 | // troubleshooting information for the `create-guten-block` command. 24 | // 25 | // Do not make breaking changes! We absolutely don't want to have to 26 | // tell people to update their global version of create-guten-block. 27 | // 28 | // Also be careful with new language features. 29 | // This file must work on Node 0.10+. 30 | // 31 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 32 | // /!\ DO NOT MODIFY THIS FILE /!\ 33 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 34 | 35 | 'use strict'; 36 | 37 | const chalk = require( 'chalk' ); 38 | const currentNodeVersion = process.versions.node; 39 | const semver = currentNodeVersion.split( '.' ); 40 | const major = semver[ 0 ]; 41 | 42 | // If below Node 8. 43 | if ( major < 8 ) { 44 | console.error( 45 | chalk.red( 46 | 'You are running Node ' + 47 | currentNodeVersion + 48 | '.\n' + 49 | 'Create Guten Block requires Node 8 or higher. \n' + 50 | 'Kindly, update your version of Node.' 51 | ) 52 | ); 53 | process.exit( 1 ); 54 | } 55 | 56 | // Makes the script crash on unhandled rejections instead of silently 57 | // ignoring them. In the future, promise rejections that are not handled will 58 | // terminate the Node.js process with a non-zero exit code. 59 | process.on( 'unhandledRejection', err => { 60 | throw err; 61 | } ); 62 | 63 | /** 64 | * Run the entire program. 65 | * 66 | * Runs all the functions with async/await. 67 | */ 68 | const run = require( './app/run' ); 69 | run(); 70 | -------------------------------------------------------------------------------- /packages/create-guten-block/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "create-guten-block", 3 | "version": "1.14.0", 4 | "description": "Create a WordPress Gutenberg Block plugin with Zero-Config #OCJS, Webpack, React, ES6/7/8/Next, ESLint, Babel, and more.", 5 | "main": "index.js", 6 | "keywords": [ 7 | "gutenberg", 8 | "create-gutenberg-block", 9 | "create-gutenberg-blocks", 10 | "wp", 11 | "wordpress", 12 | "cgb", 13 | "wp webpack", 14 | "react", 15 | "ESLint", 16 | "Webpack", 17 | "wp-scripts", 18 | "cgb-scripts", 19 | "guten-scripts", 20 | "babel", 21 | "cgb-dev-utils", 22 | "babel-preset-cgb" 23 | ], 24 | "author": "Ahmad Awais (https://AhmadAwais.com/)", 25 | "license": "MIT", 26 | "repository": { 27 | "type": "git", 28 | "url": "git+https://github.com/ahmadawais/create-guten-block.git" 29 | }, 30 | "bugs": { 31 | "url": "https://github.com/ahmadawais/create-guten-block/issues" 32 | }, 33 | "homepage": "https://github.com/ahmadawais/create-guten-block#readme", 34 | "dependencies": { 35 | "@scarf/scarf": "^1.0.6", 36 | "chalk": "^2.3.0", 37 | "commander": "^2.13.0", 38 | "directory-exists": "^1.0.2", 39 | "envinfo": "^3.11.0", 40 | "execa": "^0.9.0", 41 | "fs-extra": "^5.0.0", 42 | "ora": "^1.3.0", 43 | "shelljs": "^0.8.0", 44 | "update-notifier": "^2.3.0" 45 | }, 46 | "bin": { 47 | "create-guten-block": "./index.js" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tasks/cgb.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /** 3 | * CGB Command Run for Dev ENV. 4 | */ 5 | 6 | // Runs CGB command in development env. 7 | // Runs lerna bootstrap. 8 | // Then handleErrors. 9 | // TODO: Allow custom scripts. 10 | 11 | 'use strict'; 12 | 13 | const fs = require( 'fs' ); 14 | const path = require( 'path' ); 15 | const cp = require( 'child_process' ); 16 | 17 | const cleanup = () => { 18 | console.log( 'Cleaning up.' ); 19 | // Uncomment when snapshot testing is enabled by default: 20 | // rm ./template/src/__snapshots__/App.test.js.snap 21 | }; 22 | 23 | const handleExit = () => { 24 | cleanup(); 25 | console.log( 'Exiting without error.' ); 26 | process.exit(); 27 | }; 28 | 29 | const handleError = e => { 30 | console.error( 'ERROR! An error was encountered while executing\n', e ); 31 | cleanup(); 32 | console.log( 'Exiting with error.' ); 33 | process.exit( 1 ); 34 | }; 35 | 36 | process.on( 'SIGINT', handleExit ); 37 | process.on( 'uncaughtException', handleError ); 38 | 39 | // ****************************************************************************** 40 | // Pack cgb-scripts so we can verify they work. 41 | // ****************************************************************************** 42 | 43 | // The rootDir is where this repo exits. i.e. the dir where lerna.json is. 44 | const rootDir = path.join( __dirname, '..' ); 45 | const cgbScriptsDir = path.join( rootDir, 'packages', 'cgb-scripts' ); 46 | const packageJsonPath = path.join( cgbScriptsDir, 'package.json' ); 47 | const packageJsonOrigPath = path.join( cgbScriptsDir, 'package.json.orig' ); 48 | 49 | // Install all our packages. 50 | const lernaPath = path.join( rootDir, 'node_modules', '.bin', 'lerna' ); 51 | cp.execSync( `${ lernaPath } bootstrap`, { 52 | cwd: rootDir, 53 | stdio: 'inherit', 54 | } ); 55 | 56 | // Save package.json because we're going to touch it 57 | fs.writeFileSync( packageJsonOrigPath, fs.readFileSync( packageJsonPath ) ); 58 | 59 | // Replace own dependencies (those in the`packages` dir) with the local paths 60 | // of those packages 61 | const replaceOwnDepsPath = path.join( __dirname, 'replace-own-deps.js' ); 62 | cp.execSync( `node ${ replaceOwnDepsPath }`, { stdio: 'inherit' } ); 63 | 64 | // TODO: Allow custom scripts. 65 | // // Finally, pack cgb-scripts 66 | // // Don't redirect stdio as we want to capture the output that will be returned 67 | // // from execSync(). In this case it will be the .tgz filename. 68 | // const scriptsFileName = cp 69 | // .execSync( 'npm pack', { cwd: cgbScriptsDir } ) 70 | // .toString() 71 | // .trim(); 72 | 73 | // const scriptsPath = path.join( 74 | // rootDir, 75 | // 'packages', 76 | // 'cgb-scripts', 77 | // scriptsFileName 78 | // ); 79 | 80 | // Restore package.json 81 | fs.unlinkSync( packageJsonPath ); 82 | fs.writeFileSync( packageJsonPath, fs.readFileSync( packageJsonOrigPath ) ); 83 | fs.unlinkSync( packageJsonOrigPath ); 84 | 85 | // ****************************************************************************** 86 | // Now that we have packed them, call the global CLI. 87 | // ****************************************************************************** 88 | 89 | // If Yarn is installed, clean its cache because it may have cached cgb-scripts 90 | try { 91 | cp.execSync( 'yarn cache clean' ); 92 | } catch ( e ) { 93 | // We can safely ignore this as the user doesn't have yarn installed 94 | } 95 | 96 | const args = process.argv.slice( 2 ); 97 | 98 | // Now run the CGB command. 99 | const cgbScriptPath = path.join( 100 | rootDir, 101 | 'packages', 102 | 'create-guten-block', 103 | 'index.js' 104 | ); 105 | cp.execSync( 106 | // TODO: Allow custom scripts. 107 | // `node ${ cgbScriptPath } --scripts-version="${ scriptsPath }" ${ args.join( ' ' ) }`, 108 | `node ${ cgbScriptPath } ${ args.join( ' ' ) }`, 109 | { 110 | cwd: rootDir, 111 | stdio: 'inherit', 112 | } 113 | ); 114 | 115 | // Cleanup. Dev only. 116 | handleExit(); 117 | -------------------------------------------------------------------------------- /tasks/publish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ****************************************************************************** 4 | # This releases an update to the `cgb-scripts` package. 5 | # Don't use `npm publish` for it. 6 | # ****************************************************************************** 7 | 8 | # TODO: Release instructions. 9 | 10 | # Start in tasks/ even if run from root directory. 11 | cd "$(dirname "$0")" 12 | 13 | # Exit the script on any command with non 0 return code 14 | # We assume that all the commands in the pipeline set their return code 15 | # properly and that we do not need to validate that the output is correct 16 | set -e 17 | 18 | # Echo every command being executed 19 | set -x 20 | 21 | # Go to root 22 | cd .. 23 | root_path=$PWD 24 | 25 | if [ -n "$(git status --porcelain)" ]; then 26 | echo "❌ Your git status is not clean. Aborting."; 27 | exit 1; 28 | fi 29 | 30 | # Go! 31 | ./node_modules/.bin/lerna publish --independent "$@" -------------------------------------------------------------------------------- /tasks/replace-own-deps.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /** 3 | * Replace Deps 4 | * 5 | * Replaces internal dependencies in package.json with local package paths. 6 | * 7 | * TODO: Implement for all packages and with better flow control. 8 | */ 9 | 'use strict'; 10 | 11 | const fs = require( 'fs' ); 12 | const path = require( 'path' ); 13 | 14 | const packagesDir = path.join( __dirname, '../packages' ); 15 | const pkgFilename = path.join( packagesDir, 'cgb-scripts/package.json' ); 16 | const data = require( pkgFilename ); 17 | 18 | fs.readdirSync( packagesDir ).forEach( name => { 19 | if ( data.dependencies[ name ] ) { 20 | data.dependencies[ name ] = 'file:' + path.join( packagesDir, name ); 21 | } 22 | } ); 23 | 24 | fs.writeFile( pkgFilename, JSON.stringify( data, null, 2 ), 'utf8', err => { 25 | if ( err ) { 26 | throw err; 27 | } 28 | console.log( 'Replaced local dependencies.' ); 29 | } ); 30 | --------------------------------------------------------------------------------