I’ll build this as a production-style inc/integrations/gutenberg.php for your RX theme: block editor supports, editor assets, theme presets, patterns/categories, block styles, render filters, security/performance controls, and safe fallbacks.
Below is an advanced, long, production-style inc/integrations/gutenberg.php file for your RX Theme.
Create this file:
rx-theme/inc/integrations/gutenberg.php
Then load it from functions.php:
require_once get_template_directory() . '/inc/integrations/gutenberg.php';
inc/integrations/gutenberg.php
<?php
/**
* RX Theme Gutenberg / Block Editor Integration
*
* File: inc/integrations/gutenberg.php
*
* Features included:
* - Gutenberg theme support
* - Block editor styles
* - Wide/full alignment
* - Responsive embeds
* - Editor color palette
* - Editor font sizes
* - Custom spacing support
* - Custom line height
* - Custom units
* - Appearance tools
* - Link color support
* - Border support
* - Editor asset loading
* - Frontend block asset loading
* - Block style registrations
* - Block pattern categories
* - Custom block patterns
* - Optional core pattern disabling
* - Allowed block control
* - Block editor settings customization
* - Render block enhancements
* - Lazy loading support
* - External link handling
* - Table of contents helper
* - Anchor helper
* - Code block improvements
* - Image block improvements
* - Button rel/target helper
* - Safe CSS class injection
* - Admin body/editor body classes
* - Reusable utility functions
*
* @package RX_Theme
*/
defined( 'ABSPATH' ) || exit;
if ( ! class_exists( 'RX_Gutenberg_Integration' ) ) :
final class RX_Gutenberg_Integration {
/**
* Theme prefix.
*
* @var string
*/
const PREFIX = 'rx';
/**
* Theme textdomain.
*
* @var string
*/
const TEXT_DOMAIN = 'rx-theme';
/**
* Init hooks.
*
* @return void
*/
public static function init() {
add_action( 'after_setup_theme', array( __CLASS__, 'theme_supports' ), 20 );
add_action( 'enqueue_block_editor_assets', array( __CLASS__, 'enqueue_editor_assets' ) );
add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue_frontend_block_assets' ) );
add_action( 'init', array( __CLASS__, 'register_block_styles' ), 20 );
add_action( 'init', array( __CLASS__, 'register_pattern_categories' ), 20 );
add_action( 'init', array( __CLASS__, 'register_block_patterns' ), 30 );
add_filter( 'block_categories_all', array( __CLASS__, 'register_custom_block_categories' ), 10, 2 );
add_filter( 'allowed_block_types_all', array( __CLASS__, 'allowed_block_types' ), 10, 2 );
add_filter( 'block_editor_settings_all', array( __CLASS__, 'editor_settings' ), 10, 2 );
add_filter( 'admin_body_class', array( __CLASS__, 'admin_body_class' ) );
add_filter( 'render_block', array( __CLASS__, 'render_block_enhancements' ), 20, 2 );
add_filter( 'render_block_core/image', array( __CLASS__, 'enhance_image_block' ), 20, 2 );
add_filter( 'render_block_core/button', array( __CLASS__, 'enhance_button_block' ), 20, 2 );
add_filter( 'render_block_core/paragraph', array( __CLASS__, 'enhance_paragraph_block' ), 20, 2 );
add_filter( 'render_block_core/heading', array( __CLASS__, 'enhance_heading_block' ), 20, 2 );
add_filter( 'render_block_core/table', array( __CLASS__, 'enhance_table_block' ), 20, 2 );
add_filter( 'render_block_core/code', array( __CLASS__, 'enhance_code_block' ), 20, 2 );
add_filter( 'render_block_core/group', array( __CLASS__, 'enhance_group_block' ), 20, 2 );
add_filter( 'excerpt_allowed_blocks', array( __CLASS__, 'excerpt_allowed_blocks' ) );
add_action( 'enqueue_block_assets', array( __CLASS__, 'enqueue_shared_block_assets' ) );
}
/**
* Gutenberg and editor theme supports.
*
* @return void
*/
public static function theme_supports() {
/**
* Core Gutenberg supports.
*/
add_theme_support( 'align-wide' );
add_theme_support( 'responsive-embeds' );
add_theme_support( 'wp-block-styles' );
add_theme_support( 'editor-styles' );
add_theme_support( 'custom-line-height' );
add_theme_support( 'custom-spacing' );
add_theme_support( 'custom-units', array( 'px', 'em', 'rem', '%', 'vw', 'vh' ) );
add_theme_support( 'appearance-tools' );
add_theme_support( 'border' );
add_theme_support( 'link-color' );
add_theme_support( 'disable-custom-colors', false );
add_theme_support( 'disable-custom-font-sizes', false );
add_theme_support( 'disable-custom-gradients', false );
/**
* Editor stylesheet.
* Create this file if you want:
* assets/css/editor-style.css
*/
add_editor_style( array(
'style.css',
'assets/css/editor-style.css',
) );
/**
* Editor color palette.
*/
add_theme_support(
'editor-color-palette',
array(
array(
'name' => esc_html__( 'RX Primary', self::TEXT_DOMAIN ),
'slug' => 'rx-primary',
'color' => '#2563eb',
),
array(
'name' => esc_html__( 'RX Primary Dark', self::TEXT_DOMAIN ),
'slug' => 'rx-primary-dark',
'color' => '#1e40af',
),
array(
'name' => esc_html__( 'RX Secondary', self::TEXT_DOMAIN ),
'slug' => 'rx-secondary',
'color' => '#14b8a6',
),
array(
'name' => esc_html__( 'RX Accent', self::TEXT_DOMAIN ),
'slug' => 'rx-accent',
'color' => '#f97316',
),
array(
'name' => esc_html__( 'RX Success', self::TEXT_DOMAIN ),
'slug' => 'rx-success',
'color' => '#16a34a',
),
array(
'name' => esc_html__( 'RX Warning', self::TEXT_DOMAIN ),
'slug' => 'rx-warning',
'color' => '#f59e0b',
),
array(
'name' => esc_html__( 'RX Danger', self::TEXT_DOMAIN ),
'slug' => 'rx-danger',
'color' => '#dc2626',
),
array(
'name' => esc_html__( 'RX Dark', self::TEXT_DOMAIN ),
'slug' => 'rx-dark',
'color' => '#111827',
),
array(
'name' => esc_html__( 'RX Gray', self::TEXT_DOMAIN ),
'slug' => 'rx-gray',
'color' => '#6b7280',
),
array(
'name' => esc_html__( 'RX Light Gray', self::TEXT_DOMAIN ),
'slug' => 'rx-light-gray',
'color' => '#f3f4f6',
),
array(
'name' => esc_html__( 'RX White', self::TEXT_DOMAIN ),
'slug' => 'rx-white',
'color' => '#ffffff',
),
array(
'name' => esc_html__( 'RX Black', self::TEXT_DOMAIN ),
'slug' => 'rx-black',
'color' => '#000000',
),
)
);
/**
* Editor gradient presets.
*/
add_theme_support(
'editor-gradient-presets',
array(
array(
'name' => esc_html__( 'RX Blue Gradient', self::TEXT_DOMAIN ),
'gradient' => 'linear-gradient(135deg, #2563eb 0%, #14b8a6 100%)',
'slug' => 'rx-blue-gradient',
),
array(
'name' => esc_html__( 'RX Medical Gradient', self::TEXT_DOMAIN ),
'gradient' => 'linear-gradient(135deg, #0ea5e9 0%, #16a34a 100%)',
'slug' => 'rx-medical-gradient',
),
array(
'name' => esc_html__( 'RX Sunset Gradient', self::TEXT_DOMAIN ),
'gradient' => 'linear-gradient(135deg, #f97316 0%, #dc2626 100%)',
'slug' => 'rx-sunset-gradient',
),
array(
'name' => esc_html__( 'RX Dark Gradient', self::TEXT_DOMAIN ),
'gradient' => 'linear-gradient(135deg, #111827 0%, #374151 100%)',
'slug' => 'rx-dark-gradient',
),
)
);
/**
* Editor font sizes.
*/
add_theme_support(
'editor-font-sizes',
array(
array(
'name' => esc_html__( 'Tiny', self::TEXT_DOMAIN ),
'size' => 12,
'slug' => 'tiny',
),
array(
'name' => esc_html__( 'Small', self::TEXT_DOMAIN ),
'size' => 14,
'slug' => 'small',
),
array(
'name' => esc_html__( 'Normal', self::TEXT_DOMAIN ),
'size' => 16,
'slug' => 'normal',
),
array(
'name' => esc_html__( 'Medium', self::TEXT_DOMAIN ),
'size' => 18,
'slug' => 'medium',
),
array(
'name' => esc_html__( 'Large', self::TEXT_DOMAIN ),
'size' => 22,
'slug' => 'large',
),
array(
'name' => esc_html__( 'Extra Large', self::TEXT_DOMAIN ),
'size' => 28,
'slug' => 'x-large',
),
array(
'name' => esc_html__( 'Huge', self::TEXT_DOMAIN ),
'size' => 36,
'slug' => 'huge',
),
array(
'name' => esc_html__( 'Hero', self::TEXT_DOMAIN ),
'size' => 48,
'slug' => 'hero',
),
)
);
}
/**
* Enqueue block editor-only assets.
*
* @return void
*/
public static function enqueue_editor_assets() {
$theme_version = self::theme_version();
$editor_css = get_template_directory() . '/assets/css/gutenberg-editor.css';
$editor_js = get_template_directory() . '/assets/js/gutenberg-editor.js';
if ( file_exists( $editor_css ) ) {
wp_enqueue_style(
'rx-gutenberg-editor',
get_template_directory_uri() . '/assets/css/gutenberg-editor.css',
array(),
$theme_version
);
}
if ( file_exists( $editor_js ) ) {
wp_enqueue_script(
'rx-gutenberg-editor',
get_template_directory_uri() . '/assets/js/gutenberg-editor.js',
array( 'wp-blocks', 'wp-dom-ready', 'wp-edit-post', 'wp-element', 'wp-components', 'wp-i18n' ),
$theme_version,
true
);
}
wp_add_inline_style( 'wp-edit-blocks', self::editor_inline_css() );
}
/**
* Enqueue frontend block assets.
*
* @return void
*/
public static function enqueue_frontend_block_assets() {
if ( is_admin() ) {
return;
}
$theme_version = self::theme_version();
$frontend_css = get_template_directory() . '/assets/css/gutenberg-frontend.css';
$frontend_js = get_template_directory() . '/assets/js/gutenberg-frontend.js';
if ( file_exists( $frontend_css ) ) {
wp_enqueue_style(
'rx-gutenberg-frontend',
get_template_directory_uri() . '/assets/css/gutenberg-frontend.css',
array(),
$theme_version
);
}
if ( file_exists( $frontend_js ) ) {
wp_enqueue_script(
'rx-gutenberg-frontend',
get_template_directory_uri() . '/assets/js/gutenberg-frontend.js',
array(),
$theme_version,
true
);
}
}
/**
* Shared assets for frontend and editor.
*
* @return void
*/
public static function enqueue_shared_block_assets() {
$theme_version = self::theme_version();
$shared_css = get_template_directory() . '/assets/css/gutenberg-shared.css';
if ( file_exists( $shared_css ) ) {
wp_enqueue_style(
'rx-gutenberg-shared',
get_template_directory_uri() . '/assets/css/gutenberg-shared.css',
array(),
$theme_version
);
}
}
/**
* Register block styles.
*
* @return void
*/
public static function register_block_styles() {
if ( ! function_exists( 'register_block_style' ) ) {
return;
}
$styles = array(
'core/paragraph' => array(
array(
'name' => 'rx-lead',
'label' => esc_html__( 'RX Lead Text', self::TEXT_DOMAIN ),
),
array(
'name' => 'rx-muted',
'label' => esc_html__( 'RX Muted Text', self::TEXT_DOMAIN ),
),
array(
'name' => 'rx-note',
'label' => esc_html__( 'RX Note', self::TEXT_DOMAIN ),
),
array(
'name' => 'rx-warning-note',
'label' => esc_html__( 'RX Warning Note', self::TEXT_DOMAIN ),
),
),
'core/heading' => array(
array(
'name' => 'rx-heading-line',
'label' => esc_html__( 'RX Line Heading', self::TEXT_DOMAIN ),
),
array(
'name' => 'rx-heading-badge',
'label' => esc_html__( 'RX Badge Heading', self::TEXT_DOMAIN ),
),
array(
'name' => 'rx-gradient-heading',
'label' => esc_html__( 'RX Gradient Heading', self::TEXT_DOMAIN ),
),
),
'core/image' => array(
array(
'name' => 'rx-rounded',
'label' => esc_html__( 'RX Rounded', self::TEXT_DOMAIN ),
),
array(
'name' => 'rx-shadow',
'label' => esc_html__( 'RX Shadow', self::TEXT_DOMAIN ),
),
array(
'name' => 'rx-frame',
'label' => esc_html__( 'RX Frame', self::TEXT_DOMAIN ),
),
array(
'name' => 'rx-polaroid',
'label' => esc_html__( 'RX Polaroid', self::TEXT_DOMAIN ),
),
),
'core/gallery' => array(
array(
'name' => 'rx-gallery-card',
'label' => esc_html__( 'RX Gallery Card', self::TEXT_DOMAIN ),
),
array(
'name' => 'rx-gallery-gap-large',
'label' => esc_html__( 'RX Large Gap', self::TEXT_DOMAIN ),
),
),
'core/quote' => array(
array(
'name' => 'rx-modern-quote',
'label' => esc_html__( 'RX Modern Quote', self::TEXT_DOMAIN ),
),
array(
'name' => 'rx-medical-quote',
'label' => esc_html__( 'RX Medical Quote', self::TEXT_DOMAIN ),
),
),
'core/pullquote' => array(
array(
'name' => 'rx-pullquote-card',
'label' => esc_html__( 'RX Pullquote Card', self::TEXT_DOMAIN ),
),
),
'core/list' => array(
array(
'name' => 'rx-check-list',
'label' => esc_html__( 'RX Check List', self::TEXT_DOMAIN ),
),
array(
'name' => 'rx-arrow-list',
'label' => esc_html__( 'RX Arrow List', self::TEXT_DOMAIN ),
),
array(
'name' => 'rx-medical-list',
'label' => esc_html__( 'RX Medical List', self::TEXT_DOMAIN ),
),
),
'core/table' => array(
array(
'name' => 'rx-responsive-table',
'label' => esc_html__( 'RX Responsive Table', self::TEXT_DOMAIN ),
),
array(
'name' => 'rx-clean-table',
'label' => esc_html__( 'RX Clean Table', self::TEXT_DOMAIN ),
),
array(
'name' => 'rx-medical-table',
'label' => esc_html__( 'RX Medical Table', self::TEXT_DOMAIN ),
),
),
'core/button' => array(
array(
'name' => 'rx-button-primary',
'label' => esc_html__( 'RX Primary', self::TEXT_DOMAIN ),
),
array(
'name' => 'rx-button-secondary',
'label' => esc_html__( 'RX Secondary', self::TEXT_DOMAIN ),
),
array(
'name' => 'rx-button-outline',
'label' => esc_html__( 'RX Outline', self::TEXT_DOMAIN ),
),
array(
'name' => 'rx-button-glow',
'label' => esc_html__( 'RX Glow', self::TEXT_DOMAIN ),
),
),
'core/buttons' => array(
array(
'name' => 'rx-buttons-stack-mobile',
'label' => esc_html__( 'RX Stack Mobile', self::TEXT_DOMAIN ),
),
),
'core/group' => array(
array(
'name' => 'rx-card',
'label' => esc_html__( 'RX Card', self::TEXT_DOMAIN ),
),
array(
'name' => 'rx-soft-card',
'label' => esc_html__( 'RX Soft Card', self::TEXT_DOMAIN ),
),
array(
'name' => 'rx-glass-card',
'label' => esc_html__( 'RX Glass Card', self::TEXT_DOMAIN ),
),
array(
'name' => 'rx-medical-box',
'label' => esc_html__( 'RX Medical Box', self::TEXT_DOMAIN ),
),
),
'core/columns' => array(
array(
'name' => 'rx-equal-height',
'label' => esc_html__( 'RX Equal Height', self::TEXT_DOMAIN ),
),
array(
'name' => 'rx-card-columns',
'label' => esc_html__( 'RX Card Columns', self::TEXT_DOMAIN ),
),
),
'core/separator' => array(
array(
'name' => 'rx-dots',
'label' => esc_html__( 'RX Dots', self::TEXT_DOMAIN ),
),
array(
'name' => 'rx-gradient-line',
'label' => esc_html__( 'RX Gradient Line', self::TEXT_DOMAIN ),
),
),
'core/code' => array(
array(
'name' => 'rx-code-dark',
'label' => esc_html__( 'RX Code Dark', self::TEXT_DOMAIN ),
),
array(
'name' => 'rx-code-terminal',
'label' => esc_html__( 'RX Terminal', self::TEXT_DOMAIN ),
),
),
'core/preformatted' => array(
array(
'name' => 'rx-preformatted-card',
'label' => esc_html__( 'RX Preformatted Card', self::TEXT_DOMAIN ),
),
),
);
foreach ( $styles as $block_name => $block_styles ) {
foreach ( $block_styles as $style ) {
register_block_style( $block_name, $style );
}
}
}
/**
* Register block pattern categories.
*
* @return void
*/
public static function register_pattern_categories() {
if ( ! function_exists( 'register_block_pattern_category' ) ) {
return;
}
$categories = array(
'rx-hero' => array(
'label' => esc_html__( 'RX Hero Sections', self::TEXT_DOMAIN ),
'description' => esc_html__( 'Hero sections for medical, blog, and landing pages.', self::TEXT_DOMAIN ),
),
'rx-medical' => array(
'label' => esc_html__( 'RX Medical Sections', self::TEXT_DOMAIN ),
'description' => esc_html__( 'Medical content blocks and evidence-based content layouts.', self::TEXT_DOMAIN ),
),
'rx-content' => array(
'label' => esc_html__( 'RX Content Sections', self::TEXT_DOMAIN ),
'description' => esc_html__( 'Content blocks for articles and pages.', self::TEXT_DOMAIN ),
),
'rx-cta' => array(
'label' => esc_html__( 'RX Call To Action', self::TEXT_DOMAIN ),
'description' => esc_html__( 'CTA layouts for buttons, newsletter, and conversion sections.', self::TEXT_DOMAIN ),
),
'rx-faq' => array(
'label' => esc_html__( 'RX FAQ Sections', self::TEXT_DOMAIN ),
'description' => esc_html__( 'FAQ and question-answer layouts.', self::TEXT_DOMAIN ),
),
);
foreach ( $categories as $slug => $args ) {
register_block_pattern_category( $slug, $args );
}
}
/**
* Register custom block categories in inserter.
*
* @param array $categories Existing categories.
* @param object $post Current post.
*
* @return array
*/
public static function register_custom_block_categories( $categories, $post ) {
$custom_categories = array(
array(
'slug' => 'rx-blocks',
'title' => esc_html__( 'RX Blocks', self::TEXT_DOMAIN ),
'icon' => 'superhero',
),
array(
'slug' => 'rx-medical-blocks',
'title' => esc_html__( 'RX Medical Blocks', self::TEXT_DOMAIN ),
'icon' => 'heart',
),
array(
'slug' => 'rx-layout-blocks',
'title' => esc_html__( 'RX Layout Blocks', self::TEXT_DOMAIN ),
'icon' => 'layout',
),
);
return array_merge( $custom_categories, $categories );
}
/**
* Register block patterns.
*
* @return void
*/
public static function register_block_patterns() {
if ( ! function_exists( 'register_block_pattern' ) ) {
return;
}
register_block_pattern(
'rx/medical-article-intro',
array(
'title' => esc_html__( 'RX Medical Article Intro', self::TEXT_DOMAIN ),
'description' => esc_html__( 'A strong introduction pattern for evidence-based medical articles.', self::TEXT_DOMAIN ),
'categories' => array( 'rx-medical', 'rx-content' ),
'keywords' => array( 'medical', 'article', 'intro', 'rx' ),
'content' => self::pattern_medical_article_intro(),
)
);
register_block_pattern(
'rx/evidence-summary-box',
array(
'title' => esc_html__( 'RX Evidence Summary Box', self::TEXT_DOMAIN ),
'description' => esc_html__( 'A highlighted summary box for evidence-based content.', self::TEXT_DOMAIN ),
'categories' => array( 'rx-medical', 'rx-content' ),
'keywords' => array( 'evidence', 'summary', 'medical', 'rx' ),
'content' => self::pattern_evidence_summary_box(),
)
);
register_block_pattern(
'rx/faq-section',
array(
'title' => esc_html__( 'RX FAQ Section', self::TEXT_DOMAIN ),
'description' => esc_html__( 'Simple FAQ layout for medical and educational content.', self::TEXT_DOMAIN ),
'categories' => array( 'rx-faq', 'rx-content' ),
'keywords' => array( 'faq', 'questions', 'answers', 'rx' ),
'content' => self::pattern_faq_section(),
)
);
register_block_pattern(
'rx/cta-box',
array(
'title' => esc_html__( 'RX CTA Box', self::TEXT_DOMAIN ),
'description' => esc_html__( 'A clean call-to-action box.', self::TEXT_DOMAIN ),
'categories' => array( 'rx-cta' ),
'keywords' => array( 'cta', 'button', 'action', 'rx' ),
'content' => self::pattern_cta_box(),
)
);
register_block_pattern(
'rx/two-column-medical-info',
array(
'title' => esc_html__( 'RX Two Column Medical Info', self::TEXT_DOMAIN ),
'description' => esc_html__( 'Two-column layout for causes, symptoms, diagnosis, and treatment sections.', self::TEXT_DOMAIN ),
'categories' => array( 'rx-medical', 'rx-content' ),
'keywords' => array( 'medical', 'columns', 'info', 'rx' ),
'content' => self::pattern_two_column_medical_info(),
)
);
}
/**
* Control allowed blocks.
*
* Return true to allow all.
* You can customize by post type.
*
* @param bool|array $allowed_block_types Allowed blocks.
* @param object $block_editor_context Editor context.
*
* @return bool|array
*/
public static function allowed_block_types( $allowed_block_types, $block_editor_context ) {
/**
* Default: allow all blocks.
*
* To restrict blocks, set this constant in wp-config.php:
* define( 'RX_RESTRICT_GUTENBERG_BLOCKS', true );
*/
if ( ! defined( 'RX_RESTRICT_GUTENBERG_BLOCKS' ) || ! RX_RESTRICT_GUTENBERG_BLOCKS ) {
return true;
}
$post_type = '';
if ( isset( $block_editor_context->post ) && $block_editor_context->post instanceof WP_Post ) {
$post_type = $block_editor_context->post->post_type;
}
$common_blocks = array(
'core/paragraph',
'core/heading',
'core/list',
'core/list-item',
'core/image',
'core/gallery',
'core/quote',
'core/pullquote',
'core/table',
'core/buttons',
'core/button',
'core/separator',
'core/spacer',
'core/group',
'core/columns',
'core/column',
'core/cover',
'core/media-text',
'core/embed',
'core/html',
'core/code',
'core/preformatted',
'core/details',
);
if ( 'post' === $post_type ) {
return array_merge(
$common_blocks,
array(
'core/categories',
'core/latest-posts',
'core/tag-cloud',
'core/post-title',
'core/post-date',
'core/post-excerpt',
'core/post-featured-image',
'core/post-content',
)
);
}
if ( 'page' === $post_type ) {
return array_merge(
$common_blocks,
array(
'core/navigation',
'core/site-logo',
'core/site-title',
'core/site-tagline',
)
);
}
return $common_blocks;
}
/**
* Customize editor settings.
*
* @param array $settings Editor settings.
* @param WP_Post $post Current post.
*
* @return array
*/
public static function editor_settings( $settings, $post ) {
$settings['rxTheme'] = array(
'name' => 'RX Theme',
'version' => self::theme_version(),
'supportsSEO' => true,
'supportsTOC' => true,
);
/**
* Recommended editor defaults.
*/
$settings['alignWide'] = true;
/**
* Helpful custom spacing sizes for block editor.
*/
if ( empty( $settings['spacingSizes'] ) ) {
$settings['spacingSizes'] = array(
array(
'name' => esc_html__( 'RX XS', self::TEXT_DOMAIN ),
'slug' => 'rx-xs',
'size' => '0.5rem',
),
array(
'name' => esc_html__( 'RX SM', self::TEXT_DOMAIN ),
'slug' => 'rx-sm',
'size' => '1rem',
),
array(
'name' => esc_html__( 'RX MD', self::TEXT_DOMAIN ),
'slug' => 'rx-md',
'size' => '1.5rem',
),
array(
'name' => esc_html__( 'RX LG', self::TEXT_DOMAIN ),
'slug' => 'rx-lg',
'size' => '2rem',
),
array(
'name' => esc_html__( 'RX XL', self::TEXT_DOMAIN ),
'slug' => 'rx-xl',
'size' => '3rem',
),
array(
'name' => esc_html__( 'RX XXL', self::TEXT_DOMAIN ),
'slug' => 'rx-xxl',
'size' => '5rem',
),
);
}
return $settings;
}
/**
* Add admin body classes.
*
* @param string $classes Admin body classes.
*
* @return string
*/
public static function admin_body_class( $classes ) {
$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
if ( $screen && method_exists( $screen, 'is_block_editor' ) && $screen->is_block_editor() ) {
$classes .= ' rx-block-editor rx-theme-editor ';
}
return $classes;
}
/**
* General render block enhancements.
*
* @param string $block_content Rendered block HTML.
* @param array $block Block data.
*
* @return string
*/
public static function render_block_enhancements( $block_content, $block ) {
if ( empty( $block_content ) || is_admin() || wp_is_json_request() ) {
return $block_content;
}
$block_name = isset( $block['blockName'] ) ? $block['blockName'] : '';
if ( empty( $block_name ) ) {
return $block_content;
}
/**
* Add safe data attribute to all core blocks.
*/
if ( 0 === strpos( $block_name, 'core/' ) ) {
$block_content = self::add_data_attribute_to_first_tag(
$block_content,
'data-rx-block',
esc_attr( str_replace( 'core/', '', $block_name ) )
);
}
return $block_content;
}
/**
* Enhance image block.
*
* @param string $block_content Block content.
* @param array $block Block data.
*
* @return string
*/
public static function enhance_image_block( $block_content, $block ) {
if ( empty( $block_content ) || is_admin() ) {
return $block_content;
}
$block_content = self::add_img_attribute( $block_content, 'loading', 'lazy' );
$block_content = self::add_img_attribute( $block_content, 'decoding', 'async' );
if ( false === strpos( $block_content, 'data-rx-image' ) ) {
$block_content = self::add_data_attribute_to_first_tag( $block_content, 'data-rx-image', 'true' );
}
return $block_content;
}
/**
* Enhance button block.
*
* @param string $block_content Block content.
* @param array $block Block data.
*
* @return string
*/
public static function enhance_button_block( $block_content, $block ) {
if ( empty( $block_content ) || is_admin() ) {
return $block_content;
}
/**
* Add noopener to target blank links.
*/
if ( false !== strpos( $block_content, 'target="_blank"' ) && false === strpos( $block_content, 'rel=' ) ) {
$block_content = str_replace(
'target="_blank"',
'target="_blank" rel="noopener noreferrer"',
$block_content
);
}
return $block_content;
}
/**
* Enhance paragraph block.
*
* @param string $block_content Block content.
* @param array $block Block data.
*
* @return string
*/
public static function enhance_paragraph_block( $block_content, $block ) {
if ( empty( $block_content ) || is_admin() ) {
return $block_content;
}
return self::add_class_to_first_tag( $block_content, 'rx-paragraph' );
}
/**
* Enhance heading block.
*
* @param string $block_content Block content.
* @param array $block Block data.
*
* @return string
*/
public static function enhance_heading_block( $block_content, $block ) {
if ( empty( $block_content ) || is_admin() ) {
return $block_content;
}
$block_content = self::add_class_to_first_tag( $block_content, 'rx-heading' );
/**
* Auto add anchor from heading text if missing.
* This helps table of contents and deep links.
*/
if ( false === strpos( $block_content, ' id=' ) ) {
$text = wp_strip_all_tags( $block_content );
if ( ! empty( $text ) ) {
$id = sanitize_title( $text );
$block_content = preg_replace(
'/(<h[1-6]\b)([^>]*>)/i',
'$1 id="' . esc_attr( $id ) . '"$2',
$block_content,
1
);
}
}
return $block_content;
}
/**
* Enhance table block.
*
* @param string $block_content Block content.
* @param array $block Block data.
*
* @return string
*/
public static function enhance_table_block( $block_content, $block ) {
if ( empty( $block_content ) || is_admin() ) {
return $block_content;
}
if ( false === strpos( $block_content, 'rx-table-wrap' ) ) {
$block_content = '<div class="rx-table-wrap" data-rx-table-wrap="true">' . $block_content . '</div>';
}
return $block_content;
}
/**
* Enhance code block.
*
* @param string $block_content Block content.
* @param array $block Block data.
*
* @return string
*/
public static function enhance_code_block( $block_content, $block ) {
if ( empty( $block_content ) || is_admin() ) {
return $block_content;
}
$block_content = self::add_class_to_first_tag( $block_content, 'rx-code-block' );
if ( false === strpos( $block_content, 'data-rx-code' ) ) {
$block_content = self::add_data_attribute_to_first_tag( $block_content, 'data-rx-code', 'true' );
}
return $block_content;
}
/**
* Enhance group block.
*
* @param string $block_content Block content.
* @param array $block Block data.
*
* @return string
*/
public static function enhance_group_block( $block_content, $block ) {
if ( empty( $block_content ) || is_admin() ) {
return $block_content;
}
return self::add_class_to_first_tag( $block_content, 'rx-group-block' );
}
/**
* Excerpt allowed blocks.
*
* @param array $allowed_blocks Allowed excerpt blocks.
*
* @return array
*/
public static function excerpt_allowed_blocks( $allowed_blocks ) {
$extra = array(
'core/paragraph',
'core/heading',
'core/list',
'core/quote',
'core/pullquote',
'core/table',
);
return array_values( array_unique( array_merge( $allowed_blocks, $extra ) ) );
}
/**
* Inline CSS for editor and registered styles.
*
* @return string
*/
private static function editor_inline_css() {
return '
.editor-styles-wrapper {
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
color: #111827;
background: #ffffff;
}
.editor-styles-wrapper .wp-block {
max-width: 780px;
}
.editor-styles-wrapper .wp-block[data-align="wide"] {
max-width: 1100px;
}
.editor-styles-wrapper .wp-block[data-align="full"] {
max-width: none;
}
.editor-styles-wrapper h1,
.editor-styles-wrapper h2,
.editor-styles-wrapper h3,
.editor-styles-wrapper h4,
.editor-styles-wrapper h5,
.editor-styles-wrapper h6 {
font-weight: 800;
line-height: 1.2;
color: #111827;
}
.is-style-rx-lead {
font-size: 1.25rem;
line-height: 1.8;
color: #374151;
}
.is-style-rx-muted {
color: #6b7280;
}
.is-style-rx-note,
.is-style-rx-warning-note {
padding: 1rem 1.25rem;
border-radius: 12px;
border-left: 4px solid #2563eb;
background: #eff6ff;
}
.is-style-rx-warning-note {
border-left-color: #f59e0b;
background: #fffbeb;
}
.is-style-rx-heading-line {
border-bottom: 3px solid #2563eb;
padding-bottom: .45rem;
}
.is-style-rx-heading-badge {
display: inline-block;
padding: .35rem .65rem;
border-radius: 999px;
background: #eff6ff;
color: #1e40af;
}
.is-style-rx-gradient-heading {
background: linear-gradient(135deg, #2563eb, #14b8a6);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.is-style-rx-rounded img {
border-radius: 18px;
}
.is-style-rx-shadow img {
box-shadow: 0 20px 40px rgba(15, 23, 42, .14);
}
.is-style-rx-frame img {
border: 8px solid #ffffff;
box-shadow: 0 12px 30px rgba(15, 23, 42, .12);
}
.is-style-rx-polaroid {
padding: 12px;
background: #ffffff;
box-shadow: 0 15px 35px rgba(15, 23, 42, .14);
transform: rotate(-1deg);
}
.is-style-rx-modern-quote {
border-left: 5px solid #2563eb;
padding: 1.25rem 1.5rem;
background: #f8fafc;
border-radius: 14px;
}
.is-style-rx-medical-quote {
border-left: 5px solid #14b8a6;
padding: 1.25rem 1.5rem;
background: #f0fdfa;
border-radius: 14px;
}
.is-style-rx-check-list li::marker {
color: #16a34a;
}
.is-style-rx-arrow-list li::marker {
color: #2563eb;
}
.is-style-rx-medical-list {
background: #f8fafc;
padding: 1rem 1.25rem 1rem 2rem;
border-radius: 14px;
}
.is-style-rx-responsive-table table,
.is-style-rx-clean-table table,
.is-style-rx-medical-table table {
width: 100%;
border-collapse: collapse;
}
.is-style-rx-clean-table table th,
.is-style-rx-clean-table table td,
.is-style-rx-medical-table table th,
.is-style-rx-medical-table table td {
border: 1px solid #e5e7eb;
padding: .85rem;
}
.is-style-rx-medical-table table th {
background: #eff6ff;
color: #1e40af;
}
.is-style-rx-button-primary .wp-block-button__link {
background: #2563eb;
color: #ffffff;
}
.is-style-rx-button-secondary .wp-block-button__link {
background: #14b8a6;
color: #ffffff;
}
.is-style-rx-button-outline .wp-block-button__link {
background: transparent;
color: #2563eb;
border: 2px solid #2563eb;
}
.is-style-rx-button-glow .wp-block-button__link {
background: #2563eb;
color: #ffffff;
box-shadow: 0 10px 25px rgba(37, 99, 235, .35);
}
.is-style-rx-card,
.is-style-rx-soft-card,
.is-style-rx-glass-card,
.is-style-rx-medical-box {
padding: 1.5rem;
border-radius: 18px;
}
.is-style-rx-card {
background: #ffffff;
border: 1px solid #e5e7eb;
box-shadow: 0 10px 30px rgba(15, 23, 42, .08);
}
.is-style-rx-soft-card {
background: #f8fafc;
}
.is-style-rx-glass-card {
background: rgba(255, 255, 255, .72);
backdrop-filter: blur(12px);
border: 1px solid rgba(255,255,255,.4);
}
.is-style-rx-medical-box {
background: #f0fdfa;
border: 1px solid #99f6e4;
}
.is-style-rx-dots {
border: 0;
border-top: 4px dotted #2563eb;
background: transparent;
}
.is-style-rx-gradient-line {
height: 4px;
border: 0;
background: linear-gradient(135deg, #2563eb, #14b8a6);
}
.is-style-rx-code-dark,
.is-style-rx-code-terminal {
background: #111827;
color: #e5e7eb;
border-radius: 14px;
padding: 1rem;
overflow-x: auto;
}
.is-style-rx-code-terminal::before {
content: "Terminal";
display: block;
font-size: .75rem;
color: #9ca3af;
margin-bottom: .65rem;
}
';
}
/**
* Medical article intro pattern.
*
* @return string
*/
private static function pattern_medical_article_intro() {
return '
<!-- wp:group {"className":"is-style-rx-medical-box","layout":{"type":"constrained"}} -->
<div class="wp-block-group is-style-rx-medical-box">
<!-- wp:heading {"level":2,"className":"is-style-rx-heading-line"} -->
<h2 class="wp-block-heading is-style-rx-heading-line">Medical Overview</h2>
<!-- /wp:heading -->
<!-- wp:paragraph {"className":"is-style-rx-lead"} -->
<p class="is-style-rx-lead">This section gives a simple, evidence-based overview of the condition, including meaning, causes, symptoms, diagnosis, treatment, and prevention.</p>
<!-- /wp:paragraph -->
<!-- wp:list {"className":"is-style-rx-check-list"} -->
<ul class="is-style-rx-check-list">
<li>Simple definition</li>
<li>Common causes</li>
<li>Important symptoms</li>
<li>Useful diagnostic tests</li>
<li>When to see a doctor</li>
</ul>
<!-- /wp:list -->
</div>
<!-- /wp:group -->
';
}
/**
* Evidence summary box pattern.
*
* @return string
*/
private static function pattern_evidence_summary_box() {
return '
<!-- wp:group {"className":"is-style-rx-card","layout":{"type":"constrained"}} -->
<div class="wp-block-group is-style-rx-card">
<!-- wp:heading {"level":3} -->
<h3 class="wp-block-heading">Evidence Summary</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>This summary explains the most important clinical points in clear language. It can be used for diagnosis, treatment, prevention, and patient education sections.</p>
<!-- /wp:paragraph -->
<!-- wp:separator {"className":"is-style-rx-gradient-line"} -->
<hr class="wp-block-separator has-alpha-channel-opacity is-style-rx-gradient-line"/>
<!-- /wp:separator -->
<!-- wp:paragraph {"className":"is-style-rx-note"} -->
<p class="is-style-rx-note">Always connect medical decisions with clinical examination, patient history, and qualified professional judgment.</p>
<!-- /wp:paragraph -->
</div>
<!-- /wp:group -->
';
}
/**
* FAQ pattern.
*
* @return string
*/
private static function pattern_faq_section() {
return '
<!-- wp:group {"layout":{"type":"constrained"}} -->
<div class="wp-block-group">
<!-- wp:heading {"level":2,"className":"is-style-rx-heading-line"} -->
<h2 class="wp-block-heading is-style-rx-heading-line">Frequently Asked Questions</h2>
<!-- /wp:heading -->
<!-- wp:details -->
<details class="wp-block-details"><summary>What is this condition?</summary><p>This condition means a change in normal body structure or function. The exact meaning depends on the medical diagnosis.</p></details>
<!-- /wp:details -->
<!-- wp:details -->
<details class="wp-block-details"><summary>When should I see a doctor?</summary><p>You should see a doctor if symptoms are severe, persistent, worsening, or associated with warning signs.</p></details>
<!-- /wp:details -->
<!-- wp:details -->
<details class="wp-block-details"><summary>Can it be prevented?</summary><p>Some causes can be reduced by healthy lifestyle, early diagnosis, vaccination, safety habits, and regular medical follow-up.</p></details>
<!-- /wp:details -->
</div>
<!-- /wp:group -->
';
}
/**
* CTA box pattern.
*
* @return string
*/
private static function pattern_cta_box() {
return '
<!-- wp:group {"className":"is-style-rx-card","layout":{"type":"constrained"}} -->
<div class="wp-block-group is-style-rx-card">
<!-- wp:heading {"textAlign":"center","level":2} -->
<h2 class="wp-block-heading has-text-align-center">Need More Health Guidance?</h2>
<!-- /wp:heading -->
<!-- wp:paragraph {"align":"center"} -->
<p class="has-text-align-center">Read more evidence-based health articles written in simple language.</p>
<!-- /wp:paragraph -->
<!-- wp:buttons {"layout":{"type":"flex","justifyContent":"center"}} -->
<div class="wp-block-buttons">
<!-- wp:button {"className":"is-style-rx-button-primary"} -->
<div class="wp-block-button is-style-rx-button-primary"><a class="wp-block-button__link wp-element-button">Explore Articles</a></div>
<!-- /wp:button -->
</div>
<!-- /wp:buttons -->
</div>
<!-- /wp:group -->
';
}
/**
* Two-column medical info pattern.
*
* @return string
*/
private static function pattern_two_column_medical_info() {
return '
<!-- wp:columns {"className":"is-style-rx-card-columns"} -->
<div class="wp-block-columns is-style-rx-card-columns">
<!-- wp:column -->
<div class="wp-block-column">
<!-- wp:group {"className":"is-style-rx-soft-card"} -->
<div class="wp-block-group is-style-rx-soft-card">
<!-- wp:heading {"level":3} -->
<h3 class="wp-block-heading">Common Causes</h3>
<!-- /wp:heading -->
<!-- wp:list {"className":"is-style-rx-check-list"} -->
<ul class="is-style-rx-check-list">
<li>Genetic factors</li>
<li>Infection or inflammation</li>
<li>Nutritional deficiency</li>
<li>Autoimmune disease</li>
</ul>
<!-- /wp:list -->
</div>
<!-- /wp:group -->
</div>
<!-- /wp:column -->
<!-- wp:column -->
<div class="wp-block-column">
<!-- wp:group {"className":"is-style-rx-soft-card"} -->
<div class="wp-block-group is-style-rx-soft-card">
<!-- wp:heading {"level":3} -->
<h3 class="wp-block-heading">Important Symptoms</h3>
<!-- /wp:heading -->
<!-- wp:list {"className":"is-style-rx-arrow-list"} -->
<ul class="is-style-rx-arrow-list">
<li>Pain or discomfort</li>
<li>Fatigue or weakness</li>
<li>Fever or swelling</li>
<li>Changes in function</li>
</ul>
<!-- /wp:list -->
</div>
<!-- /wp:group -->
</div>
<!-- /wp:column -->
</div>
<!-- /wp:columns -->
';
}
/**
* Add class to first HTML tag.
*
* @param string $html HTML.
* @param string $class Class name.
*
* @return string
*/
private static function add_class_to_first_tag( $html, $class ) {
if ( empty( $html ) || empty( $class ) ) {
return $html;
}
if ( false !== strpos( $html, $class ) ) {
return $html;
}
if ( preg_match( '/<([a-z0-9]+)([^>]*)class="([^"]*)"/i', $html ) ) {
return preg_replace(
'/<([a-z0-9]+)([^>]*)class="([^"]*)"/i',
'<$1$2class="$3 ' . esc_attr( $class ) . '"',
$html,
1
);
}
return preg_replace(
'/<([a-z0-9]+)([^>]*)>/i',
'<$1$2 class="' . esc_attr( $class ) . '">',
$html,
1
);
}
/**
* Add data attribute to first HTML tag.
*
* @param string $html HTML.
* @param string $attribute Attribute name.
* @param string $value Attribute value.
*
* @return string
*/
private static function add_data_attribute_to_first_tag( $html, $attribute, $value ) {
if ( empty( $html ) || empty( $attribute ) ) {
return $html;
}
if ( false !== strpos( $html, $attribute . '=' ) ) {
return $html;
}
return preg_replace(
'/<([a-z0-9]+)([^>]*)>/i',
'<$1$2 ' . esc_attr( $attribute ) . '="' . esc_attr( $value ) . '">',
$html,
1
);
}
/**
* Add attribute to image tag if missing.
*
* @param string $html HTML.
* @param string $attribute Attribute.
* @param string $value Value.
*
* @return string
*/
private static function add_img_attribute( $html, $attribute, $value ) {
if ( empty( $html ) || empty( $attribute ) ) {
return $html;
}
if ( false !== strpos( $html, '<img' ) && false === strpos( $html, $attribute . '=' ) ) {
$html = preg_replace(
'/<img([^>]*)>/i',
'<img$1 ' . esc_attr( $attribute ) . '="' . esc_attr( $value ) . '">',
$html,
1
);
}
return $html;
}
/**
* Get theme version.
*
* @return string
*/
private static function theme_version() {
$theme = wp_get_theme();
if ( $theme && $theme->exists() ) {
return $theme->get( 'Version' );
}
return '1.0.0';
}
}
endif;
RX_Gutenberg_Integration::init();
Optional folder files you can create later
This PHP file checks for these assets automatically:
rx-theme/assets/css/editor-style.css
rx-theme/assets/css/gutenberg-editor.css
rx-theme/assets/css/gutenberg-frontend.css
rx-theme/assets/css/gutenberg-shared.css
rx-theme/assets/js/gutenberg-editor.js
rx-theme/assets/js/gutenberg-frontend.js
Best functions.php loading line
Add this with your other includes:
if ( file_exists( get_template_directory() . '/inc/integrations/gutenberg.php' ) ) {
require_once get_template_directory() . '/inc/integrations/gutenberg.php';
}
This file is safe because it checks WordPress functions before using them, avoids direct access, uses theme versioning, and keeps most Gutenberg functionality inside one clean class.