Initial commit: TechBlog Pro WordPress theme

Features:
- Modern UI with dark mode support
- Code highlighting with copy button
- Auto table of contents
- Reading time & views counter
- Responsive design
- Admin settings page
- AJAX search
This commit is contained in:
Your Name
2026-08-18 16:05:14 +08:00
commit 6d4368fbd1
17 changed files with 4103 additions and 0 deletions
Executable
+459
View File
@@ -0,0 +1,459 @@
<?php
/**
* TechBlog Pro Theme Functions
*
* @package TechBlog Pro
* @version 1.0.0
*/
defined('ABSPATH') || exit;
// Theme Constants
define('TECHBLOG_VERSION', '1.0.0');
define('TECHBLOG_DIR', get_template_directory());
define('TECHBLOG_URI', get_template_directory_uri());
// Include admin options
require_once TECHBLOG_DIR . '/inc/admin-options.php';
/**
* Theme Setup
*/
function techblog_setup() {
// Add theme support
add_theme_support('title-tag');
add_theme_support('post-thumbnails');
add_theme_support('custom-logo', array(
'height' => 40,
'width' => 200,
'flex-height' => true,
'flex-width' => true,
));
add_theme_support('html5', array(
'search-form',
'comment-form',
'comment-list',
'gallery',
'caption',
'style',
'script',
));
add_theme_support('editor-styles');
add_theme_support('responsive-embeds');
add_theme_support('wp-block-styles');
// Register Navigation Menus
register_nav_menus(array(
'primary' => esc_html__('主导航菜单', 'techblog'),
'footer' => esc_html__('页脚菜单', 'techblog'),
));
// Set content width
if (!isset($content_width)) {
$content_width = 780;
}
}
add_action('after_setup_theme', 'techblog_setup');
/**
* Enqueue Styles and Scripts
*/
function techblog_scripts() {
// Google Fonts
wp_enqueue_style('techblog-fonts',
'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap',
array(),
null
);
// Main Stylesheet
wp_enqueue_style('techblog-style',
get_stylesheet_uri(),
array(),
TECHBLOG_VERSION
);
// Main JavaScript
wp_enqueue_script('techblog-main',
TECHBLOG_URI . '/js/main.js',
array(),
TECHBLOG_VERSION,
true
);
// Localize script
wp_localize_script('techblog-main', 'techblog', array(
'ajaxurl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('techblog-nonce'),
));
}
add_action('wp_enqueue_scripts', 'techblog_scripts');
/**
* Register Sidebars
*/
function techblog_widgets_init() {
register_sidebar(array(
'name' => esc_html__('主侧边栏', 'techblog'),
'id' => 'sidebar-main',
'description' => esc_html__('文章页面右侧的侧边栏', 'techblog'),
'before_widget' => '<div id="%1$s" class="sidebar-widget %2$s">',
'after_widget' => '</div>',
'before_title' => '<h3 class="widget-title">',
'after_title' => '</h3>',
));
register_sidebar(array(
'name' => esc_html__('页脚栏 1', 'techblog'),
'id' => 'footer-1',
'description' => esc_html__('页脚第一列', 'techblog'),
'before_widget' => '<div id="%1$s" class="footer-section %2$s">',
'after_widget' => '</div>',
'before_title' => '<h3>',
'after_title' => '</h3>',
));
register_sidebar(array(
'name' => esc_html__('页脚栏 2', 'techblog'),
'id' => 'footer-2',
'description' => esc_html__('页脚第二列', 'techblog'),
'before_widget' => '<div id="%1$s" class="footer-section %2$s">',
'after_widget' => '</div>',
'before_title' => '<h3>',
'after_title' => '</h3>',
));
register_sidebar(array(
'name' => esc_html__('页脚栏 3', 'techblog'),
'id' => 'footer-3',
'description' => esc_html__('页脚第三列', 'techblog'),
'before_widget' => '<div id="%1$s" class="footer-section %2$s">',
'after_widget' => '</div>',
'before_title' => '<h3>',
'after_title' => '</h3>',
));
}
add_action('widgets_init', 'techblog_widgets_init');
/**
* Custom Excerpt Length
*/
function techblog_excerpt_length($length) {
return 25;
}
add_filter('excerpt_length', 'techblog_excerpt_length');
/**
* Custom Excerpt More
*/
function techblog_excerpt_more($more) {
return '...';
}
add_filter('excerpt_more', 'techblog_excerpt_more');
/**
* Add Code Language Class to Pre Tags
*/
function techblog_code_block_attributes($block_content, $block) {
if ($block['blockName'] === 'core/code') {
if (!empty($block['attrs']['language'])) {
$lang = esc_attr($block['attrs']['language']);
$block_content = str_replace(
'<pre class="wp-block-code',
'<pre class="wp-block-code lang-' . $lang,
$block_content
);
}
}
return $block_content;
}
add_filter('render_block', 'techblog_code_block_attributes', 10, 2);
/**
* Generate Table of Contents
*/
function techblog_generate_toc($content) {
if (!is_single()) {
return $content;
}
preg_match_all('/<h([2-3])[^>]*>(.*?)<\/h[2-3]>/is', $content, $matches, PREG_SET_ORDER);
if (count($matches) < 3) {
return $content;
}
$toc = '<div class="toc-container"><nav class="toc">';
$toc .= '<div class="toc-title"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 6h16M4 12h16M4 18h16"/></svg> 目录</div>';
$toc .= '<ul class="toc-list">';
$headings = array();
foreach ($matches as $match) {
$level = $match[1];
$text = strip_tags($match[2]);
$id = sanitize_title($text);
$id = preg_replace('/[^a-z0-9\-]/', '', $id);
// Ensure unique IDs
if (in_array($id, $headings)) {
$id .= '-' . count($headings);
}
$headings[] = $id;
$class = $level == 3 ? ' class="toc-h3"' : '';
$toc .= '<li><a href="#' . esc_attr($id) . '"' . $class . '>' . esc_html($text) . '</a></li>';
// Add ID to heading in content
$content = str_replace(
$match[0],
'<h' . $level . ' id="' . esc_attr($id) . '">' . $match[2] . '</h' . $level . '>',
$content
);
}
$toc .= '</ul></nav></div>';
// Insert TOC after first paragraph or before first heading
$first_p = strpos($content, '</p>');
if ($first_p !== false) {
$content = substr($content, 0, $first_p + 4) . $toc . substr($content, $first_p + 4);
} else {
$content = $toc . $content;
}
return $content;
}
add_filter('the_content', 'techblog_generate_toc', 20);
/**
* Add Copy Button to Code Blocks
*/
function techblog_add_code_copy_button($content) {
if (!is_single() && !is_page()) {
return $content;
}
$content = preg_replace_callback(
'/<pre([^>]*)>(.*?)<\/pre>/is',
function($matches) {
$attrs = $matches[1];
$code = $matches[2];
// Extract language if present
$lang = '';
if (preg_match('/lang-([a-z0-9]+)/', $attrs, $lang_match)) {
$lang = strtoupper($lang_match[1]);
}
$header = '<div class="code-header">';
$header .= '<span class="code-lang">' . ($lang ?: 'CODE') . '</span>';
$header .= '<button class="copy-btn" onclick="copyCode(this)">';
$header .= '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg>';
$header .= '复制</button></div>';
return '<pre' . $attrs . '>' . $header . $code . '</pre>';
},
$content
);
return $content;
}
add_filter('the_content', 'techblog_add_code_copy_button', 25);
/**
* Custom Walker for Navigation Menu
*/
class TechBlog_Nav_Walker extends Walker_Nav_Menu {
function start_el(&$output, $item, $depth = 0, $args = null, $id = 0) {
$classes = empty($item->classes) ? array() : (array) $item->classes;
$class = join(' ', array_filter($classes));
if (in_array('current-menu-item', $classes) || in_array('current_page_item', $classes)) {
$class .= ' current';
}
$output .= '<a href="' . esc_url($item->url) . '" class="' . esc_attr($class) . '">';
$output .= esc_html($item->title);
$output .= '</a>';
}
}
/**
* Reading Time
*/
function techblog_reading_time() {
$content = get_the_content();
$word_count = str_word_count(strip_tags($content));
$reading_time = ceil($word_count / 200); // Average reading speed
return $reading_time;
}
/**
* Post Views (Simple implementation)
*/
function techblog_get_post_views() {
$count = get_post_meta(get_the_ID(), 'post_views', true);
return $count ? intval($count) : 0;
}
function techblog_set_post_views() {
if (!is_single()) return;
$post_id = get_the_ID();
$count = get_post_meta($post_id, 'post_views', true);
if ($count == '') {
$count = 0;
delete_post_meta($post_id, 'post_views');
add_post_meta($post_id, 'post_views', '0');
} else {
$count++;
update_post_meta($post_id, 'post_views', $count);
}
}
add_action('wp_head', 'techblog_set_post_views');
/**
* Format View Count
*/
function techblog_format_views($count) {
if ($count >= 10000) {
return round($count / 10000, 1) . 'w';
} elseif ($count >= 1000) {
return round($count / 1000, 1) . 'k';
}
return $count;
}
/**
* Custom Comment Form
*/
function techblog_comment_form_defaults($defaults) {
$defaults['comment_notes_before'] = '';
$defaults['comment_field'] = '<div class="comment-form-field">
<textarea id="comment" name="comment" rows="5" required></textarea>
</div>';
return $defaults;
}
add_filter('comment_form_defaults', 'techblog_comment_form_defaults');
/**
* Theme Customizer
*/
function techblog_customize_register($wp_customize) {
// Hero Section
$wp_customize->add_section('techblog_hero', array(
'title' => esc_html__('首页横幅', 'techblog'),
'priority' => 30,
));
$wp_customize->add_setting('hero_title', array(
'default' => '探索技术世界',
'sanitize_callback' => 'sanitize_text_field',
));
$wp_customize->add_control('hero_title', array(
'label' => esc_html__('横幅标题', 'techblog'),
'section' => 'techblog_hero',
'type' => 'text',
));
$wp_customize->add_setting('hero_description', array(
'default' => '分享最新的IT技术、编程教程、系统运维经验',
'sanitize_callback' => 'sanitize_textarea_field',
));
$wp_customize->add_control('hero_description', array(
'label' => esc_html__('横幅描述', 'techblog'),
'section' => 'techblog_hero',
'type' => 'textarea',
));
// Social Links
$wp_customize->add_section('techblog_social', array(
'title' => esc_html__('社交媒体', 'techblog'),
'priority' => 35,
));
$social_platforms = array(
'github' => 'GitHub',
'twitter' => 'Twitter / X',
'gitee' => 'Gitee',
'email' => '邮箱',
);
foreach ($social_platforms as $key => $label) {
$wp_customize->add_setting('social_' . $key, array(
'default' => '',
'sanitize_callback' => 'esc_url_raw',
));
$wp_customize->add_control('social_' . $key, array(
'label' => $label,
'section' => 'techblog_social',
'type' => 'url',
));
}
}
add_action('customize_register', 'techblog_customize_register');
/**
* Custom Post Type for Projects (optional)
*/
function techblog_register_post_types() {
register_post_type('project', array(
'labels' => array(
'name' => esc_html__('项目', 'techblog'),
'singular_name' => esc_html__('项目', 'techblog'),
'add_new' => esc_html__('添加项目', 'techblog'),
'add_new_item' => esc_html__('添加新项目', 'techblog'),
'edit_item' => esc_html__('编辑项目', 'techblog'),
'all_items' => esc_html__('所有项目', 'techblog'),
'view_item' => esc_html__('查看项目', 'techblog'),
'search_items' => esc_html__('搜索项目', 'techblog'),
),
'public' => true,
'has_archive' => true,
'menu_icon' => 'dashicons-portfolio',
'supports' => array('title', 'editor', 'thumbnail', 'excerpt'),
'rewrite' => array('slug' => 'project'),
));
}
add_action('init', 'techblog_register_post_types');
/**
* AJAX Search
*/
function techblog_ajax_search() {
check_ajax_referer('techblog-nonce', 'nonce');
$search_term = sanitize_text_field($_POST['search']);
if (empty($search_term)) {
wp_send_json_error('请输入搜索关键词');
}
$query = new WP_Query(array(
's' => $search_term,
'posts_per_page' => 5,
'post_status' => 'publish',
));
$results = array();
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
$results[] = array(
'title' => get_the_title(),
'url' => get_the_permalink(),
'excerpt' => wp_trim_words(get_the_excerpt(), 20),
'date' => get_the_date('Y-m-d'),
);
}
}
wp_reset_postdata();
wp_send_json_success($results);
}
add_action('wp_ajax_techblog_search', 'techblog_ajax_search');
add_action('wp_ajax_nopriv_techblog_search', 'techblog_ajax_search');