190 lines
9.5 KiB
PHP
190 lines
9.5 KiB
PHP
<?php
|
|
/**
|
|
* Shortcode Handler Class
|
|
* Manages the [github_code_viewer] shortcode
|
|
*/
|
|
|
|
// Prevent direct access
|
|
if (!defined('WPINC')) {
|
|
die('Direct access not permitted.');
|
|
}
|
|
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
class MCB_Shortcode {
|
|
|
|
/**
|
|
* Initialize shortcode
|
|
*/
|
|
public static function init() {
|
|
add_shortcode('maple_code_block', array(__CLASS__, 'render_shortcode'));
|
|
}
|
|
|
|
/**
|
|
* Render the shortcode
|
|
*/
|
|
public static function render_shortcode($atts) {
|
|
// Parse shortcode attributes
|
|
$atts = shortcode_atts(array(
|
|
'repo' => '',
|
|
'theme' => 'dark',
|
|
'height' => '600px',
|
|
'show_line_numbers' => 'true',
|
|
'initial_file' => '',
|
|
'title' => ''
|
|
), $atts, 'github_code_viewer');
|
|
|
|
// Validate repository
|
|
if (empty($atts['repo'])) {
|
|
return '<div class="mcb-error">Error: No repository specified. Use repo="owner/repository"</div>';
|
|
}
|
|
|
|
// Sanitize attributes
|
|
$repo = sanitize_text_field($atts['repo']);
|
|
$theme = in_array($atts['theme'], array('dark', 'light', 'monokai', 'solarized')) ? $atts['theme'] : 'dark';
|
|
|
|
// Validate height - only allow specific units
|
|
$height = sanitize_text_field($atts['height']);
|
|
if (!preg_match('/^\d+(px|%|em|rem|vh)$/', $height)) {
|
|
$height = '600px'; // Default to safe value if invalid
|
|
}
|
|
|
|
$show_line_numbers = filter_var($atts['show_line_numbers'], FILTER_VALIDATE_BOOLEAN);
|
|
$initial_file = sanitize_text_field($atts['initial_file']);
|
|
$title = sanitize_text_field($atts['title']);
|
|
|
|
// Detect platform from repo string
|
|
$platform = 'github'; // default
|
|
$display_repo = $repo;
|
|
|
|
if (strpos($repo, ':') !== false) {
|
|
list($platform, $display_repo) = explode(':', $repo, 2);
|
|
} elseif (strpos($repo, 'https://') === 0 || strpos($repo, 'http://') === 0) {
|
|
// Parse URL to detect platform
|
|
if (strpos($repo, 'gitlab.com') !== false) {
|
|
$platform = 'gitlab';
|
|
} elseif (strpos($repo, 'bitbucket.org') !== false) {
|
|
$platform = 'bitbucket';
|
|
} elseif (strpos($repo, 'codeberg.org') !== false) {
|
|
$platform = 'codeberg';
|
|
}
|
|
// Extract repo name from URL
|
|
$parsed = parse_url($repo);
|
|
if ($parsed && isset($parsed['path'])) {
|
|
$display_repo = trim($parsed['path'], '/');
|
|
}
|
|
}
|
|
|
|
// Generate unique ID for this instance
|
|
$viewer_id = 'mcb-' . uniqid();
|
|
|
|
// Build the viewer HTML
|
|
ob_start();
|
|
?>
|
|
<div id="<?php echo esc_attr($viewer_id); ?>" class="maple-code-blocks mcb-theme-<?php echo esc_attr($theme); ?>"
|
|
data-repo="<?php echo esc_attr($repo); ?>"
|
|
data-theme="<?php echo esc_attr($theme); ?>"
|
|
data-show-line-numbers="<?php echo $show_line_numbers ? 'true' : 'false'; ?>"
|
|
data-initial-file="<?php echo esc_attr($initial_file); ?>"
|
|
style="height: <?php echo esc_attr($height); ?>;">
|
|
|
|
<div class="mcb-header">
|
|
<?php if (!empty($title)) : ?>
|
|
<h3 class="mcb-title"><?php echo esc_html($title); ?></h3>
|
|
<?php endif; ?>
|
|
<div class="mcb-repo-info">
|
|
<?php
|
|
// Display platform-specific icon
|
|
switch($platform) {
|
|
case 'gitlab':
|
|
?>
|
|
<svg class="mcb-platform-icon" viewBox="0 0 24 24" width="20" height="20">
|
|
<path fill="#FC6D26" d="M22.65 14.39L12 22.13 1.35 14.39a.84.84 0 0 1-.3-.94l1.22-3.78 2.44-7.51A.42.42 0 0 1 4.82 2a.43.43 0 0 1 .58 0 .42.42 0 0 1 .11.18l2.44 7.49h8.1l2.44-7.51A.42.42 0 0 1 18.6 2a.43.43 0 0 1 .58 0 .42.42 0 0 1 .11.18l2.44 7.51L23 13.45a.84.84 0 0 1-.35.94z"/>
|
|
</svg>
|
|
<?php
|
|
break;
|
|
case 'bitbucket':
|
|
?>
|
|
<svg class="mcb-platform-icon" viewBox="0 0 24 24" width="20" height="20">
|
|
<path fill="#0052CC" d="M3.28 2.42a1 1 0 00-.97.8l-2.3 14.3a1.35 1.35 0 00.78 1.51l9.84 4.13c.36.15.77.15 1.13 0l9.86-4.13a1.35 1.35 0 00.78-1.5l-2.3-14.31a1 1 0 00-.97-.8H3.28zm8.3 12.66h-3.8l-1-6.4h5.56l.75 6.4z"/>
|
|
</svg>
|
|
<?php
|
|
break;
|
|
case 'codeberg':
|
|
?>
|
|
<svg class="mcb-platform-icon" viewBox="0 0 24 24" width="20" height="20">
|
|
<path fill="#2185D0" d="M12 2C6.48 2 2 6.48 2 12c0 4.42 2.87 8.17 6.84 9.49.5.09.68-.22.68-.48 0-.24-.01-1.02-.01-1.85-2.78.6-3.37-1.18-3.37-1.18-.45-1.15-1.11-1.46-1.11-1.46-.91-.62.07-.61.07-.61 1 .07 1.53 1.03 1.53 1.03.89 1.53 2.34 1.09 2.91.83.09-.64.35-1.09.63-1.34-2.22-.25-4.55-1.11-4.55-4.93 0-1.09.39-1.98 1.03-2.68-.1-.25-.45-1.27.1-2.64 0 0 .84-.27 2.75 1.03A9.58 9.58 0 0112 6.8c.85.004 1.71.115 2.51.34 1.91-1.3 2.75-1.03 2.75-1.03.55 1.37.2 2.39.1 2.64.64.7 1.03 1.59 1.03 2.68 0 3.83-2.34 4.68-4.56 4.92.36.31.68.92.68 1.85 0 1.34-.01 2.42-.01 2.75 0 .27.18.58.69.48A10.01 10.01 0 0022 12c0-5.52-4.48-10-10-10z"/>
|
|
</svg>
|
|
<?php
|
|
break;
|
|
case 'github':
|
|
default:
|
|
?>
|
|
<svg class="mcb-platform-icon" viewBox="0 0 24 24" width="20" height="20">
|
|
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
|
|
</svg>
|
|
<?php
|
|
break;
|
|
}
|
|
?>
|
|
<span class="mcb-repo-name"><?php echo esc_html($display_repo); ?></span>
|
|
</div>
|
|
<div class="mcb-controls">
|
|
<button class="mcb-home-btn" title="Go to root">
|
|
<svg viewBox="0 0 24 24" width="18" height="18">
|
|
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
|
|
</svg>
|
|
</button>
|
|
<button class="mcb-refresh-btn" title="Refresh files">
|
|
<svg viewBox="0 0 24 24" width="18" height="18">
|
|
<path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/>
|
|
</svg>
|
|
</button>
|
|
<button class="mcb-fullscreen-btn" title="Toggle fullscreen">
|
|
<svg viewBox="0 0 24 24" width="18" height="18">
|
|
<path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mcb-content">
|
|
<div class="mcb-sidebar">
|
|
<div class="mcb-search-box">
|
|
<input type="text" class="mcb-search-input" placeholder="Search files...">
|
|
</div>
|
|
<div class="mcb-file-list">
|
|
<div class="mcb-loading">
|
|
<div class="mcb-spinner"></div>
|
|
<span>Loading repository files...</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mcb-editor">
|
|
<div class="mcb-tabs">
|
|
<!-- Tabs will be added dynamically -->
|
|
</div>
|
|
<div class="mcb-code-area">
|
|
<div class="mcb-welcome">
|
|
<svg viewBox="0 0 24 24" width="64" height="64">
|
|
<path d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z"/>
|
|
</svg>
|
|
<h4>GitHub Code Viewer</h4>
|
|
<p>Select a file from the sidebar to view its content</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mcb-status-bar">
|
|
<span class="mcb-status-text">Ready</span>
|
|
<span class="mcb-file-info"></span>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
return ob_get_clean();
|
|
}
|
|
}
|