├── .github └── workflows │ └── npm-publish.yml ├── .gitignore ├── README.md ├── index.js ├── inner-template ├── index.js └── templates │ ├── block.json.mustache │ ├── edit.js.mustache │ ├── editor.scss.mustache │ ├── index.js.mustache │ ├── save.js.mustache │ └── style.scss.mustache ├── package.json └── templates ├── $slug.php.mustache ├── .editorconfig.mustache ├── .eslintrc.mustache ├── .gitignore.mustache ├── includes └── block-editor │ └── blocks │ └── $slug │ ├── block.json.mustache │ ├── edit.js.mustache │ ├── editor.scss.mustache │ ├── index.js.mustache │ ├── save.js.mustache │ └── style.scss.mustache └── webpack.config.js.mustache /.github/workflows/npm-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages 3 | 4 | name: Node.js Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v2 15 | - uses: actions/setup-node@v2 16 | with: 17 | node-version: 14 18 | - run: npm ci 19 | - run: npm test 20 | 21 | publish-npm: 22 | needs: build 23 | runs-on: ubuntu-latest 24 | steps: 25 | - uses: actions/checkout@v2 26 | - uses: actions/setup-node@v2 27 | with: 28 | node-version: 14 29 | registry-url: https://registry.npmjs.org/ 30 | - run: npm ci 31 | - run: npm publish 32 | env: 33 | NODE_AUTH_TOKEN: ${{secrets.npm_token}} 34 | 35 | publish-gpr: 36 | needs: build 37 | runs-on: ubuntu-latest 38 | permissions: 39 | contents: read 40 | packages: write 41 | steps: 42 | - uses: actions/checkout@v2 43 | - uses: actions/setup-node@v2 44 | with: 45 | node-version: 14 46 | registry-url: https://npm.pkg.github.com/ 47 | - run: npm ci 48 | - run: npm publish 49 | env: 50 | NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}} 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Coverage directory used by tools like istanbul 9 | coverage 10 | 11 | # Compiled binary addons (https://nodejs.org/api/addons.html) 12 | build/Release 13 | 14 | # Dependency directories 15 | node_modules/ 16 | 17 | # Optional npm cache directory 18 | .npm 19 | 20 | # Optional eslint cache 21 | .eslintcache 22 | 23 | # Output of 'npm pack' 24 | *.tgz 25 | 26 | # dotenv environment variables file 27 | .env 28 | 29 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # multiple-blocks-template 2 | 3 | This template will scaffold a plugin that is set up for registering multiple blocks in a single plugin create using the [`@wordpress/create-block`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-create-block/) tool. 4 | 5 | ## Usage 6 | Run the following in the terminal of your choice: 7 | 8 | `npx @wordpress/create-block example-plugin --template @ryanwelcher/multiple-blocks-template` 9 | 10 | The name of the plugin ( example-plugin in the example above) is used as both the name of the plugin and the name of the block being created. This is due to the current `@wordpress/create-block` tool expecting a single block per plugin. 11 | 12 | 13 | ## Structure 14 | 15 | Once the command has completed, the following structure will be created. 16 | 17 | ``` 18 | - assets - this contains an internal template for subsequent blocks 19 | - build 20 | - includes 21 | --> block-editor 22 | ---> blocks 23 | ----> {example-block} 24 | -----> block.json 25 | -----> edit.js 26 | -----> editor.scss 27 | -----> index.js 28 | -----> save.js 29 | -----> style.scss 30 | .editorconfig 31 | .eslintrc 32 | .gitignore 33 | {example-block}.php 34 | package.json 35 | package-lock.json 36 | webpack.config.js 37 | ``` 38 | 39 | ### Adding another block requires the following steps: 40 | 41 | 1. From the root of the plugin, cc into the includes/block-editor/blocks directory 42 | 2. Run the following command: `npx @wordpress/create-block --template ../../../assets 43 | 3. Add a new entry point in `webpack.config.js` that points to the new block. 44 | 4. Update the `$blocks` array in the main plugin php file to include the new block. 45 | 5. Update the editorScripts, editorStyles, and styles items in the newly added block. -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const { join } = require( 'path' ); 2 | 3 | module.exports = { 4 | defaultValues: {}, 5 | templatesPath: join( __dirname, 'templates' ), 6 | assetsPath: join( __dirname, 'inner-template' ), 7 | }; -------------------------------------------------------------------------------- /inner-template/index.js: -------------------------------------------------------------------------------- 1 | const { join } = require( 'path' ); 2 | 3 | module.exports = { 4 | defaultValues: { 5 | wpScripts: false, 6 | editorScript: "file:../../../../build/{{slug}}.js", 7 | editorStyle: "file:../../../../build/{{slug}}.css", 8 | style: "file:../../../../build/{{slug}}.css", 9 | }, 10 | templatesPath: join( __dirname, 'templates' ), 11 | }; -------------------------------------------------------------------------------- /inner-template/templates/block.json.mustache: -------------------------------------------------------------------------------- 1 | { 2 | "apiVersion": {{apiVersion}}, 3 | "name": "{{namespace}}/{{slug}}", 4 | "version": "{{version}}", 5 | "title": "{{title}}", 6 | "category": "{{category}}", 7 | "description": "{{description}}", 8 | "supports": { 9 | "html": false 10 | }, 11 | "textdomain": "{{namespace}}", 12 | "editorScript": "file:../../../../build/{{slug}}.js", 13 | "editorStyle": "file:../../../../build/{{slug}}.css", 14 | "style": "file:../../../../build/style-{{slug}}.css" 15 | } 16 | -------------------------------------------------------------------------------- /inner-template/templates/edit.js.mustache: -------------------------------------------------------------------------------- 1 | /** 2 | * Retrieves the translation of text. 3 | * 4 | * @see https://developer.wordpress.org/block-editor/packages/packages-i18n/ 5 | */ 6 | import { __ } from '@wordpress/i18n'; 7 | 8 | /** 9 | * React hook that is used to mark the block wrapper element. 10 | * It provides all the necessary props like the class name. 11 | * 12 | * @see https://developer.wordpress.org/block-editor/packages/packages-block-editor/#useBlockProps 13 | */ 14 | import { useBlockProps } from '@wordpress/block-editor'; 15 | 16 | /** 17 | * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files. 18 | * Those files can contain any CSS code that gets applied to the editor. 19 | * 20 | * @see https://www.npmjs.com/package/@wordpress/scripts#using-css 21 | */ 22 | import './editor.scss'; 23 | 24 | /** 25 | * The edit function describes the structure of your block in the context of the 26 | * editor. This represents what the editor will render when the block is used. 27 | * 28 | * @see https://developer.wordpress.org/block-editor/developers/block-api/block-edit-save/#edit 29 | * @return {WPElement} Element to render. 30 | */ 31 | export default function Edit() { 32 | return ( 33 |
34 | { __( '{{title}} – hello from the editor!', '{{textdomain}}' ) } 35 |
36 | ); 37 | } 38 | -------------------------------------------------------------------------------- /inner-template/templates/editor.scss.mustache: -------------------------------------------------------------------------------- 1 | /** 2 | * The following styles get applied inside the editor only. 3 | * 4 | * Replace them with your own styles or remove the file completely. 5 | */ 6 | 7 | .wp-block-{{namespace}}-{{slug}} { 8 | border: 1px dotted #f00; 9 | } 10 | -------------------------------------------------------------------------------- /inner-template/templates/index.js.mustache: -------------------------------------------------------------------------------- 1 | /** 2 | * Registers a new block provided a unique name and an object defining its behavior. 3 | * 4 | * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/ 5 | */ 6 | import { registerBlockType } from '@wordpress/blocks'; 7 | 8 | /** 9 | * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files. 10 | * All files containing `style` keyword are bundled together. The code used 11 | * gets applied both to the front of your site and to the editor. 12 | * 13 | * @see https://www.npmjs.com/package/@wordpress/scripts#using-css 14 | */ 15 | import './style.scss'; 16 | 17 | /** 18 | * Internal dependencies 19 | */ 20 | import json from './block.json'; 21 | import edit from './edit'; 22 | import save from './save'; 23 | 24 | const {name, ...settings} = json; 25 | 26 | /** 27 | * Every block starts by registering a new block type definition. 28 | * 29 | * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/ 30 | */ 31 | registerBlockType(name, { 32 | ...settings, 33 | /** 34 | * @see ./edit.js 35 | */ 36 | edit, 37 | 38 | /** 39 | * @see ./save.js 40 | */ 41 | save, 42 | }); 43 | -------------------------------------------------------------------------------- /inner-template/templates/save.js.mustache: -------------------------------------------------------------------------------- 1 | /** 2 | * Retrieves the translation of text. 3 | * 4 | * @see https://developer.wordpress.org/block-editor/packages/packages-i18n/ 5 | */ 6 | import { __ } from '@wordpress/i18n'; 7 | 8 | /** 9 | * React hook that is used to mark the block wrapper element. 10 | * It provides all the necessary props like the class name. 11 | * 12 | * @see https://developer.wordpress.org/block-editor/packages/packages-block-editor/#useBlockProps 13 | */ 14 | import { useBlockProps } from '@wordpress/block-editor'; 15 | 16 | /** 17 | * The save function defines the way in which the different attributes should 18 | * be combined into the final markup, which is then serialized by the block 19 | * editor into `post_content`. 20 | * 21 | * @see https://developer.wordpress.org/block-editor/developers/block-api/block-edit-save/#save 22 | * 23 | * @return {WPElement} Element to render. 24 | */ 25 | export default function save() { 26 | return ( 27 |28 | { __( 29 | '{{title}} – hello from the saved content!', 30 | '{{textdomain}}' 31 | ) } 32 |
33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /inner-template/templates/style.scss.mustache: -------------------------------------------------------------------------------- 1 | /** 2 | * The following styles get applied both on the front of your site 3 | * and in the editor. 4 | * 5 | * Replace them with your own styles or remove the file completely. 6 | */ 7 | 8 | .wp-block-{{namespace}}-{{slug}} { 9 | background-color: #21759b; 10 | color: #fff; 11 | padding: 2px; 12 | } 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ryanwelcher/multiple-blocks-template", 3 | "version": "1.2.2", 4 | "description": "A template for use with @wordpress/create-block to support multiple blocks", 5 | "license": "GPL-2.0-or-later", 6 | "keywords": [ 7 | "wordpress", 8 | "create block", 9 | "block template" 10 | ], 11 | "author": { 12 | "name": "Ryan Welcher", 13 | "url": "https://ryanwelcher.com" 14 | }, 15 | "homepage": "https://github.com/ryanwelcher/create-block-multple-blocks-template", 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/ryanwelcher/create-block-multple-blocks-template.git" 19 | }, 20 | "bugs": { 21 | "url": "https://github.com/ryanwelcher/create-block-multple-blocks-template/issues" 22 | }, 23 | "publishConfig": { 24 | "access": "public" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /templates/$slug.php.mustache: -------------------------------------------------------------------------------- 1 | 34 | { __( '{{title}} – hello from the editor!', '{{textdomain}}' ) } 35 | 36 | ); 37 | } 38 | -------------------------------------------------------------------------------- /templates/includes/block-editor/blocks/$slug/editor.scss.mustache: -------------------------------------------------------------------------------- 1 | /** 2 | * The following styles get applied inside the editor only. 3 | * 4 | * Replace them with your own styles or remove the file completely. 5 | */ 6 | 7 | .wp-block-{{namespace}}-{{slug}} { 8 | border: 1px dotted #f00; 9 | } 10 | -------------------------------------------------------------------------------- /templates/includes/block-editor/blocks/$slug/index.js.mustache: -------------------------------------------------------------------------------- 1 | /** 2 | * Registers a new block provided a unique name and an object defining its behavior. 3 | * 4 | * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/ 5 | */ 6 | import { registerBlockType } from '@wordpress/blocks'; 7 | 8 | /** 9 | * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files. 10 | * All files containing `style` keyword are bundled together. The code used 11 | * gets applied both to the front of your site and to the editor. 12 | * 13 | * @see https://www.npmjs.com/package/@wordpress/scripts#using-css 14 | */ 15 | import './style.scss'; 16 | 17 | /** 18 | * Internal dependencies 19 | */ 20 | import json from './block.json'; 21 | import edit from './edit'; 22 | import save from './save'; 23 | 24 | const {name, ...settings} = json; 25 | 26 | /** 27 | * Every block starts by registering a new block type definition. 28 | * 29 | * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/ 30 | */ 31 | registerBlockType(name, { 32 | ...settings, 33 | /** 34 | * @see ./edit.js 35 | */ 36 | edit, 37 | 38 | /** 39 | * @see ./save.js 40 | */ 41 | save, 42 | }); 43 | -------------------------------------------------------------------------------- /templates/includes/block-editor/blocks/$slug/save.js.mustache: -------------------------------------------------------------------------------- 1 | /** 2 | * Retrieves the translation of text. 3 | * 4 | * @see https://developer.wordpress.org/block-editor/packages/packages-i18n/ 5 | */ 6 | import { __ } from '@wordpress/i18n'; 7 | 8 | /** 9 | * React hook that is used to mark the block wrapper element. 10 | * It provides all the necessary props like the class name. 11 | * 12 | * @see https://developer.wordpress.org/block-editor/packages/packages-block-editor/#useBlockProps 13 | */ 14 | import { useBlockProps } from '@wordpress/block-editor'; 15 | 16 | /** 17 | * The save function defines the way in which the different attributes should 18 | * be combined into the final markup, which is then serialized by the block 19 | * editor into `post_content`. 20 | * 21 | * @see https://developer.wordpress.org/block-editor/developers/block-api/block-edit-save/#save 22 | * 23 | * @return {WPElement} Element to render. 24 | */ 25 | export default function save() { 26 | return ( 27 |28 | { __( 29 | '{{title}} – hello from the saved content!', 30 | '{{textdomain}}' 31 | ) } 32 |
33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /templates/includes/block-editor/blocks/$slug/style.scss.mustache: -------------------------------------------------------------------------------- 1 | /** 2 | * The following styles get applied both on the front of your site 3 | * and in the editor. 4 | * 5 | * Replace them with your own styles or remove the file completely. 6 | */ 7 | 8 | .wp-block-{{namespace}}-{{slug}} { 9 | background-color: #21759b; 10 | color: #fff; 11 | padding: 2px; 12 | } 13 | -------------------------------------------------------------------------------- /templates/webpack.config.js.mustache: -------------------------------------------------------------------------------- 1 | 2 | const defaultConfig = require('@wordpress/scripts/config/webpack.config'); 3 | module.exports = { 4 | ...defaultConfig, 5 | entry: { 6 | '{{slug}}': './includes/block-editor/blocks/{{slug}}', 7 | }, 8 | }; 9 | --------------------------------------------------------------------------------