auto-registering blocks in php and javascript with dynamic enqueuing of associated styles and scripts with support for scss and blade
This commit is contained in:
@@ -36,65 +36,76 @@ add_action('init', function () {
|
|||||||
$blocks = glob(get_theme_file_path('resources/views/blocks/*/block.json'));
|
$blocks = glob(get_theme_file_path('resources/views/blocks/*/block.json'));
|
||||||
|
|
||||||
foreach ($blocks as $block_json) {
|
foreach ($blocks as $block_json) {
|
||||||
$json = json_decode($block_json);
|
$json = json_decode(file_get_contents($block_json));
|
||||||
$slug = basename(dirname($block_json));
|
$slug = basename(dirname($block_json));
|
||||||
|
$blockPath = "resources/views/blocks/{$slug}";
|
||||||
|
|
||||||
// Editor JS
|
$viewScript = "{$blockPath}/view.js";
|
||||||
$editor_js_path = "resources/views/blocks/{$slug}/index.jsx";
|
$script = "{$blockPath}/script.js";
|
||||||
if (file_exists(get_theme_file_path($editor_js_path))) {
|
$editorCSS = "{$blockPath}/editor.scss";
|
||||||
|
$style = "{$blockPath}/style.scss";
|
||||||
|
|
||||||
|
// editorStyle
|
||||||
|
if (file_exists(get_theme_file_path($editorCSS))) {
|
||||||
|
wp_register_style(
|
||||||
|
"{$slug}-editor-style",
|
||||||
|
\Vite::asset($editorCSS),
|
||||||
|
[],
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// script
|
||||||
|
if(file_exists(get_theme_file_path($script))) {
|
||||||
wp_register_script(
|
wp_register_script(
|
||||||
"{$slug}-editor-script",
|
"{$slug}-script",
|
||||||
\Vite::asset($editor_js_path),
|
\Vite::asset($script),
|
||||||
['wp-blocks', 'wp-element', 'wp-editor'],
|
[],
|
||||||
null,
|
null,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Editor SCSS (compiled to CSS)
|
// style
|
||||||
$editor_css_path = "resources/views/blocks/{$slug}/editor.scss";
|
if (file_exists(get_theme_file_path($style))) {
|
||||||
if (file_exists(get_theme_file_path($editor_css_path))) {
|
|
||||||
wp_register_style(
|
wp_register_style(
|
||||||
"{$slug}-editor-style",
|
"{$slug}-style",
|
||||||
\Vite::asset($editor_css_path),
|
\Vite::asset($style),
|
||||||
[],
|
[],
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Frontend SCSS (compiled to CSS)
|
// viewScript
|
||||||
$style_css_path = "resources/views/blocks/{$slug}/style.scss";
|
if(file_exists(get_theme_file_path($viewScript))) {
|
||||||
if (file_exists(get_theme_file_path($style_css_path))) {
|
wp_register_script(
|
||||||
wp_register_style(
|
"{$slug}-view-script",
|
||||||
"{$slug}-style",
|
\Vite::asset($viewScript),
|
||||||
\Vite::asset($style_css_path),
|
|
||||||
[],
|
[],
|
||||||
null
|
null,
|
||||||
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$props = [
|
$props = [
|
||||||
'editor_script' => "{$slug}-editor-script",
|
|
||||||
'editor_style' => "{$slug}-editor-style",
|
'editor_style' => "{$slug}-editor-style",
|
||||||
'style' => "{$slug}-style",
|
'style' => "{$slug}-style",
|
||||||
'render_callback' => function ($attributes, $content, $block) {
|
'script' => "{$slug}-script",
|
||||||
$slug = basename($block->name);
|
'view_script' => "{$slug}-view-script",
|
||||||
$view = "blocks.{$slug}.render";
|
];
|
||||||
|
|
||||||
if (\Roots\view()->exists($view)) {
|
if(!property_exists($json, 'acf') && \Roots\view()->exists("blocks.{$slug}.render")) {
|
||||||
return \Roots\view($view, [
|
$props['render_callback'] = function ($attributes, $content, $block) {
|
||||||
|
$slug = basename($block->name);
|
||||||
|
|
||||||
|
return \Roots\view("blocks.{$slug}.render", [
|
||||||
'attributes' => $attributes,
|
'attributes' => $attributes,
|
||||||
'content' => $content,
|
'content' => $content,
|
||||||
'block' => $block,
|
'block' => $block,
|
||||||
]);
|
]);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return $content;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
if(!@$json['render_callback']) unset($props['render_callback']);
|
|
||||||
|
|
||||||
register_block_type($block_json, $props);
|
register_block_type($block_json, $props);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -136,3 +147,36 @@ function list_allowed()
|
|||||||
apply_filters('badegg_block_types_allow', $add_allowed),
|
apply_filters('badegg_block_types_allow', $add_allowed),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function render_acf($block, $content = '', $is_preview = false, $post_id = 0, $wp_block = false, $context = false) {
|
||||||
|
$slug = basename($block['name']);
|
||||||
|
$block['slug'] = $slug;
|
||||||
|
|
||||||
|
$blade = \Roots\view("blocks.{$slug}.render", [
|
||||||
|
'block' => $block,
|
||||||
|
'content' => $content,
|
||||||
|
'is_preview' => $is_preview,
|
||||||
|
'post_id' => $post_id,
|
||||||
|
'wp_block' => $wp_block,
|
||||||
|
'context' => $context,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if($blade) {
|
||||||
|
echo $blade;
|
||||||
|
} else {
|
||||||
|
ob_start(); ?>
|
||||||
|
|
||||||
|
<section class="section bg-error knockout">
|
||||||
|
<div class="container container-small align-centre wysiwyg">
|
||||||
|
<h2>Missing Blade Template</h2>
|
||||||
|
<p>(resources/views/blocks/<?= $slug ?>/render.blade.php)</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<?php echo ob_get_clean();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
add_action('wp_footer', function(){
|
||||||
|
echo '<pre>',print_r(list_allowed()),'</pre>';
|
||||||
|
});
|
||||||
|
|||||||
@@ -3,8 +3,11 @@ import.meta.glob([
|
|||||||
'../fonts/**',
|
'../fonts/**',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// import.meta.glob('../views/blocks/**/{style.scss,script.js,view.js}', { eager: true })
|
||||||
|
|
||||||
import Header from '../views/sections/header/header.js';
|
import Header from '../views/sections/header/header.js';
|
||||||
import LazyLoad from './lib/Lazy.js';
|
import LazyLoad from './lib/Lazy.js';
|
||||||
|
|
||||||
LazyLoad();
|
LazyLoad();
|
||||||
Header();
|
Header();
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import domReady from '@wordpress/dom-ready';
|
import domReady from '@wordpress/dom-ready';
|
||||||
import blockWhitelist from '../json/core-block-whitelist.json';
|
import blockWhitelist from '../json/core-block-whitelist.json';
|
||||||
|
import.meta.glob('../views/blocks/**/{index.jsx,index.js}', { eager: true })
|
||||||
|
|
||||||
domReady(() => {
|
domReady(() => {
|
||||||
const TEXT_EDITOR_BLOCKS = [
|
const TEXT_EDITOR_BLOCKS = [
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ class Editor
|
|||||||
|
|
||||||
$data = array_merge($data, $block);
|
$data = array_merge($data, $block);
|
||||||
$data['section_classes'] = $CssClasses->section($data);
|
$data['section_classes'] = $CssClasses->section($data);
|
||||||
$data['allowed_blocks'] = \App\block_whitelist();
|
$data['allowed_blocks'] = \App\Blocks\list_inner();
|
||||||
$data['template'] = $this->default_template();
|
$data['template'] = $this->default_template();
|
||||||
$data['block'] = $block;
|
$data['block'] = $block;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"name": "badegg/acfdemo",
|
||||||
|
"title": "ACF Demo",
|
||||||
|
"category": "badegg",
|
||||||
|
"icon": "media-document",
|
||||||
|
"description": "An example block powered by ACF",
|
||||||
|
"keywords": ["acf", "demo"],
|
||||||
|
|
||||||
|
"editorScript": "acfdemo-editor-script",
|
||||||
|
"editorStyle": "acfdemo-editor-style",
|
||||||
|
"script": "acfdemo-script",
|
||||||
|
"style": "acfdemo-style",
|
||||||
|
"viewScript": "acfdemo-view-script",
|
||||||
|
|
||||||
|
"acf": {
|
||||||
|
"mode": "preview",
|
||||||
|
"validate": "false",
|
||||||
|
"renderCallback": "\\App\\Blocks\\render_acf"
|
||||||
|
},
|
||||||
|
"supports": {
|
||||||
|
"anchor": true,
|
||||||
|
"align": false,
|
||||||
|
"jsx": true
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"attributes": {
|
||||||
|
"mode": "preview",
|
||||||
|
"data": {
|
||||||
|
"inserter": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// block.json's editorStyle, applied in block editor and front end
|
||||||
|
.wp-block-acf-demo.block-editor-block-list__block {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
// block.json's editorScript, loaded only in the block editor
|
||||||
|
console.log('loaded: resources/views/blocks/acfdemo/index.js')
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<section class="wp-block-{{ $block['slug'] }}">
|
||||||
|
<h2>ACF Example</h2>
|
||||||
|
</section>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
// block.json's script, loaded in block editor and front end
|
||||||
|
console.log('loaded: resources/views/blocks/acf-demo/script.js')
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// block.json's style, applied in block editor and front end
|
||||||
|
.wp-block-acf-demo {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
// block.json's viewScript, applied on front end only
|
||||||
|
console.log('loaded: resources/views/blocks/acf-demo/view.js')
|
||||||
@@ -3,8 +3,17 @@
|
|||||||
"name": "badegg/article",
|
"name": "badegg/article",
|
||||||
"title": "Article Builder",
|
"title": "Article Builder",
|
||||||
"category": "badegg",
|
"category": "badegg",
|
||||||
|
"icon": {
|
||||||
|
"src": "format-aside",
|
||||||
|
"foreground": "#f58762"
|
||||||
|
},
|
||||||
"description": "A wrapper to contain core blocks",
|
"description": "A wrapper to contain core blocks",
|
||||||
"editorScript": "article-editor-script",
|
"supports": {
|
||||||
"editorStyle": "article-editor-style",
|
"html": true,
|
||||||
"style": "article-style"
|
"align": ["wide", "full"],
|
||||||
|
"color": {
|
||||||
|
"background": true,
|
||||||
|
"text": false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
.block-badegg-example-editor {
|
// block.json's editorStyle, applied in block editor and front end
|
||||||
|
.wp-block-badegg-article.block-editor-block-list__block {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
|
// block.json's editorScript, loaded only in the block editor
|
||||||
|
|
||||||
import { registerBlockType } from '@wordpress/blocks';
|
import { registerBlockType } from '@wordpress/blocks';
|
||||||
import { InnerBlocks, useBlockProps } from '@wordpress/block-editor';
|
import { InnerBlocks, useBlockProps } from '@wordpress/block-editor';
|
||||||
import metadata from './block.json';
|
import metadata from './block.json';
|
||||||
import allowedBlocks from '../../../json/core-block-whitelist.json';
|
import allowedBlocks from '../../../json/core-block-whitelist.json';
|
||||||
|
|
||||||
registerBlockType(metadata.name, {
|
registerBlockType(metadata.name, {
|
||||||
icon: {
|
|
||||||
src: 'format-aside',
|
|
||||||
foreground: '#f58762',
|
|
||||||
},
|
|
||||||
edit({ attributes, setAttributes }) {
|
edit({ attributes, setAttributes }) {
|
||||||
const blockProps = useBlockProps();
|
const blockProps = useBlockProps();
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
<section class="block-badegg-article">
|
|
||||||
<h2>Bad Egg Article Block (Blade)</h2>
|
|
||||||
</section>
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
// block.json's script, loaded in block editor and front end
|
||||||
|
console.log('loaded: resources/views/blocks/article/script.js')
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
.block-badegg-hero {
|
// block.json's style, applied in block editor and front end
|
||||||
|
.wp-block-badegg-article {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
// block.json's viewScript, applied on front end only
|
||||||
|
console.log('loaded: resources/views/blocks/article/view.js')
|
||||||
@@ -4,9 +4,12 @@
|
|||||||
"title": "Example",
|
"title": "Example",
|
||||||
"category": "badegg",
|
"category": "badegg",
|
||||||
"icon": "cover-image",
|
"icon": "cover-image",
|
||||||
"description": "This is an example of a custom Wordpress Block created using the offical method.",
|
"description": "This is an example of a custom native block",
|
||||||
"editorScript": "example-editor-script",
|
"editorScript": "example-editor-script",
|
||||||
"editorStyle": "example-editor-style",
|
"editorStyle": "example-editor-style",
|
||||||
"style": "example-style",
|
"style": "example-style",
|
||||||
"render": "resources/blocks/example/render.blade.php"
|
"script": "example-script",
|
||||||
|
"supports": {
|
||||||
|
"html": false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
.block-badegg-example-editor {
|
// block.json's editorStyle, applied in block editor and front end
|
||||||
|
.wp-block-badegg-example.block-editor-block-list__block {
|
||||||
display: block;
|
display: block;
|
||||||
|
border: 2px solid red;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
import { registerBlockType } from '@wordpress/blocks';
|
// block.json's editorScript, loaded only in the block editor
|
||||||
|
|
||||||
registerBlockType('badegg/example', {
|
import { registerBlockType } from '@wordpress/blocks';
|
||||||
|
import { useBlockProps } from '@wordpress/block-editor';
|
||||||
|
import metadata from './block.json';
|
||||||
|
|
||||||
|
registerBlockType(metadata.name, {
|
||||||
edit() {
|
edit() {
|
||||||
|
const blockProps = useBlockProps();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="block-badegg-example">
|
<section { ...blockProps }>
|
||||||
<h2>Bad Egg Block Example</h2>
|
<h2>Bad Egg Block Example</h2>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
// block.json's script, loaded in block editor and front end
|
||||||
|
console.log('loaded: resources/views/blocks/example/script.js')
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
.block-badegg-hero {
|
// block.json's style, applied in block editor and front end
|
||||||
|
.wp-block-badegg-example {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
// block.json's viewScript, applied on front end only
|
||||||
|
console.log('loaded: resources/views/blocks/example/view.js')
|
||||||
@@ -1,21 +1,49 @@
|
|||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import laravel from 'laravel-vite-plugin'
|
import laravel from 'laravel-vite-plugin'
|
||||||
import { wordpressPlugin, wordpressThemeJson } from '@roots/vite-plugin';
|
import { wordpressPlugin, wordpressThemeJson } from '@roots/vite-plugin';
|
||||||
import fg from 'fast-glob'
|
import fg from 'fast-glob';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
const blockEntries = fg.sync('resources/views/blocks/**/{index.jsx,style.scss,editor.js,editor.scss}')
|
function blockAsset(file)
|
||||||
|
{
|
||||||
|
const files = fg.sync('resources/views/blocks/**/' + file);
|
||||||
|
let list = {};
|
||||||
|
|
||||||
|
files.forEach(file => {
|
||||||
|
const parts = file.split(path.sep);
|
||||||
|
const fileName = parts[parts.length - 1];
|
||||||
|
const extension = fileName.split('.').pop();
|
||||||
|
const blockName = parts[parts.length - 2];
|
||||||
|
|
||||||
|
list[`blocks/${blockName}/${fileName.replace('.' + extension, '')}`] = `resources/views/blocks/${blockName}/${fileName}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
const editorStyle = blockAsset('editor.scss');
|
||||||
|
const script = blockAsset('script.js');
|
||||||
|
const viewScript = blockAsset('view.js');
|
||||||
|
const style = blockAsset('style.scss');
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
base: '/app/themes/badegg/public/build/',
|
base: '/app/themes/badegg/public/build/',
|
||||||
plugins: [
|
plugins: [
|
||||||
laravel({
|
laravel({
|
||||||
input: [
|
input: {
|
||||||
'resources/css/app.scss',
|
// 'resources/css/app.scss',
|
||||||
'resources/js/app.js',
|
// 'resources/js/app.js',
|
||||||
'resources/css/editor.scss',
|
// 'resources/css/editor.scss',
|
||||||
'resources/js/editor.js',
|
// 'resources/js/editor.js',
|
||||||
...blockEntries,
|
'css/app': 'resources/css/app.scss',
|
||||||
],
|
'js/app': 'resources/js/app.js',
|
||||||
|
'css/editor': 'resources/css/editor.scss',
|
||||||
|
'js/editor': 'resources/js/editor.js',
|
||||||
|
...editorStyle,
|
||||||
|
...viewScript,
|
||||||
|
...script,
|
||||||
|
...style,
|
||||||
|
},
|
||||||
refresh: true,
|
refresh: true,
|
||||||
url: process.env.APP_URL,
|
url: process.env.APP_URL,
|
||||||
}),
|
}),
|
||||||
|
|||||||
Reference in New Issue
Block a user