这是indexloc提供的服务,不要输入任何密码
Skip to content

Feature : Add support for building blocks in theme #512

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions bin/create-block.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/usr/bin/env node

/**
* External dependencies
*/
const fs = require( 'fs' );
const path = require( 'path' );
const { execSync } = require( 'child_process' );

/**
* Parse user inputed arguments.
* @param {Array} args User inputed arguments
* @return {string} Parsed arguments
*/
const parseUserInputedArgs = ( args ) => {
const expectedArgs = {
'--title': '',
'--variant': 'static',
'--namespace': 'elementary-theme',
'--category': '',
'--icon': '',
'--keywords': '',
'--short-description': '',
};

let parsedArgs = '';

args = args.filter( ( arg ) => {
const [ key, value ] = arg.split( '=' );
if ( key in expectedArgs ) {
parsedArgs += `${ key }=${ value } `;
return false;
}
return true;
} );

// Add default arguments.
for ( const [ key, value ] of Object.entries( expectedArgs ) ) {
if ( value && ! args.includes( key ) ) {
parsedArgs += `${ key }=${ value } `;
}
}

// Add remaining arguments.
parsedArgs += args.join( ' ' );

return parsedArgs;
};

/**
* Initialize the script.
* @return {void}
* @throws {Error} If an error occurs.
*/
const init = () => {
try {
// Capture command-line arguments
const args = process.argv.slice( 2 ); // Get all arguments passed after 'node ./bin/create-block.js'

// Check for block slug.
const blockName = args.shift();
if ( ! blockName ) {
console.error( 'Error: You must specify a block name as the first argument.' );
process.exit( 1 );
}

const blockDir = path.join( 'assets', 'src', 'blocks', blockName );

// Parse user inputed arguments
const userInputedArgs = parseUserInputedArgs( args );

// Run @wordpress/create-block with provided arguments
execSync( `npx @wordpress/create-block ${ blockName } --target-dir=${ blockDir } --no-plugin ${ userInputedArgs }`, { stdio: 'inherit' } );

// Check if the block directory exists
if ( fs.existsSync( blockDir ) ) {
console.log( `Block created successfully at ${ blockDir }` );
} else {
throw new Error( 'Error creating block: Block directory does not exist.' );
}
} catch ( error ) {
console.error( 'Error creating block:', error.message );
process.exit( 1 );
}
};

// Run the script.
init();
129 changes: 129 additions & 0 deletions docs/blocks-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# Documentation: Block Development Commands and Workflow in Elementary Theme

The **Elementary Theme** is a starter theme for developing WordPress block-based themes. This documentation outlines the commands available for managing blocks, the process for creating blocks, and the structure for organizing and excluding blocks in your project.

---

## How to Create a New Block

Follow these steps to create a new block:

1. **Run the `create:block` Command**
Execute the following command, replacing `<block-name>` with the desired name of your block:
```bash
npm run create:block <block-name> -- --title="Your Block Title"
```

2. **Customize the Block**
Edit the block’s files in the `assets/src/blocks/<block-name>` directory. You can define the block’s functionality, styles, and scripts in the respective files generated.

3. **Build the Blocks**
Once your block development is complete, build the block to generate production-ready assets:
```bash
npm run build:blocks
```

4. **Verify Block Registration**
The block will be automatically registered based on the manifest and folder structure. Check your WordPress site’s block editor to ensure the block is listed.

---

## How to Exclude a Block

If you need to exclude a block from being registered or built:

1. **Prefix the Block Folder Name with an Underscore**
Rename the block’s folder in `assets/src/blocks` to start with `_` (e.g., `_example-block`).

2. **Effect of the Underscore**
- Blocks with folder names starting with `_` are ignored during the build process.
- They are not registered in WordPress.

---

## Folder Structure for Blocks

Each block resides in its own directory within the `assets/src/blocks` folder. The typical structure for a block is as follows:

```
assets/
└── src/
└── blocks/
├── hero-section/
│ ├── index.js # Block script
│ ├── style.css # Frontend styles
│ ├── editor.css # Editor-specific styles
│ └── block.json # Block metadata
├── testimonial-slider/
│ ├── index.js
│ ├── style.css
│ ├── editor.css
│ └── block.json
└── _example-block/ # Excluded block (prefixed with `_`)
```

