'mcb-block-editor',
'editor_style' => 'mcb-block-editor-style',
'render_callback' => array(__CLASS__, 'render_block'),
'attributes' => array(
'repository' => array(
'type' => 'string',
'default' => ''
),
'theme' => array(
'type' => 'string',
'default' => 'dark'
),
'height' => array(
'type' => 'string',
'default' => '600px'
),
'showLineNumbers' => array(
'type' => 'boolean',
'default' => true
),
'initialFile' => array(
'type' => 'string',
'default' => ''
),
'title' => array(
'type' => 'string',
'default' => ''
),
'align' => array(
'type' => 'string',
'default' => 'none'
),
'className' => array(
'type' => 'string',
'default' => ''
)
),
'supports' => array(
'align' => array('wide', 'full'),
'className' => true,
'customClassName' => true,
'html' => false,
'anchor' => true
),
'example' => array(
'attributes' => array(
'repository' => 'facebook/react',
'theme' => 'dark',
'height' => '400px',
'title' => 'React Source Code Example'
)
)
));
// Add block variations
wp_register_script(
'mcb-block-variations',
MCB_PLUGIN_URL . 'assets/js/block-variations.js',
array('wp-blocks', 'wp-dom-ready'),
MCB_PLUGIN_VERSION,
true
);
wp_enqueue_script('mcb-block-variations');
}
/**
* Render the block on the frontend
*/
public static function render_block($attributes, $content) {
// Validate required attributes
if (empty($attributes['repository'])) {
return '
Please specify a repository (e.g., owner/repository)
';
}
// Sanitize attributes
$repository = sanitize_text_field($attributes['repository']);
// Validate repository format
if (!MCB_Security::validate_repo_format($repository)) {
return 'Invalid repository format. Use: owner/repository
';
}
// Build shortcode attributes
$shortcode_atts = array(
'repo' => $repository,
'theme' => sanitize_text_field($attributes['theme'] ?? 'dark'),
'height' => sanitize_text_field($attributes['height'] ?? '600px'),
'show_line_numbers' => $attributes['showLineNumbers'] ? 'true' : 'false',
'initial_file' => sanitize_text_field($attributes['initialFile'] ?? ''),
'title' => sanitize_text_field($attributes['title'] ?? '')
);
// Add alignment class if needed
$wrapper_class = 'mcb-block-wrapper';
if (!empty($attributes['align'])) {
$wrapper_class .= ' align' . esc_attr($attributes['align']);
}
if (!empty($attributes['className'])) {
$wrapper_class .= ' ' . esc_attr($attributes['className']);
}
// Generate shortcode
$shortcode = '[maple_code_block';
foreach ($shortcode_atts as $key => $value) {
if (!empty($value)) {
$shortcode .= ' ' . $key . '="' . esc_attr($value) . '"';
}
}
$shortcode .= ']';
// Render with wrapper
return sprintf(
'%s
',
esc_attr($wrapper_class),
do_shortcode($shortcode)
);
}
/**
* Enqueue block editor assets
*/
public static function enqueue_block_editor_assets() {
// Debug log
error_log('MCB: Enqueueing block editor assets');
// Make sure our script is registered
if (!wp_script_is('mcb-block-editor', 'registered')) {
error_log('MCB: Script not registered, registering now');
wp_register_script(
'mcb-block-editor',
MCB_PLUGIN_URL . 'assets/js/block-editor.js',
array('wp-blocks', 'wp-element', 'wp-editor', 'wp-components', 'wp-i18n', 'wp-data'),
MCB_PLUGIN_VERSION,
true
);
}
// Localize script with data for the editor
wp_localize_script('mcb-block-editor', 'mcbBlockData', array(
'pluginUrl' => MCB_PLUGIN_URL,
'themes' => array(
array('label' => 'Dark', 'value' => 'dark'),
array('label' => 'Light', 'value' => 'light'),
array('label' => 'Monokai', 'value' => 'monokai'),
array('label' => 'Solarized', 'value' => 'solarized')
),
'defaultHeight' => '600px',
'popularRepos' => array(
'facebook/react',
'vuejs/vue',
'angular/angular',
'microsoft/vscode',
'torvalds/linux',
'tensorflow/tensorflow',
'kubernetes/kubernetes',
'nodejs/node',
'rust-lang/rust',
'golang/go'
),
'nonce' => wp_create_nonce('mcb_block_nonce')
));
}
/**
* Enqueue frontend block assets
*/
public static function enqueue_block_assets() {
// Only enqueue on frontend
if (!is_admin()) {
// These will be enqueued by the shortcode handler
// We just need to ensure the block wrapper styles are loaded
wp_enqueue_style(
'mcb-block-style',
MCB_PLUGIN_URL . 'assets/css/block-style.css',
array(),
MCB_PLUGIN_VERSION
);
}
}
/**
* Add custom block category
*/
public static function add_block_category($categories, $post) {
return array_merge(
array(
array(
'slug' => 'maple-code-blocks',
'title' => __('Maple Code Blocks', 'maple-code-blocks'),
'icon' => 'editor-code'
)
),
$categories
);
}
/**
* Register REST API endpoint for repository validation
*/
public static function register_rest_routes() {
register_rest_route('maple-code-blocks/v1', '/validate-repo', array(
'methods' => 'POST',
'callback' => array(__CLASS__, 'validate_repository'),
'permission_callback' => function() {
return current_user_can('edit_posts');
},
'args' => array(
'repository' => array(
'required' => true,
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field'
)
)
));
register_rest_route('maple-code-blocks/v1', '/get-files', array(
'methods' => 'POST',
'callback' => array(__CLASS__, 'get_repository_files'),
'permission_callback' => function() {
return current_user_can('edit_posts');
},
'args' => array(
'repository' => array(
'required' => true,
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field'
)
)
));
}
/**
* Validate repository via REST API
*/
public static function validate_repository($request) {
$repository = $request->get_param('repository');
// Validate format
if (!MCB_Security::validate_repo_format($repository)) {
return new WP_Error('invalid_format', 'Invalid repository format. Use: owner/repository');
}
// Quick check with GitHub API
$github_api = new MCB_GitHub_API();
$result = $github_api->validate_repository_exists($repository);
if (is_wp_error($result)) {
return $result;
}
return array(
'valid' => true,
'repository' => $repository
);
}
/**
* Get repository files for block editor preview
*/
public static function get_repository_files($request) {
$repository = $request->get_param('repository');
// Validate format
if (!MCB_Security::validate_repo_format($repository)) {
return new WP_Error('invalid_format', 'Invalid repository format');
}
$github_api = new MCB_GitHub_API();
$files = $github_api->get_repository_files($repository);
if (is_wp_error($files)) {
return $files;
}
// Return only file names for the editor
$file_list = array_map(function($file) {
return array(
'path' => $file['path'],
'name' => $file['name']
);
}, array_slice($files, 0, 10)); // Limit to 10 files for preview
return array(
'files' => $file_list,
'total' => count($files)
);
}
}
// Initialize block editor support
add_action('init', array('MCB_Block_Editor', 'init'));
add_action('rest_api_init', array('MCB_Block_Editor', 'register_rest_routes'));