An open API service indexing awesome lists of open source software.

https://github.com/jverneaut/html-to-gutenberg


https://github.com/jverneaut/html-to-gutenberg

Last synced: about 2 months ago
JSON representation

Awesome Lists containing this project

README

        

![Tests Status](https://github.com/jverneaut/html-to-gutenberg/actions/workflows/test.yml/badge.svg)
![GitHub Release](https://img.shields.io/github/v/release/jverneaut/html-to-gutenberg)

# HTML To Gutenberg

A Webpack plugin and CLI that generates dynamic Gutenberg blocks built with React and either PHP or Twig, from a single HTML file.

Instead of manually coding both React and PHP/Twig components, simply write an HTML file with some special attributes, and this plugin will automatically generate all necessary files for you:

- ✅ **React-based** `edit.js` for the WordPress editor
- ✅ **Frontend rendering with** `render.php` by default
- ✅ Or use **Twig-based** `render.twig` if you prefer (recommended!)
- ✅ **block.json** with automatically defined attributes
- ✅ **index.js** to register the block type

https://github.com/user-attachments/assets/d9ee9410-9529-4664-a7a4-82b0eb1ad306

This plugin now **defaults to PHP rendering**, making it more compatible with typical WordPress projects.

However, if you're working with **Timber, Bedrock**, or just want a more **frontend-friendly templating experience**, you can enable Twig rendering by setting:

```js
new HTMLToGutenbergPlugin({
...
engine: "twig", // Enables render.twig instead of render.php
});
```

👉 Personally, **I highly recommend Twig** for rendering blocks. It feels closer to HTML, is easier to read and write, and is much nicer to maintain—especially if you're a front-end developer.

> For a full Twig-based Gutenberg-ready setup, check out my other project [gutenberg-tailwindcss-bedrock-timber-twig](https://github.com/jverneaut/gutenberg-tailwindcss-bedrock-timber-twig/)

## ✨ Features

- **Automatic Gutenberg block generation** from simple HTML
- **Use attributes** (`data-attribute="title"`, etc.) to define editable fields
- **Supports RichText and MediaUpload**:
- Non-`` elements with `data-attribute="something"` → **Editable RichText**
- `` elements with `data-attribute="something"` → **Image selection via MediaUpload**
- **Fully automates block.json attributes creation**
- **Add additional styles** via the `data-styles="primary secondary"` attribute on the root block element
- **InnerBlocks handling** with `` and `` elements
- **Automatic `style` strings to JS objects conversion** for `edit.js`
- **Supports both PHP and Twig** for frontend rendering

## 📦 Installation

```sh
npm install --save-dev @jverneaut/html-to-gutenberg
npm install --save-dev @10up/block-components # Required for the edit.js component
```

## ⚙️ Webpack Configuration

This plugin is designed to work with Webpack. Here's how to integrate it:

```js
// webpack.config.js
import HTMLToGutenbergPlugin from "@jverneaut/html-to-gutenberg";

export default {
plugins: [
new HTMLToGutenbergPlugin({
inputDirectory: "./blocks", // Your source HTML files
outputDirectory: "./generated-blocks", // Where generated Gutenberg blocks will be placed
blocksPrefix: "custom", // Blocks namespace

// Optional: switch to Twig-based rendering (recommended)
engine: "twig", // either 'php' (default) or 'twig'
}),
],
};
```

📌 This setup will:

- Scan `blocks/` for `.html` files
- Generate Gutenberg blocks inside `generated-blocks/`

> **Note: These blocks still need to be bundled and registered with WordPress before use.**

### Minimal full setup example using Webpack and PHP

#### Webpack configuration

```js
// webpack.config.js
import HTMLToGutenbergPlugin from "@jverneaut/html-to-gutenberg";
import GutenbergWebpackPlugin from "@jverneaut/gutenberg-webpack-plugin";

export default {
mode: "development",
entry: "./index.js", // Your main entry point for non-Gutenberg scripts

plugins: [
new HTMLToGutenbergPlugin({
inputDirectory: "./blocks", // Source folder for your custom blocks HTML
outputDirectory: "./generated-blocks", // Where transformed blocks will be output
}),

new GutenbergWebpackPlugin("./generated-blocks"), // Registers the generated blocks
],

module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env", "@babel/preset-react"],
},
},
},
],
},
};
```

#### Registering Blocks in PHP

Add the following to your theme’s `functions.php` file or a custom plugin to automatically register the generated blocks with WordPress:

```php
add_action('init', function () {
$blocks_path = get_stylesheet_directory() . '/dist/blocks';
$blocks = array_filter(glob($blocks_path . '/**/*'), 'is_dir');

foreach ($blocks as $block) {
register_block_type($block);
}
});
```

This is a lightweight, automatic setup. Feel free to adapt it to your specific workflow — other approaches might suit your project better.

## CLI

```sh
Usage: npx @jverneaut/html-to-gutenberg [options]

A Webpack plugin and CLI that generates dynamic Gutenberg blocks built with React and either PHP or Twig, from a single HTML file.

Options:
-V, --version output the version number
-i, --input HTML blocks input path (default: ".")
-o, --output Gutenberg blocks output path
-p, --prefix Blocks namespace (default: "custom")
-e, --engine Engine (either "php", "twig" or "all") (default: "php")
-w, --watch Watch the input directory for changes and regenerate blocks
-h, --help display help for command
```

## 🚀 Quick Start (Example Project)

**An example** is available in the `example/` folder. You can test it by running:

```sh
cd example
npm install
npm run dev
```

You can then edit `demo-block.html` and see the generated block inside `example/generated/demo-block`. It is setup to output both `render.php` as well as `render.twig` for demonstration purposes.

## Usage

> _Documentation writing in progress..._
>
> In the meantime, you can explore a variety of examples in the [\_\_tests\_\_/fixtures/processable](https://github.com/jverneaut/html-to-gutenberg/tree/main/__tests__/fixtures/processable) directory. These include both Twig and PHP rendering examples to help you understand how to generate blocks using HTML with this plugin.
>
> As long as the input HTML is valid, the plugin should correctly parse it and generate the corresponding translated JS/Twig/PHP files. If you come across any edge cases or manage to break the plugin in unexpected ways, feel free to open an issue.

## Example

### 📝 Input HTML

```html



Hello, Gutenberg!


Lorem ipsum dolor sit amet consectetur, adipisicing elit. Veritatis
facere deleniti nam magni. Aspernatur, obcaecati fuga.








Title 2
42







```

### 🔄 Generated files

✅ `edit.js` **(for Gutenberg editor)**

```jsx
import {
useBlockProps,
RichText,
MediaUpload,
InnerBlocks,
} from "@wordpress/block-editor";
import { Image } from "@10up/block-components";

export default ({ attributes, setAttributes }) => {
return (



setAttributes({ title })}
>

setAttributes({ content })}
>


setAttributes({ image: image.id })}
render={({ open }) => (
setAttributes({ image: image.id })}
/>
)}
>


Title 2", number: 42 },
],
["custom/other-child-block", { title: "Title 3", number: 42 }],
]}
templateLock
>



);
};
```

✅ `render.twig` **(for frontend rendering)**

```twig



{{ attributes.title }}


{{ attributes.content }}



{{ get_image(attributes.image).alt }}


{{ content }}

```

✅ `render.php` **(for frontend rendering)**

```php

'container']); ?>>





<?php echo esc_attr($image_alt); ?>




```

✅ `block.json` **(auto-generated block metadata)**

```json
{
"name": "custom/demo-block",
"title": "Demo Block",
"textdomain": "demo-block",
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"version": "0.1.0",
"category": "theme",
"example": {},
"styles": [
{ "name": "primary", "label": "Primary", "isDefault": true },
{ "name": "secondary", "label": "Secondary" }
],
"attributes": {
"align": { "type": "string", "default": "full" },
"title": {
"type": "string",
"default": "Hello, Gutenberg!"
},
"content": {
"type": "string",
"default": "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Veritatis facere deleniti nam magni. Aspernatur, obcaecati fuga."
},
"image": { "type": "integer" }
},
"supports": { "html": false, "align": ["full"] },
"editorScript": "file:./index.js",
"render": "file:./render.twig", // if using Twig engine
"render": "file:./render.php" // if using PHP engine
}
```

✅ `index.js` **(register the block type)**

```js
import { registerBlockType } from "@wordpress/blocks";
import { InnerBlocks } from "@wordpress/block-editor";

import Edit from "./edit.js";
import metadata from "./block.json";

registerBlockType(metadata.name, {
edit: Edit,
save: () => ,
});
```

## ❓ FAQ

### Can I add more fields beyond RichText and MediaUpload?

Right now, the plugin auto-generates fields for text and images as well as InnerBlocks. Support for additional fields may come later based on my experience building production sites with this tool.

### Should generated blocks be versioned, or should the source HTML file be?

That depends on your strategy:

- **Versioning the source HTML files only:**

You treat the `.html` files as **the single source of truth**, and let this plugin regenerate the entire block every time. This is ideal when using this plugin as a **build tool**, fully automating block creation and updates. You don’t version the generated files—just the `.html`.

- **Versioning the generated files only:**

You use the HTML input files as a **block scaffolding tool**, generate the files once, delete or ignore the `.html` files, and then **manually edit the generated React/Twig/PHP code**. This approach gives you more control over customization at the cost of automation.

👉 Choose the one that fits your workflow best—**automated generation** vs **manual control**.

### Why would I choose Twig instead of PHP for rendering blocks?

Personally, I find **Twig much friendlier** for templating. It’s closer to HTML, which makes it easier to read, write, and maintain—especially for front-end developers.

On top of that, **writing code generation for Twig is simpler** than for PHP. Since the syntax is less verbose and more structured, it’s a better fit for the kind of programmatic output this plugin produces.

### How do I use the Twig-generated blocks inside my project?

Check out [gutenberg-tailwindcss-bedrock-timber-twig](https://github.com/jverneaut/gutenberg-tailwindcss-bedrock-timber-twig/) — a companion project that enables you to use **Twig as the rendering engine for Gutenberg blocks**.

This setup uses Timber and integrates tightly with TailwindCSS and Bedrock, giving you full control over the front-end and a seamless Twig-based authoring experience.

> I plan to release this integration as a standalone package in the future to make it easier to use in other projects.