---

## Automatic Block Registration

Blocks are automatically registered during the WordPress `init` action. The `blocks-manifest.php` file ensures all blocks in the `assets/build/blocks` directory are registered efficiently. Excluded blocks (with `_` prefixes) are skipped during registration.

---

## Commands for Managing Blocks

### 1. **Create a Block**
Command:
```bash
npm run create:block
```

**Description**:
This command generates a new block using the `@wordpress/create-block` package. It automatically sets up the necessary files and folders in the `assets/src/blocks` directory.

**Usage**:
```bash
npm run create:block <block-name> -- --title="Block Title" --namespace="elementary-theme" --category="common" --icon="smiley" --keywords="block,custom"
```

**Parameters**:
- `--title`: (Optional) The display name of the block.
- `--variant`: (Optional) The variant type of block, default is `static`.
- `--namespace`: (Optional) The namespace for the block, default is `elementary-theme`.
- `--category`: (Optional) The block category, e.g., `common`, `widgets`.
- `--icon`: (Optional) An icon for the block.
- `--keywords`: (Optional) Keywords to help users find the block.
> Note: You can pass additional paramenters that can be used by `@wordpress/create-block` command.

Example:
```bash
npm run create:block hero-section -- --title="Hero Section" --category="layout"
```

### 2. **Build All Blocks**
Command:
```bash
npm run build:blocks
```

**Description**:
Compiles all block files from `assets/src/blocks` and outputs the production-ready code into `assets/build/blocks`.

### 3. **Build Blocks Manifest**
Command:
```bash
npm run build:block-manifest
```

**Description**:
Generates the `blocks-manifest.php` file, which provides metadata about the blocks. This helps WordPress efficiently register and manage block metadata.

---

## Best Practices

- **Use meaningful names** for blocks and their folders to enhance clarity.
- **Test blocks in the WordPress editor** after creation and build to ensure proper functionality.
- **Exclude experimental blocks** by prefixing their folder names with `_`.

By following this workflow, you can streamline the process of developing and managing custom blocks in the Elementary Theme.
76 changes: 76 additions & 0 deletions inc/classes/class-blocks.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php
/**
* Blocks registration file.
*
* @package Elementary-Theme
*/

namespace Elementary_Theme;

use Elementary_Theme\Traits\Singleton;

/**
* Class Blocks
*
* @since 1.0.0
*/
class Blocks {

use Singleton;

/**
* Constructor.
*/
protected function __construct() {
// Setup hooks.
$this->setup_hooks();
}

/**
* Setup hooks.
*
* @since 1.0.0
*/
public function setup_hooks() {
add_action( 'init', array( $this, 'register_blocks' ) );
}

/**
* Register blocks.
*
* @since 1.0.0
*
* @action init
*/
public function register_blocks() {

$blocks_dir = untrailingslashit( get_template_directory() ) . '/assets/build/blocks';

// Get blocks manifest file path.
$manifest = $blocks_dir . '/blocks-manifest.php';

// Check if manifest file exists.
if ( file_exists( $manifest ) ) {

// Register the blocks metadata collection. This will allow WordPress to know about the blocks and improve the performance.
wp_register_block_metadata_collection(
$blocks_dir,
$manifest
);
}

// List all subdirectories in 'inc/blocks' directory.
$blocks = array_filter( glob( $blocks_dir . '/*' ), 'is_dir' );

// Register each block.
foreach ( $blocks as $block ) {
// Get the block name and skip the ones starting with '_' (underscore) prefix.
$block_name = str_replace( $blocks_dir, '', $block );
if ( 0 === strpos( $block_name, '_' ) ) {
continue;
}
// Register the block.
register_block_type( $block );
}
}
}
2 changes: 2 additions & 0 deletions inc/classes/class-elementary-theme.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

use Elementary_Theme\Traits\Singleton;
use Elementary_Theme\Assets;
use Elementary_Theme\Blocks;

/**
* Class Elementary_Theme
Expand All @@ -25,6 +26,7 @@ class Elementary_Theme {
protected function __construct() {
// Instantiate classes.
Assets::get_instance();
Blocks::get_instance();

// Setup hooks.
$this->setup_hooks();
Expand Down
Loading
Loading