Files
argon-theme/doc/argon-theme-training.md

97 KiB
Raw Blame History

Argon 主题开发文档

项目概述

Argon 是一款基于 WordPress 的现代化博客主题,采用 Material Design 设计语言,提供丰富的功能和高度的可定制性。

核心特性

  • Material Design 风格界面
  • 响应式布局,支持多种页面布局模式(单栏/双栏/三栏)
  • 夜间模式与 AMOLED 暗黑模式
  • 沉浸式主题色系统
  • PJAX 无刷新页面加载
  • 瀑布流文章列表布局
  • 完整的评论系统(支持 Markdown、表情、点赞、置顶
  • 说说功能(类似微博的短内容发布)
  • AI 摘要生成
  • 代码高亮与数学公式渲染
  • 友链管理系统
  • 反馈系统
  • 性能优化模块

技术栈

  • PHP 7.0+
  • WordPress 4.4+
  • jQuery 3.x
  • Bootstrap 4 (Argon Design System)
  • Highlight.js (代码高亮)
  • MathJax/KaTeX (数学公式)
  • Headroom.js (顶栏自动隐藏)

项目文件结构

核心文件

argon/
├── style.css                    # 主题样式表 (核心样式定义,包含配色、排版、组件样式)
├── argontheme.js               # 主题核心 JavaScript (负责 PJAX、界面交互、功能初始化)
├── functions.php               # WordPress 主题函数 (功能入口、Hook 挂载、核心逻辑实现)
├── settings.php                # 后台设置页面 (提供外观、功能开关等配置选项)
├── header.php                  # 页面头部模板 (HTML Head、顶部导航栏、全局变量输出)
├── footer.php                  # 页面底部模板 (页脚区域、JavaScript 脚本引入)
├── index.php                   # 首页模板 (文章列表展示)
├── single.php                  # 文章页模板 (单篇文章内容展示)
├── page.php                    # 页面模板 (独立页面展示)
├── archive.php                 # 归档页模板 (分类、标签、日期归档)
├── search.php                  # 搜索结果页模板
├── 404.php                     # 404 错误页面模板
├── comments.php                # 评论区模板 (评论列表与发表评论表单)
├── sidebar.php                 # 侧边栏模板 (个人信息卡片、小工具挂载点)
├── admin.css                   # 后台设置页面样式
└── languages/                  # 多语言包目录 (.po/.mo 文件)

功能模块文件

argon/
├── shuoshuo.php                # 说说页面模板
├── timeline.php                # 时间线页面模板
├── msgboard.php                # 留言板页面模板
├── friend-links.php            # 友链页面模板
├── feedback.php                # 反馈系统
├── emotions.php                # 表情系统
├── parsedown.php               # Markdown 解析器
├── useragent-parser.php        # User Agent 解析
├── ai-summary-query.php        # AI 摘要查询接口
├── unsubscribe-comment-mailnotice.php  # 评论邮件退订
└── argon-performance.js        # 性能优化模块

模板片段

template-parts/
├── content-single.php          # 单篇文章内容
├── content-page.php            # 页面内容
├── content-preview-1.php       # 文章预览样式 1
├── content-preview-2.php       # 文章预览样式 2
├── content-preview-3.php       # 文章预览样式 3
├── content-shuoshuo.php        # 说说内容
├── content-shuoshuo-preview.php # 说说预览
├── content-shuoshuo-details.php # 说说详情
├── content-timeline.php        # 时间线内容
├── content-none-search.php     # 搜索无结果
├── content-none-tag.php        # 标签无结果
├── ai-summary.php              # AI 摘要组件
├── emotion-keyboard.php        # 表情键盘
├── post-actions.php            # 文章操作按钮
└── shuoshuo-operations.php     # 说说操作按钮

资源文件

assets/
├── css/
│   ├── argon.css              # Argon Design System 样式
│   └── bootstrap/             # Bootstrap 样式
├── js/
│   ├── argon.js               # Argon Design System 脚本
│   └── easter-egg.js          # 彩蛋功能
├── img/                       # 图片资源
├── icons/                     # 图标资源
├── vendor/                    # 第三方库
├── tinymce_assets/            # TinyMCE 编辑器资源
├── argon_css_merged.css       # 合并后的 CSS
└── argon_js_merged.js         # 合并后的 JS

邮件模板

email-templates/
├── base.php                   # 邮件模板基类
├── comment-notify.php         # 评论通知
├── reply-notify.php           # 回复通知
├── feedback-notify.php        # 反馈通知
├── spam-notify.php            # 垃圾评论通知
├── blacklist-spam-notify.php  # 黑名单垃圾评论通知
└── username-change-notify.php # 用户名变更通知

代码规范

CSS 规范

格式化规则

  • 使用 Tab 缩进1 Tab = 4 空格宽度)
  • 每个属性独占一行
  • 属性之间不要有空行
  • 规则块之间保留一个空行
  • 选择器与 { 之间有一个空格
  • 属性值后的 ; 前不要有空格

示例

/* 正确 */
.selector {
	property: value;
	another-property: value;
}

.another-selector {
	property: value;
}

/* 错误 - 属性之间有空行 */
.selector {

	property: value;

	another-property: value;

}

注释规范

/* ==========================================================================
   大区块标题
   ========================================================================== */

/* ---------- 小区块标题 ---------- */

/* 普通注释 */

JavaScript 规范

格式化规则

  • 使用 Tab 缩进
  • 字符串优先使用单引号 '
  • 比较运算符使用严格相等 ===!==
  • 语句末尾必须有分号 ;
  • 函数名与括号之间无空格
  • 关键字后有空格if, for, while, function 等)

变量声明

  • 优先使用 letconst
  • 避免使用 var(除非需要函数作用域或全局变量)

全局变量(需保留 var

以下全局变量必须使用 var 声明以确保跨作用域访问:

  • argonConfig - 主题配置对象
  • translation - 多语言翻译表
  • pjaxLoading - PJAX 加载状态
  • headroom - Headroom 实例

注释规范

// ==========================================================================
// 大区块标题
// ==========================================================================

// ---------- 小区块标题 ----------

/**
 * 函数说明
 * @param {string} param - 参数说明
 * @returns {boolean} 返回值说明
 */
function functionName(param) {
	// 单行注释
	if (param === 'value') {
		return true;
	}
	return false;
}

PHP 规范

格式化规则

  • 使用 Tab 缩进
  • 字符串优先使用单引号
  • 数组使用短语法 []
  • 类名使用 PascalCase
  • 函数名使用 snake_case遵循 WordPress 规范)
  • 箭头操作符 -> 前后不要有空格

WordPress 特定

  • 使用 esc_html(), esc_attr() 等函数转义输出
  • 使用 wp_nonce_field() 进行安全验证
  • 遵循 WordPress Coding Standards

示例

// 正确
$theme->Version
get_option('argon_theme_color')

// 错误
$theme -> Version

核心架构

主题初始化流程

主题的初始化分为服务器端PHP和客户端JavaScript两个阶段。

服务器端初始化

  1. functions.php 加载WordPress 加载主题时执行)
// functions.php
// 检查 WordPress 版本兼容性
if (version_compare($GLOBALS['wp_version'], '4.4-alpha', '<')) {
	echo "<div style='...'>Argon 主题不支持 Wordpress 4.4 以下版本</div>";
}

// 设置主题支持功能
function theme_slug_setup() {
	add_theme_support('title-tag');        // 标题标签
	add_theme_support('post-thumbnails');  // 特色图片
	load_theme_textdomain('argon', get_template_directory() . '/languages');  // 多语言
}
add_action('after_setup_theme','theme_slug_setup');

// 设置全局变量
$argon_version = !(wp_get_theme()->Template) ? wp_get_theme()->Version : wp_get_theme(wp_get_theme()->Template)->Version;
$GLOBALS['theme_version'] = $argon_version;
$GLOBALS['assets_path'] = get_bloginfo('template_url');
  1. 导航菜单注册

    主题通过 init 挂钩注册了四个核心菜单位置,用于定义页面的不同导航区域:

    // functions.php
    function init_nav_menus(){
    	register_nav_menus( array(
    		'toolbar_menu' => __('顶部导航', 'argon'),             // 顶部工具栏菜单
    		'leftbar_menu' => __('左侧栏菜单', 'argon'),           // 左侧主要导航菜单
    		'leftbar_author_links' => __('左侧栏作者个人链接', 'argon'), // 左侧作者信息下方的图标链接
    		'leftbar_friend_links' => __('左侧栏友情链接', 'argon')  // 左侧底部的友情链接区域
    	));
    }
    add_action('init', 'init_nav_menus');
    
    1. header.php 渲染(输出 HTML 头部)
// header.php
// 1. 生成 HTML 类名(根据后台设置)
$htmlclasses = "";
if (get_option('argon_page_layout') == "single"){
	$htmlclasses .= "single-column ";
}
if (get_option('argon_enable_immersion_color') == "true"){
	$htmlclasses .= "immersion-color ";
}
// ... 更多类名

// 2. 获取主题色配置
$themecolor = get_option("argon_theme_color", "#5e72e4");
if (isset($_COOKIE["argon_custom_theme_color"])){
	if (checkHEX($_COOKIE["argon_custom_theme_color"]) && 
	    get_option('argon_show_customize_theme_color_picker') != 'false'){
		$themecolor = $_COOKIE["argon_custom_theme_color"];
	}
}

// 3. 输出 HTML 文档头
?>
<html <?php language_attributes(); ?> class="no-js <?php echo $htmlclasses;?>">
<head>
	<meta charset="<?php bloginfo('charset'); ?>">
	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
	<meta name="theme-color" content="<?php echo $themecolor; ?>">
	
	<!-- 预加载用户样式设置 - 避免样式跳变 -->
	<script>
	(function() {
		var html = document.documentElement;
		var ls = localStorage;
		
		// 字体设置
		if (ls.getItem('Argon_Use_Serif') === 'true') {
			html.classList.add('use-serif');
		}
		// 阴影设置
		if (ls.getItem('Argon_Use_Big_Shadow') === 'true') {
			html.classList.add('use-big-shadow');
		}
		// ... 更多设置
	})();
	</script>
	
	<?php
	// 4. 加载 CSS 和 JavaScript
	$assets_version = argon_get_assets_version();
	wp_enqueue_style("argon_css_merged", $GLOBALS['assets_path'] . "/assets/argon_css_merged.css", array(), $assets_version, 'all');
	wp_enqueue_style("style", $GLOBALS['assets_path'] . "/style.css", array('argon_css_merged'), $assets_version, 'all');
	wp_enqueue_script("argon_js_merged", $GLOBALS['assets_path'] . "/assets/argon_js_merged.js", array(), $assets_version, false);
	?>
	
	<?php wp_head(); ?>
	
	<!-- 5. 输出动态 CSS 变量 -->
	<style id="themecolor_css">
	:root{
		--themecolor: <?php echo $themecolor; ?>;
		--themecolor-R: <?php echo $RGB['R']; ?>;
		--themecolor-G: <?php echo $RGB['G']; ?>;
		--themecolor-B: <?php echo $RGB['B']; ?>;
		--themecolor-H: <?php echo $HSL['H']; ?>;
		--themecolor-S: <?php echo $HSL['S']; ?>;
		--themecolor-L: <?php echo $HSL['L']; ?>;
	}
	</style>
	
	<!-- 6. 输出全局配置对象 -->
	<script>
	document.documentElement.classList.remove("no-js");
	var argonConfig = {
		wp_path: "<?php echo $GLOBALS['wp_path']; ?>",
		language: "<?php echo argon_get_locate(); ?>",
		// ... 更多配置
	};
	</script>
	
	<!-- 7. 夜间模式初始化脚本 -->
	<script>
	var darkmodeAutoSwitch = "<?php echo get_option("argon_darkmode_autoswitch");?>";
	function setDarkmode(enable){ /* ... */ }
	function toggleDarkmode(){ /* ... */ }
	// ... 夜间模式逻辑
	</script>
</head>

客户端初始化

  1. 兼容性修复argontheme.js 开头)
// argontheme.js
// 确保 Prism 存在
if (typeof window.Prism === 'undefined') {
	window.Prism = { 
		highlightAll: function() {},
		highlightElement: function() {},
		plugins: {}
	};
}

// 确保 jQuery 插件存在
if (typeof jQuery !== 'undefined') {
	(function($) {
		// 修复空选择器问题
		if (!$.fn._argonInit) {
			$.fn._argonInit = $.fn.init;
			$.fn.init = function(selector, context, root) {
				if (typeof selector === 'string') {
					let trimmed = selector.trim();
					if (trimmed === '' || trimmed === '#') {
						return new $.fn._argonInit();
					}
				}
				return $.fn._argonInit.call(this, selector, context, root);
			};
			$.fn.init.prototype = $.fn;
		}
	})(jQuery);
}
  1. 工具函数定义
// argontheme.js
// Cookie 操作
function setCookie(cname, cvalue, exdays) { /* ... */ }
function getCookie(cname) { /* ... */ }

// 多语言翻译
var translation = {};
translation['en_US'] = { /* ... */ };
translation['ru_RU'] = { /* ... */ };
function __(text) {
	if (typeof translation[argonConfig.language] !== 'undefined' && 
	    typeof translation[argonConfig.language][text] !== 'undefined') {
		return translation[argonConfig.language][text];
	}
	return text;
}
  1. DOM 加载完成后初始化
// argontheme.js
$(document).ready(function() {
	// 初始化顶栏
	initNavbar();
	
	// 初始化侧边栏
	initSidebar();
	
	// 初始化瀑布流
	waterflowInit();
	
	// 初始化懒加载
	if (argonConfig.lazyload) {
		initLazyload();
	}
	
	// 初始化图片缩放
	if (argonConfig.zoomify) {
		$('.post-content img').zoomify(argonConfig.zoomify);
	}
	
	// 初始化代码高亮
	if (argonConfig.code_highlight.enable) {
		initCodeHighlight();
	}
	
	// 初始化评论系统
	initCommentSystem();
	
	// 初始化浮动按钮
	initFloatButtons();
	
	// 初始化 PJAX
	if (!argonConfig.disable_pjax) {
		initPjax();
	}
	
	// 移除加载类
	$('#float_action_buttons').removeClass('fabtns-unloaded');
});

资源加载策略

  1. CSS 加载顺序
// header.php
// 1. 合并的 CSS包含 Bootstrap 和 Argon Design System
wp_enqueue_style("argon_css_merged", ".../argon_css_merged.css");

// 2. 主题样式(依赖合并的 CSS
wp_enqueue_style("style", ".../style.css", array('argon_css_merged'));
  1. JavaScript 加载顺序
// header.php
// 1. 资源加载器(用于备用资源加载)
wp_enqueue_script("resource_loader", ".../resource-loader.js");

// 2. 合并的 JS包含 jQuery 和其他库)- 在头部同步加载
wp_enqueue_script("argon_js_merged", ".../argon_js_merged.js", array(), $assets_version, false);

// 3. Argon 修复补丁(必须在 wp_head() 之后)
<script src="<?php echo get_template_directory_uri(); ?>/assets/js/argon.min.js?ver=<?php echo $assets_version; ?>"></script>

// 4. 主题核心脚本(在 footer.php 中加载)
<?php $assets_version = function_exists('argon_get_assets_version') ? argon_get_assets_version() : $GLOBALS['theme_version']; ?>
<script src="<?php echo $GLOBALS['assets_path']; ?>/argontheme.js?v=<?php echo $assets_version; ?>"></script>
  1. 按需加载
// argontheme.js
// Google Fonts 按需加载
if (typeof ArgonResourceLoader !== "undefined") {
	ArgonResourceLoader.smartLoad("//fonts.googleapis.com/css?family=...", "css");
}

// 数学公式渲染库在 footer.php 中按设置输出get_option('argon_math_render')
// 可选mathjax3 / mathjax2 / katex / disabled

强制刷新机制

当主题更新后,可能需要清除客户端缓存:

// functions.php
function argon_is_force_refresh_enabled() {
	$enabled_time = get_option('argon_force_refresh_enabled_time', 0);
	if ($enabled_time == 0) {
		return false;
	}
	// 1 小时后自动关闭
	if (time() - $enabled_time > 3600) {
		update_option('argon_force_refresh_enabled_time', 0);
		return false;
	}
	return true;
}

function argon_get_assets_version() {
	if (argon_is_force_refresh_enabled()) {
		$enabled_time = get_option('argon_force_refresh_enabled_time', 0);
		return $GLOBALS['theme_version'] . '.r' . $enabled_time;
	}
	return $GLOBALS['theme_version'];
}

强制刷新时header.php 会输出清除缓存的脚本:

// header.php
<?php if (argon_is_force_refresh_enabled()): ?>
<script>
(function() {
	var forceRefreshKey = 'argon_force_refresh_version';
	var currentVersion = '<?php echo get_option('argon_force_refresh_enabled_time', 0); ?>';
	var lastVersion = localStorage.getItem(forceRefreshKey);
	
	if (lastVersion !== currentVersion) {
		localStorage.setItem(forceRefreshKey, currentVersion);
		if (lastVersion !== null) {
			// 清除所有缓存
			if ('caches' in window) {
				caches.keys().then(function(names) {
					return Promise.all(names.map(function(name) {
						return caches.delete(name);
					}));
				});
			}
			// 重新加载页面
			window.location.reload();
		}
	}
})();
</script>
<?php endif; ?>

全局配置对象

argonConfig 是主题的核心配置对象,在 header.php 中通过 PHP 动态生成并输出到页面:

var argonConfig = {
	wp_path: "/",                    // WordPress 安装路径
	language: "zh_CN",               // 当前语言代码
	dateFormat: "YMD",               // 日期显示格式
	
	// 图片缩放配置Zoomify
	zoomify: {
		duration: 200,               // 缩放动画时长(毫秒)
		easing: "cubic-bezier(0.4,0,0,1)", // 缓动函数
		scale: 0.9                   // 缩放比例
	},
	// 如果禁用则为 false
	
	pangu: "false",                  // 盘古之白(中英文间自动加空格)
	
	// 懒加载配置
	lazyload: true,                  // 是否启用懒加载
	lazyload_effect: "fadeIn",       // 懒加载显示效果
	lazyload_threshold: 800,         // 提前加载阈值(像素)
	
	fold_long_comments: false,       // 是否折叠长评论
	fold_long_shuoshuo: false,       // 是否折叠长说说
	
	// PJAX 配置
	disable_pjax: false,             // 是否禁用 PJAX
	pjax_animation_durtion: 600,     // PJAX 切换动画时长(毫秒)
	
	headroom: "false",               // 顶栏自动隐藏模式false/true/absolute
	
	// 文章列表布局
	waterflow_columns: "1",          // 瀑布流列数1/2/3
	article_list_layout_mobile: "1", // 移动端文章列表布局样式
	
	// 代码高亮配置
	code_highlight: {
		enable: false,               // 是否启用代码高亮
		hide_linenumber: false,      // 是否隐藏行号
		transparent_linenumber: false, // 行号是否透明
		break_line: false            // 是否自动折行
	}
};

配置对象的值从 WordPress 后台设置中读取,通过 PHP 的 get_option() 函数获取。例如:

// header.php
lazyload: <?php echo (get_option('argon_enable_lazyload', 'true') == 'false' ? 'false' : 'true'); ?>,

CSS 变量系统

主题使用 CSS 自定义属性CSS Variables实现动态主题色和样式配置。这些变量在 header.php 中通过 PHP 动态生成。

主题色变量

// header.php - 获取主题色
$themecolor = get_option("argon_theme_color", "#5e72e4");
// 支持用户自定义主题色(通过 Cookie
if (isset($_COOKIE["argon_custom_theme_color"])) {
	if (checkHEX($_COOKIE["argon_custom_theme_color"]) && 
	    get_option('argon_show_customize_theme_color_picker') != 'false') {
		$themecolor = $_COOKIE["argon_custom_theme_color"];
	}
}

// 转换为 RGB 和 HSL 值
$RGB = hexstr2rgb($themecolor);
$HSL = rgb2hsl($RGB['R'], $RGB['G'], $RGB['B']);

生成的 CSS 变量:

:root {
	/* 主题色 - 十六进制 */
	--themecolor: #5e72e4;
	
	/* 主题色 - RGB 分量(用于 rgba() 函数)*/
	--themecolor-R: 94;
	--themecolor-G: 114;
	--themecolor-B: 228;
	
	/* 主题色 - HSL 分量(用于生成色调变体)*/
	--themecolor-H: 231;
	--themecolor-S: 71;
	--themecolor-L: 63;
}

动画系统变量

:root {
	/* 动画时长 - 遵循 Material Design 3 规范 */
	--animation-fast: 150ms;      // 快速动画(按钮点击等)
	--animation-normal: 250ms;    // 标准动画(卡片展开等)
	--animation-slow: 400ms;      // 慢速动画(页面切换等)
	
	/* 缓动函数 - 融合 Material 3 + Apple 风格 */
	--ease-standard: cubic-bezier(0.25, 0.1, 0.25, 1);  // 标准缓动,流畅自然
	--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);   // 弹性缓动,有活力
}

卡片样式变量

:root {
	--card-radius: 4px;           // 卡片圆角
	--card-opacity: 0.7;          // 卡片透明度
	--card-blur: 20px;            // 毛玻璃模糊度
	--card-saturate: 180%;        // 饱和度增强
	--toolbar-blur: 12px;         // 顶栏模糊度(卡片的 60%
	--page-background-opacity: 1; // 页面背景透明度
}

这些值可以通过后台设置动态调整:

// header.php
$card_opacity = get_option('argon_post_background_opacity', '0.7');
$card_blur = get_option('argon_card_blur', '20');
$card_saturate = get_option('argon_card_saturate', '180');

颜色变量

:root {
	/* 日间模式颜色 */
	--color-background: #f4f5f7;   // 页面背景色
	--color-foreground: #fff;      // 卡片背景色
	--color-widgets: #fff;         // 小工具背景色
	--color-border: #dce0e5;       // 边框颜色
	--color-text-deeper: #212529;  // 深色文本
}

夜间模式通过 html.darkmode 类切换颜色变量:

html.darkmode body {
	--color-background: #282828;   // 深色背景
	--color-foreground: #424242;   // 深色卡片
	--color-widgets: #555;         // 深色小工具
	--color-text-deeper: #eee;     // 浅色文本
}

AMOLED 暗黑模式提供更深的黑色:

html.darkmode.amoled-dark body {
	--color-background: #111;      // 纯黑背景
	--color-foreground: #000;      // 纯黑卡片
	--color-widgets: #151515;      // 深黑小工具
}

后台设置框架

Argon 主题不依赖第三方设置框架(如 Redux 或 Codestar而是使用原生 PHP + HTML 实现了一个轻量级的设置页面。

1. 设置页面结构

设置页面位于 settings.php,通过 functions.php 中的 add_theme_page 挂载:

// functions.php
function themeoptions_admin_menu() {
    add_theme_page("Argon 主题设置", "Argon 主题选项", 'edit_themes', basename(__FILE__), 'themeoptions_page');
}
add_action('admin_menu', 'themeoptions_admin_menu');

页面内容主要由 themeoptions_page() 函数输出,采用 HTML Table 布局,包含多个选项卡(如“全局设置”、“侧栏设置”等)。

2. 选项存储与更新

设置数据的保存逻辑集成在 settings.php 顶部:

// settings.php
if (isset($_POST['update_themeoptions']) && $_POST['update_themeoptions'] == 'true') {
    // 1. 验证 Nonce 安全令牌
    check_admin_referer('argon_update_themeoptions', 'argon_update_themeoptions_nonce');
    
    // 2. 处理复选框(未选中的 checkbox 不会提交,需要手动设为 false
    if (!isset($_POST['argon_enable_lazyload'])) $_POST['argon_enable_lazyload'] = 'false';
    
    // 3. 循环更新所有选项
    foreach ($_POST as $key => $value) {
        if (isset($value) && $value != '') {
            update_option($key, $value);
        } else {
            delete_option($key); // 空值则删除选项
        }
    }
    
    // 4. 提示保存成功
    echo '<div id="message" class="updated fade"><p><strong>设置已保存</strong></p></div>';
}

3. 添加新选项指南

要在主题中添加一个新的设置项,需遵循以下步骤:

  1. settings.php 的对应表格行中添加 HTML 输入控件。
  2. name 属性必须以 argon_ 开头(这是约定,方便管理)。
  3. 使用 get_option('option_name') 获取当前值回显。

示例:添加一个“显示版权信息”的开关

<tr>
    <th><label><?php _e('显示版权信息', 'argon');?></label></th>
    <td>
        <select name="argon_show_copyright">
            <?php $show_copyright = get_option('argon_show_copyright', 'true'); ?>
            <option value="true" <?php selected($show_copyright, 'true'); ?>>开启</option>
            <option value="false" <?php selected($show_copyright, 'false'); ?>>关闭</option>
        </select>
    </td>
</tr>

前端交互架构 (PJAX & SPA)

Argon 主题采用 PJAX (PushState + AJAX) 技术实现单页应用 (SPA) 体验,核心逻辑位于 assets/js/argontheme.js

1. PJAX 工作原理

  1. 拦截点击:监听所有 a 标签点击事件。
  2. 获取内容:通过 AJAX 请求目标页面 URL。
  3. 解析响应:从响应 HTML 中提取 #content 容器内容。
  4. 替换容器:将当前页面的 #content 替换为新内容。
  5. 更新状态:使用 history.pushState 更新浏览器 URL。
  6. 重载资源:重新执行内联脚本,重置事件监听器。

2. 初始化与重载机制

由于 PJAX 会替换页面的部分 DOM依赖旧 DOM 的事件绑定与第三方实例需要在 PJAX 完成后重新初始化。Argon 的实现采用“首屏最小初始化 + PJAX 完整重初始化”的策略。

首屏加载完成后的初始化入口位于 argontheme.js$(document).ready(...),主要执行性能优化模块初始化(如已加载)以及基础渲染:

$(document).ready(function(){
	if (typeof initArgonPerformance === 'function') {
		initArgonPerformance();
	}
	highlightJsRender();
	waterflowInit();
});

PJAX 主流程通过 $(document).pjax(...) 建立,并在 pjax:beforeReplace 统一清理旧页面资源,在 pjax:complete 完整初始化新页面模块(包含数学公式渲染、脚本执行与各功能模块的错误隔离初始化)。

3. 脚本执行器 (Inline Script Executor)

PJAX 替换的 DOM 片段中可能包含内联 <script>。Argon 使用“创建新 script 节点并插入 head”的方式执行内联脚本同时为每个脚本标记 data-pjax-executed,避免重复执行:

function executeInlineScripts(container) {
	const scripts = container.querySelectorAll('script');
	scripts.forEach((script) => {
		if (script.getAttribute('data-pjax-executed') === 'true') return;
		if (script.src) return;
		if (!script.textContent || script.textContent.trim() === '') return;
		const newScript = document.createElement('script');
		newScript.text = script.textContent;
		document.head.appendChild(newScript);
		document.head.removeChild(newScript);
		script.setAttribute('data-pjax-executed', 'true');
	});
}

开发注意:如果你在文章或页面中编写了自定义 JavaScript确保它们不依赖 document.ready,或者在 PJAX 重载时能被正确处理。

核心功能模块

1. 主题色系统

实现原理

主题色通过 PHP 动态生成 CSS 变量,支持用户自定义:

// header.php
$themecolor = get_option("argon_theme_color", "#5e72e4");
if (isset($_COOKIE["argon_custom_theme_color"])) {
	$themecolor = $_COOKIE["argon_custom_theme_color"];
}
$RGB = hexstr2rgb($themecolor);
$HSL = rgb2hsl($RGB['R'], $RGB['G'], $RGB['B']);

生成的 CSS 变量:

:root {
	--themecolor: #5e72e4;
	--themecolor-R: 94;
	--themecolor-G: 114;
	--themecolor-B: 228;
	--themecolor-H: 231;
	--themecolor-S: 71;
	--themecolor-L: 63;
}

沉浸式主题色

开启沉浸式主题色后,页面背景和卡片会使用主题色的浅色变体:

html.immersion-color body {
	--color-background: rgb(var(--color-tint-86));
	--color-foreground: rgb(var(--color-tint-92));
}

2. 夜间模式

切换方案

主题支持四种夜间模式切换方案,通过后台设置 argon_darkmode_autoswitch 选项控制:

  1. false默认 - 手动切换,不自动切换
  2. system - 跟随系统,通过 prefers-color-scheme 媒体查询
  3. time - 根据时间自动切换22:00-7:00
  4. alwayson - 始终开启夜间模式

实现代码

夜间模式的核心实现在 header.php 中:

// header.php
var darkmodeAutoSwitch = "<?php echo (get_option("argon_darkmode_autoswitch") == '' ? 'false' : get_option("argon_darkmode_autoswitch"));?>";

// 设置夜间模式
function setDarkmode(enable){
	// 添加过渡类以启用平滑切换动画
	document.documentElement.classList.add("theme-transitioning");
	
	if (enable == true){
		document.documentElement.classList.add("darkmode");
	}else{
		document.documentElement.classList.remove("darkmode");
	}
	
	// 过渡完成后移除过渡类300ms 后)
	setTimeout(function() {
		document.documentElement.classList.remove("theme-transitioning");
	}, 300);
	
	// 触发滚动事件以更新顶栏状态
	if (typeof jQuery !== 'undefined') {
		jQuery(window).trigger("scroll");
	} else {
		window.dispatchEvent(new Event('scroll'));
	}
	
	// 触发自定义事件,供其他模块监听
	document.dispatchEvent(new CustomEvent('argon:theme-switched', {
		detail: { darkmode: enable }
	}));
}

// 切换夜间模式
function toggleDarkmode(){
	if (document.documentElement.classList.contains("darkmode")){
		setDarkmode(false);
		sessionStorage.setItem("Argon_Enable_Dark_Mode", "false");
	}else{
		setDarkmode(true);
		sessionStorage.setItem("Argon_Enable_Dark_Mode", "true");
	}
}

跟随系统方案

使用 matchMedia API 监听系统主题变化:

// header.php
function toggleDarkmodeByPrefersColorScheme(media){
	// 如果用户手动设置过,则不自动切换
	if (sessionStorage.getItem('Argon_Enable_Dark_Mode') == "false" || 
	    sessionStorage.getItem('Argon_Enable_Dark_Mode') == "true"){
		return;
	}
	
	if (media.matches){
		setDarkmode(true);
	}else{
		setDarkmode(false);
	}
}

if (darkmodeAutoSwitch == 'system'){
	var darkmodeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
	darkmodeMediaQuery.addListener(toggleDarkmodeByPrefersColorScheme);
	toggleDarkmodeByPrefersColorScheme(darkmodeMediaQuery);
}

根据时间方案

// header.php
function toggleDarkmodeByTime(){
	// 如果用户手动设置过,则不自动切换
	if (sessionStorage.getItem('Argon_Enable_Dark_Mode') == "false" || 
	    sessionStorage.getItem('Argon_Enable_Dark_Mode') == "true"){
		return;
	}
	
	let hour = new Date().getHours();
	
	// 默认22:00-7:00 开启夜间模式
	// 可通过过滤器 argon_darkmode_time_check 自定义时间范围
	if (<?php echo apply_filters("argon_darkmode_time_check", "hour < 7 || hour >= 22")?>){
		setDarkmode(true);
	}else{
		setDarkmode(false);
	}
}

if (darkmodeAutoSwitch == 'time'){
	toggleDarkmodeByTime();
}

AMOLED 暗黑模式

AMOLED 模式提供更深的黑色背景,适合 AMOLED 屏幕节省电量:

// header.php
function toggleAmoledDarkMode(){
	document.documentElement.classList.toggle("amoled-dark");
	
	if (document.documentElement.classList.contains("amoled-dark")){
		localStorage.setItem("Argon_Enable_Amoled_Dark_Mode", "true");
	}else{
		localStorage.setItem("Argon_Enable_Amoled_Dark_Mode", "false");
	}
}

// 页面加载时恢复 AMOLED 模式设置
if (localStorage.getItem("Argon_Enable_Amoled_Dark_Mode") == "true"){
	document.documentElement.classList.add("amoled-dark");
}else if (localStorage.getItem("Argon_Enable_Amoled_Dark_Mode") == "false"){
	document.documentElement.classList.remove("amoled-dark");
}

用户偏好存储

夜间模式的用户选择存储在 sessionStorageAMOLED 模式存储在 localStorage 中:

  • sessionStorage.Argon_Enable_Dark_Mode - 夜间模式开关(会话级别)
  • localStorage.Argon_Enable_Amoled_Dark_Mode - AMOLED 模式开关(持久化)

这样设计的原因:

  • 夜间模式使用 sessionStorage每次打开浏览器都会根据设置重新判断
  • AMOLED 模式使用 localStorage用户设置会永久保存

3. PJAX 无刷新加载

配置与初始化

PJAX 使用 jquery-pjax 库实现页面无刷新加载。配置在 argontheme.js 中:

// argontheme.js
$.pjax.defaults.timeout = 10000;  // 超时时间 10 秒
var pjaxContainerSelectors = ['#primary', '#leftbar_part1_menu', '#leftbar_part2_inner', '.page-information-card-container', '#rightbar', '#wpadminbar'];
var pjaxContainers = pjaxContainerSelectors.filter(function(selector) {
	return document.querySelector(selector);
});
$.pjax.defaults.container = pjaxContainers;  // 要替换的容器
$.pjax.defaults.fragment = pjaxContainers;   // 从响应中提取的片段

链接拦截

主题会自动拦截站内链接的点击事件:

// argontheme.js
$(document).pjax(
	"a[href]:not([no-pjax]):not(.no-pjax):not([target='_blank']):not([download]):not(.reference-link):not(.reference-list-backlink):not([href^='#'])",
	pjaxContainers.length ? pjaxContainers[0] : '#primary',
	{ fragment: (pjaxContainers.length ? pjaxContainers : ['#primary']), timeout: $.pjax.defaults.timeout }
);

页面切换流程

PJAX 加载过程中会触发一系列事件:

// argontheme.js

// 1. 开始发送请求
$(document).on('pjax:send', function() {
	// 设置加载状态
	pjaxLoading = true;
	
	// 显示加载动画
	$('#content').addClass('pjax-loading');
	
	// 添加淡出效果
	$('#content, #leftbar, #rightbar').css('opacity', '0');
});

// 2. 请求成功,内容已替换
$(document).on('pjax:complete', function() {
	// 清除加载状态
	pjaxLoading = false;
	
	// 移除加载动画
	$('#content').removeClass('pjax-loading');
	
	// 添加淡入效果
	$('#content, #leftbar, #rightbar').animate({
		opacity: 1
	}, argonConfig.pjax_animation_durtion);
	
	// 滚动到顶部
	$('html, body').animate({
		scrollTop: 0
	}, argonConfig.pjax_animation_durtion);
	
	// 重新初始化各功能模块(主题在 pjax:complete 内集中处理,如 waterflowInit / lazyloadInit / zoomifyInit / highlightJsRender 等)
});

// 3. 请求失败
$(document).on('pjax:error', function(xhr, textStatus, error) {
	console.error('PJAX 加载失败:', error);
	// 失败时会自动回退到普通页面跳转
});

// 4. 超时
$(document).on('pjax:timeout', function(event) {
	// 阻止默认的超时处理(会中断请求)
	event.preventDefault();
});

重新初始化

PJAX 加载完成后,需要重新初始化页面功能:

// argontheme.js
// 主题在 pjax:complete 事件里集中完成“功能重置/再初始化”(单个模块失败不会影响其他模块)
try { waterflowInit(); } catch (err) {}
try { lazyloadInit(); } catch (err) {}
try { zoomifyInit(); } catch (err) {}
try { highlightJsRender(); } catch (err) {}
try { panguInit(); } catch (err) {}
try { clampInit(); } catch (err) {}
try { tippyInit(); } catch (err) {}
try { getGithubInfoCardContent(); } catch (err) {}
try { showPostOutdateToast(); } catch (err) {}
try { calcHumanTimesOnPage(); } catch (err) {}
try { foldLongComments(); } catch (err) {}
try { foldLongShuoshuo(); } catch (err) {}
try { handleHashNavigation(); } catch (err) {}

禁用 PJAX

可以通过以下方式禁用 PJAX

  1. 后台设置中禁用(argon_pjax_disabled 选项)
  2. 给链接添加 no-pjax 属性:
<a href="/page" no-pjax>普通跳转</a>
  1. 给链接添加 target 属性:
<a href="/page" target="_blank">新窗口打开</a>

浏览器历史记录

PJAX 会自动更新浏览器历史记录,支持前进后退按钮:

// argontheme.js
$(window).on('popstate', function() {
	// 浏览器前进/后退时PJAX 会自动加载对应页面
});

性能优化

PJAX 加载时的性能优化措施:

  1. 只替换必要的容器content、leftbar、rightbar
  2. 使用 CSS 动画而非 JavaScript 动画
  3. 延迟初始化非关键功能
  4. 复用已加载的资源CSS、JS
// argontheme.js
// 动画时长可配置,设为 0 可禁用动画
pjax_animation_durtion: <?php echo (get_option("argon_disable_pjax_animation") == 'true' ? '0' : '600'); ?>

4. 瀑布流布局

实现原理

瀑布流布局通过 JavaScript 动态计算每个文章卡片的位置,实现类似 Pinterest 的多列布局。

核心算法

// argontheme.js
function waterflowInit() {
	// 如果设置为单列,直接返回
	if (argonConfig.waterflow_columns == "1") {
		return;
	}
	
	// 监听图片加载,加载完成后重新计算布局
	$("#main.article-list img").each(function(index, ele){
		ele.onload = function(){
			waterflowInit();
		}
	});
	
	// 确定列数
	let columns;
	if (argonConfig.waterflow_columns == "2and3") {
		// 自适应 2-3 列
		if ($("#main").outerWidth() > 1000) {
			columns = 3;
		} else {
			columns = 2;
		}
	}else{
		columns = parseInt(argonConfig.waterflow_columns);
	}
	
	// 响应式适配:窄屏幕时强制单列
	if ($("#main").outerWidth() < 650 && columns == 2) {
		columns = 1;
	}else if ($("#main").outerWidth() < 800 && columns == 3) {
		columns = 1;
	}
	
	// 记录每列的高度
	let heights = [0, 0, 0];
	
	// 获取当前最矮列的索引
	function getMinHeightPosition(){
		let res = 0, minn = 2147483647;
		for (var i = 0; i < columns; i++) {
			if (heights[i] < minn) {
				minn = heights[i];
				res = i;
			}
		}
		return res;
	}
	
	// 获取最高列的高度
	function getMaxHeight(){
		let res = 0;
		for (let i in heights) {
			res = Math.max(res, heights[i]);
		}
		return res;
	}
	
	// 添加瀑布流类
	$("#primary").css("transition", "none").addClass("waterflow");
	
	let $container = $("#main.article-list");
	if (!$container.length){
		return;
	}
	
	// 获取所有文章卡片
	let $items = $container.find("article.post:not(.no-results), .shuoshuo-preview-container");
	
	// 列数不能超过文章数量
	columns = Math.max(Math.min(columns, $items.length), 1);
	
	if (columns == 1) {
		// 单列模式:移除瀑布流样式
		$container.removeClass("waterflow");
		$items.css("transition", "")
			.css("position", "")
			.css("width", "")
			.css("top", "")
			.css("left", "")
			.css("margin", "");
		$(".waterflow-placeholder").remove();
	}else{
		// 多列模式:计算每个卡片的位置
		$container.addClass("waterflow");
		$items.each(function(index, item) {
			let $item = $(item);
			
			// 设置卡片宽度(平分容器宽度,减去间距)
			$item.css("transition", "none")
				.css("position", "absolute")
				.css("width", "calc(" + (100 / columns) + "% - " + (10 * (columns - 1) / columns) + "px)")
				.css("margin", 0);
			
			// 计算卡片高度(包含 10px 间距)
			let itemHeight = $item.outerHeight() + 10;
			
			// 找到最矮的列
			let pos = getMinHeightPosition();
			
			// 设置卡片位置
			$item.css("top", heights[pos] + "px")
				.css("left", (pos * $item.outerWidth() + 10 * pos) + "px");
			
			// 更新该列的高度
			heights[pos] += itemHeight;
		});
	}
	
	// 创建占位元素,撑开容器高度
	if ($(".waterflow-placeholder").length) {
		$(".waterflow-placeholder").css("height", getMaxHeight() + "px");
	}else{
		$container.prepend("<div class='waterflow-placeholder' style='height: " + getMaxHeight() +"px;'></div>");
	}
}

初始化与监听

// argontheme.js
// 页面加载时初始化
waterflowInit();

// 非单列模式下监听窗口大小变化
if (argonConfig.waterflow_columns != "1") {
	// 窗口大小改变时重新计算
	$(window).resize(function(){
		waterflowInit();
	});
	
	// 监听 DOM 变化(如 PJAX 加载新内容)
	new MutationObserver(function(mutations, observer){
		waterflowInit();
	}).observe(document.querySelector("#primary"), {
		'childList': true
	});
}

移动端布局切换

移动端可以使用不同的文章列表布局样式:

// argontheme.js
!function(){
	var mobileLayout = argonConfig.article_list_layout_mobile || "1";
	var isMobile = window.innerWidth <= 900;
	
	function applyMobileLayout() {
		var nowMobile = window.innerWidth <= 900;
		if (nowMobile) {
			// 添加移动端布局类
			$("html").addClass("mobile-layout-" + mobileLayout);
		} else {
			// 移除移动端布局类
			$("html").removeClass("mobile-layout-1 mobile-layout-2 mobile-layout-3");
		}
	}
	
	applyMobileLayout();
	$(window).resize(applyMobileLayout);
}();

配置选项

瀑布流列数通过后台设置 argon_article_list_waterflow 控制:

  • "1" - 单列(默认)
  • "2" - 双列
  • "3" - 三列
  • "2and3" - 自适应 2-3 列(宽屏 3 列,窄屏 2 列)

性能优化

  1. 图片加载完成后才计算布局,避免高度计算错误
  2. 使用 MutationObserver 监听 DOM 变化,而非轮询
  3. 窗口大小改变时使用防抖,避免频繁计算
  4. 单列模式下不监听事件,减少性能开销

CSS 配合

/* style.css */
#main.article-list.waterflow {
	position: relative;
}

#main.article-list.waterflow article.post {
	position: absolute;
	transition: top 0.3s ease, left 0.3s ease;
}

.waterflow-placeholder {
	width: 100%;
	pointer-events: none;
}

5. 评论系统

数据库结构

评论数据存储在 WordPress 标准的 wp_comments 表中,扩展字段通过 wp_commentmeta 表存储:

标准字段wp_comments 表):

  • comment_ID - 评论 ID
  • comment_post_ID - 所属文章 ID
  • comment_author - 评论者昵称
  • comment_author_email - 评论者邮箱
  • comment_author_url - 评论者网站
  • comment_content - 评论内容HTML
  • comment_parent - 父评论 ID用于回复
  • user_id - 用户 ID登录用户
  • comment_date - 评论时间

扩展字段wp_commentmeta 表):

  • comment_upvote - 点赞数
  • comment_is_private - 是否私密评论
  • comment_use_markdown - 是否使用 Markdown
  • comment_content_source - Markdown 源码
  • comment_edit_history - 编辑历史JSON 格式)
  • comment_pinned - 是否置顶
  • qq - QQ 号(用于 QQ 头像)

AJAX 发送评论

前端通过 AJAX 提交评论,避免页面刷新:

// argontheme.js
function postComment() {
	let formData = {
		action: 'ajax_post_comment',
		comment_post_ID: postID,
		author: $('#comment_author').val(),
		email: $('#comment_email').val(),
		url: $('#comment_url').val(),
		comment: $('#comment_content').val(),
		comment_parent: replyID,
		use_markdown: $('#use_markdown').is(':checked') ? 'true' : 'false',
		is_private: $('#is_private').is(':checked') ? 'true' : 'false',
		argon_nonce: $('#argon_comment_nonce').val(),
		// 验证码相关字段
		captcha_seed: $('#captcha_seed').val(),
		captcha_answer: $('#captcha_answer').val()
	};
	
	$.ajax({
		type: 'POST',
		url: argonConfig.wp_path + "wp-admin/admin-ajax.php",
		dataType: "json",
		data: formData,
		beforeSend: function() {
			$('#comment_submit').text(__('发送中'));
			$('#comment_submit').prop('disabled', true);
		},
		success: function(result) {
			if (result.status == "success") {
				// 插入新评论到页面
				insertComment(result.html, result.parentID, result.commentOrder);
				// 清空表单
				$('#comment_content').val('');
				// 更新验证码
				updateCaptcha(result.newCaptchaSeed, result.newCaptcha);
			} else {
				alert(result.msg);
			}
		},
		error: function() {
			alert(__('评论发送失败'));
		},
		complete: function() {
			$('#comment_submit').text(__('发送'));
			$('#comment_submit').prop('disabled', false);
		}
	});
}

PHP 处理函数

服务器端处理评论提交:

// functions.php
function ajax_post_comment(){
	// 1. IP 黑名单检查
	if (argon_is_ip_blocked_global()) {
		exit(json_encode(array(
			'status' => 'failed',
			'msg' => __('您的 IP 已被限制访问', 'argon'),
			'isAdmin' => current_user_can('level_7')
		)));
	}
	
	// 2. 私密评论权限检查
	$parentID = $_POST['comment_parent'];
	if (is_comment_private_mode($parentID)){
		if (!user_can_view_comment($parentID)){
			exit(json_encode(array(
				'status' => 'failed',
				'msg' =>  __('不能回复其他人的悄悄话评论', 'argon'),
				'isAdmin' => current_user_can('level_7')
			)));
		}
	}
	
	// 3. QQ 邮箱处理
	if (get_option('argon_comment_enable_qq_avatar') == 'true'){
		if (check_qqnumber($_POST['email'])){
			$_POST['qq'] = $_POST['email'];
			$_POST['email'] .= "@qq.com";
		}
	}
	
	// 4. CSRF nonce 校验
	if (!isset($_POST['argon_nonce']) || !wp_verify_nonce($_POST['argon_nonce'], 'argon_comment')) {
		exit(json_encode(array(
			'status' => 'failed',
			'msg' => __('请求已失效,请刷新页面后重试', 'argon'),
			'isAdmin' => current_user_can('level_7')
		)));
	}
	
	// 5. Honeypot 反垃圾检查
	if (!empty($_POST['argon_comment_honeypot'])) {
		exit(json_encode(array(
			'status' => 'failed',
			'msg' => __('Spam detected', 'argon'),
			'isAdmin' => current_user_can('level_7')
		)));
	}
	
	// 6. 速率限制(防止刷评论)
	$rate_enable = get_option('argon_rate_limit_enable', 'true');
	if ($rate_enable === 'true') {
		$ip = isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0] : $_SERVER['REMOTE_ADDR'];
		$ip = sanitize_text_field($ip);
		$rate_key = 'argon_rate_cmt_' . md5($ip);
		$state = get_transient($rate_key);
		$now = time();
		$window = intval(get_option('argon_rate_limit_window', 300)); // 窗口秒数(默认 5 分钟)
		$max_count = intval(get_option('argon_rate_limit_max_count', 5)); // 窗口内最大次数
		$min_interval = intval(get_option('argon_rate_limit_min_interval', 10)); // 两次最小间隔(秒)
		
		// 检查最小间隔
		if (!is_array($state)) {
			$state = array('count' => 0, 'start' => $now, 'last' => 0);
		}
		if ($state['last'] > 0 && ($now - intval($state['last'])) < $min_interval) {
			exit(json_encode(array(
				'status' => 'failed',
				'msg' => __('您评论过快,请稍后再试', 'argon'),
				'isAdmin' => current_user_can('level_7')
			)));
		}
		
		// 检查窗口内次数
		if (($now - intval($state['start'])) < $window && intval($state['count']) >= $max_count) {
			exit(json_encode(array(
				'status' => 'failed',
				'msg' => __('操作过于频繁,请稍后再试', 'argon'),
				'isAdmin' => current_user_can('level_7')
			)));
		}
		
		// 更新速率状态
		if (($now - intval($state['start'])) >= $window) {
			$state['start'] = $now;
			$state['count'] = 0;
		}
		$state['count'] = intval($state['count']) + 1;
		$state['last'] = $now;
		set_transient($rate_key, $state, $window);
	}
	
	// 7. 提交评论
	$comment = wp_handle_comment_submission(wp_unslash($_POST));
	if (is_wp_error($comment)){
		$msg = $comment->get_error_message();
		exit(json_encode(array(
			'status' => 'failed',
			'msg' => $msg,
			'isAdmin' => current_user_can('level_7')
		)));
	}
	
	// 8. 设置 Cookie
	$user = wp_get_current_user();
	do_action('set_comment_cookies', $comment, $user);
	
	// 9. 生成评论 HTML
	$html = wp_list_comments(
		array(
			'type'      => 'comment',
			'callback'  => 'argon_comment_format',
			'echo'      => false
		),
		array($comment)
	);
	
	// 10. 生成新验证码
	$newCaptchaSeed = get_comment_captcha_seed(true);
	$newCaptcha = get_comment_captcha($newCaptchaSeed);
	
	// 11. 返回结果
	exit(json_encode(array(
		'status' => 'success',
		'html' => $html,
		'id' => $comment->comment_ID,
		'parentID' => $comment->comment_parent,
		'commentOrder' => (get_option("comment_order") == "" ? "desc" : get_option("comment_order")),
		'newCaptchaSeed' => $newCaptchaSeed,
		'newCaptcha' => $newCaptcha,
		'isAdmin' => current_user_can('level_7'),
		'isLogin' => is_user_logged_in()
	)));
}
add_action('wp_ajax_ajax_post_comment', 'ajax_post_comment');
add_action('wp_ajax_nopriv_ajax_post_comment', 'ajax_post_comment');

Markdown 解析

评论支持 Markdown 语法,使用 Parsedown 库解析:

// functions.php
require_once(get_template_directory() . '/parsedown.php');

function comment_markdown_parse($comment_content){
	// 允许评论中额外的 HTML 标签
	global $allowedtags;
	$allowedtags['pre'] = array('class' => array());
	$allowedtags['i'] = array('class' => array(), 'aria-hidden' => array());
	$allowedtags['img'] = array('src' => array(), 'alt' => array(), 'class' => array());
	$allowedtags['ol'] = array();
	$allowedtags['ul'] = array();
	$allowedtags['li'] = array();
	$allowedtags['span'] = array('class' => array(), 'style' => array(), 'title' => array());
	$allowedtags['a']['class'] = array();
	$allowedtags['a']['data-src'] = array();
	$allowedtags['a']['target'] = array();
	$allowedtags['h1'] = $allowedtags['h2'] = $allowedtags['h3'] = $allowedtags['h4'] = $allowedtags['h5'] = $allowedtags['h6'] = array();
	
	// 解析 Markdown
	$parsedown = new _Parsedown();
	$res = $parsedown->text($comment_content);
	
	// 为链接添加 target="_blank"
	$res = preg_replace(
		'/<a (.*?)>(.*?)<\/a>/',
		'<a $1 target="_blank">$2</a>',
		$res
	);
	
	return $res;
}

// 评论发送前处理
function post_comment_preprocessing($comment){
	// 保存评论未经 Markdown 解析的源码
	$_POST['comment_content_source'] = $comment['comment_content'];
	
	// 应用评论宏(黑幕、彩幕等)
	$comment['comment_content'] = argon_apply_comment_macros($comment['comment_content']);
	
	// Markdown 解析
	if ($_POST['use_markdown'] == 'true' && get_option("argon_comment_allow_markdown") != "false"){
		$comment['comment_content'] = comment_markdown_parse($comment['comment_content']);
	}
	
	return $comment;
}
add_filter('preprocess_comment', 'post_comment_preprocessing');

评论宏

主题支持多种评论宏,用于实现特殊效果:

// functions.php
function argon_apply_comment_macros($text){
	// 黑幕:{{黑幕|内容}} 或 {{黑幕|内容|提示}}
	$text = preg_replace_callback('/\{\{黑幕\|([\s\S]*?)(?:\|([\s\S]*?))?\}\}/u', function($m){
		$content = trim($m[1]);
		$title = isset($m[2]) ? trim($m[2]) : '你知道的太多了';
		return '<span class="heimu"' . (strlen($title) ? ' title="' . htmlspecialchars($title, ENT_QUOTES) . '"' : '') . '>' . htmlspecialchars($content) . '</span>';
	}, $text);
	
	// 彩幕:{{彩幕|内容|背景色|提示|前景色}}
	$text = preg_replace_callback('/\{\{彩幕\|([\s\S]*?)\}\}/u', function($m){
		$parts = explode('|', $m[1]);
		$content = isset($parts[0]) ? trim($parts[0]) : '';
		$bg = isset($parts[1]) ? trim($parts[1]) : '#252525';
		$tip = isset($parts[2]) ? trim($parts[2]) : '你知道的太多了';
		$fg = isset($parts[3]) ? trim($parts[3]) : '';
		
		// 如果没有指定前景色,根据背景色亮度自动计算
		if (empty($fg)) {
			$hex = ltrim($bg, '#');
			if (strlen($hex) == 6) {
				$r = hexdec(substr($hex, 0, 2));
				$g = hexdec(substr($hex, 2, 2));
				$b = hexdec(substr($hex, 4, 2));
				$luma = 0.2126 * $r + 0.7152 * $g + 0.0722 * $b;
				$fg = ($luma >= 180) ? '#000' : '#fff';
			} else {
				$fg = '#fff';
			}
		}
		
		$style = '--curtain-bg: ' . htmlspecialchars($bg, ENT_QUOTES) . '; --curtain-fg: ' . htmlspecialchars($fg, ENT_QUOTES) . ';';
		return '<span class="color-curtain"' . (strlen($tip) ? ' title="' . htmlspecialchars($tip, ENT_QUOTES) . '"' : '') . ' style="' . $style . '">' . htmlspecialchars($content) . '</span>';
	}, $text);
	
	// 文字模糊:{{文字模糊|内容|提示|颜色|时间}}
	$text = preg_replace_callback('/\{\{文字模糊\|([\s\S]*?)\}\}/u', function($m){
		$parts = explode('|', $m[1]);
		$content = isset($parts[0]) ? trim($parts[0]) : '';
		$tip = isset($parts[1]) ? trim($parts[1]) : '你知道的太多了';
		$color = isset($parts[2]) ? trim($parts[2]) : '';
		$time = isset($parts[3]) ? trim($parts[3]) : '0.2';
		$style = '--text-blur-transition-time: ' . preg_replace('/[^0-9\.]/', '', $time) . 's;';
		if (strlen($color) > 0) {
			$style .= ' --text-blur-color: ' . htmlspecialchars($color, ENT_QUOTES) . ';';
		}
		return '<span class="text-blur"' . (strlen($tip) ? ' title="' . htmlspecialchars($tip, ENT_QUOTES) . '"' : '') . ' style="' . $style . '">' . htmlspecialchars($content) . '</span>';
	}, $text);
	
	return $text;
}
add_filter('comment_text', 'argon_comment_text_render', 9);

使用示例:

  • {{黑幕|剧透内容}} - 鼠标悬停显示
  • {{彩幕|彩色文字|#ff0000}} - 彩色背景
  • {{文字模糊|模糊文字}} - 鼠标悬停清晰

6. 说说功能

自定义文章类型

说说是一个独立的自定义文章类型,类似微博的短内容发布功能:

// functions.php
add_action('init', 'init_shuoshuo');
function init_shuoshuo(){
	$labels = array(
		'name' => __('说说', 'argon'),
		'singular_name' => __('说说', 'argon'),
		'add_new' => __('发表说说', 'argon'),
		'add_new_item' => __('发表说说', 'argon'),
		'edit_item' => __('编辑说说', 'argon'),
		'new_item' => __('新说说', 'argon'),
		'view_item' => __('查看说说', 'argon'),
		'search_items' => __('搜索说说', 'argon'),
		'not_found' => __('暂无说说', 'argon'),
		'not_found_in_trash' => __('没有已遗弃的说说', 'argon'),
		'parent_item_colon' => '',
		'menu_name' => __('说说', 'argon')
	);
	$args = array(
		'labels' => $labels,
		'public' => true,
		'publicly_queryable' => true,
		'show_ui' => true,
		'show_in_menu' => true,
		'exclude_from_search' => true,
		'query_var' => true,
		'rewrite' => array(
			'slug' => 'shuoshuo',
			'with_front' => false
		),
		'capability_type' => 'post',
		'has_archive' => false,
		'hierarchical' => false,
		'menu_position' => null,
		'menu_icon' => 'dashicons-format-quote',
		'supports' => array('editor', 'author', 'title', 'custom-fields', 'comments')
	);
	register_post_type('shuoshuo', $args);
}

页面模板

说说页面使用独立的模板文件 shuoshuo.php

// shuoshuo.php
/*
Template Name: 说说
*/
query_posts("post_type=shuoshuo&post_status=publish&posts_per_page=-1");

说说内容模板

说说内容通过 template-parts/content-shuoshuo.php 渲染:

<div class="shuoshuo-item card">
	<div class="card-body">
		<div class="shuoshuo-author">
			<?php echo get_avatar(get_the_author_meta('ID'), 40); ?>
			<span class="shuoshuo-author-name">
				<?php the_author(); ?>
			</span>
		</div>
		<div class="shuoshuo-content">
			<?php the_content(); ?>
		</div>
		<div class="shuoshuo-meta">
			<span class="shuoshuo-time">
				<?php echo get_the_date('Y-m-d H:i'); ?>
			</span>
			<span class="shuoshuo-comment-count">
				<?php comments_number('0 条评论', '1 条评论', '% 条评论'); ?>
			</span>
		</div>
	</div>
</div>

说说操作按钮

支持点赞、评论、分享等操作,通过 template-parts/shuoshuo-operations.php 实现。

折叠长说说

当说说内容超过一定长度时自动折叠:

// argontheme.js
if (argonConfig.fold_long_shuoshuo) {
	$('.shuoshuo-content').each(function() {
		let $content = $(this);
		if ($content.height() > 300) {
			$content.addClass('folded');
			$content.after('<a class="unfold-btn">展开</a>');
		}
	});
}

7. AI 摘要功能

功能概述

AI 摘要功能允许为文章自动生成摘要,支持多种 AI 服务提供商。

查询接口

通过独立的 PHP 文件 ai-summary-query.php 处理 AI 摘要请求:

// ai-summary-query.php
$wp_load_path = dirname(dirname(dirname(dirname(__FILE__)))) . '/wp-load.php';
if (!file_exists($wp_load_path)) $wp_load_path = $_SERVER['DOCUMENT_ROOT'] . '/wp-load.php';
require_once($wp_load_path);

安全防护

实现了完善的 IP 访问限制机制:

/**
 * 获取客户端真实 IP
 * 优先级CF-Connecting-IP > X-Real-IP > X-Forwarded-For > REMOTE_ADDR
 */
function argon_ai_query_get_client_ip() {
	$ip = '';
	
	// Cloudflare
	if (!empty($_SERVER['HTTP_CF_CONNECTING_IP'])) {
		$ip = $_SERVER['HTTP_CF_CONNECTING_IP'];
	}
	// Nginx proxy_pass 或其他反向代理
	elseif (!empty($_SERVER['HTTP_X_REAL_IP'])) {
		$ip = $_SERVER['HTTP_X_REAL_IP'];
	}
	// 通过代理转发(取第一个 IP
	elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
		$ip = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0];
	}
	// 直连 IP
	else {
		$ip = $_SERVER['REMOTE_ADDR'];
	}
	
	return trim($ip);
}

访问频率限制

/**
 * 检查 IP 访问频率限制
 * @return bool|string true 表示允许访问,字符串表示错误信息
 */
function argon_ai_query_check_rate_limit() {
	$client_ip = argon_ai_query_get_client_ip();
	if (empty($client_ip)) {
		return __('无法获取客户端 IP', 'argon');
	}
	
	$transient_key = 'ai_query_lock_' . md5($client_ip);
	$rate_limit_key = 'ai_query_rate_' . md5($client_ip);
	
	// 检查是否有正在进行的查询(单线程限制)
	if (get_transient($transient_key)) {
		return __('请等待上一次查询完成', 'argon');
	}
	
	// 检查访问频率60秒内最多10次
	$access_count = get_transient($rate_limit_key);
	if ($access_count === false) {
		set_transient($rate_limit_key, 1, 60);
	} else {
		if ($access_count >= 10) {
			return __('访问过于频繁,请稍后再试', 'argon');
		}
		set_transient($rate_limit_key, $access_count + 1, 60);
	}
	
	// 设置查询锁3秒超时
	set_transient($transient_key, 1, 3);
	
	return true;
}

AI 服务配置

在后台设置页面配置 AI 服务:

  • API 端点 URL
  • API 密钥
  • 模型名称
  • 请求参数(温度、最大 token 数等)
  • 超时设置

前端调用

// argontheme.js
function loadAISummary(postId) {
	$.ajax({
		url: argonConfig.wp_path + '?argon_ai_query=1',
		type: 'POST',
		data: {
			post_id: postId
		},
		success: function(response) {
			$('#ai-summary-content').html(response.summary);
		}
	});
}

8. 后台设置系统

设置页面结构

settings.php 是主题的后台设置页面,包含 7000+ 行代码(当前仓库约 7273 行),提供完整的主题配置界面。

设置分类

设置页面分为多个选项卡:

  1. 外观设置 - 主题色、布局、卡片样式
  2. 功能设置 - PJAX、懒加载、代码高亮
  3. 文章设置 - 文章列表样式、摘要长度
  4. 评论设置 - 评论验证码、邮件通知
  5. 说说设置 - 说说页面配置
  6. AI 设置 - AI 摘要服务配置
  7. 性能优化 - 资源合并、缓存控制
  8. 高级设置 - 自定义 CSS/JS、SEO

选项存储

所有设置通过 WordPress Options API 存储:

// 保存设置
update_option('argon_theme_color', $_POST['argon_theme_color']);

// 读取设置
$theme_color = get_option('argon_theme_color', '#5e72e4');

设置验证

提交设置时进行安全验证:

// settings.php
if (isset($_POST['save'])) {
	// 验证 nonce
	check_admin_referer('argon_theme_options');
	
	// 验证权限
	if (!current_user_can('manage_options')) {
		wp_die(__('权限不足', 'argon'));
	}
	
	// 保存设置
	foreach ($_POST as $key => $value) {
		if (strpos($key, 'argon_') === 0) {
			update_option($key, sanitize_text_field($value));
		}
	}
	
	echo '<div class="updated"><p>设置已保存</p></div>';
}

动态设置界面

设置页面使用 jQuery 实现动态交互:

// settings.php 内嵌脚本
$(document).ready(function() {
	// 选项卡切换
	$('.nav-tab').click(function() {
		let target = $(this).data('target');
		$('.nav-tab').removeClass('nav-tab-active');
		$(this).addClass('nav-tab-active');
		$('.settings-section').hide();
		$('#' + target).show();
	});
	
	// 颜色选择器
	$('.color-picker').wpColorPicker();
	
	// 拖拽排序
	dragula([$('#sortable-list')[0]]);
});

AI API 配置表格

支持配置多个 AI 服务提供商:

<table class="argon-ai-api-table">
	<thead>
		<tr>
			<th>服务名称</th>
			<th>API 端点</th>
			<th>API 密钥</th>
			<th>模型</th>
			<th>状态</th>
			<th>操作</th>
		</tr>
	</thead>
	<tbody id="argon-unified-api-list">
		<?php
		$api_list = get_option('argon_ai_api_list', []);
		foreach ($api_list as $api) {
			echo '<tr>';
			echo '<td>' . esc_html($api['name']) . '</td>';
			echo '<td>' . esc_html($api['endpoint']) . '</td>';
			echo '<td>***</td>';
			echo '<td>' . esc_html($api['model']) . '</td>';
			echo '<td>' . ($api['enabled'] ? '启用' : '禁用') . '</td>';
			echo '<td><button class="edit-api">编辑</button></td>';
			echo '</tr>';
		}
		?>
	</tbody>
</table>

9. 性能优化

资源合并

主题支持将多个 CSS 和 JS 文件合并为单个文件:

// functions.php
function argon_merge_assets() {
	$css_files = [
		'assets/css/bootstrap/bootstrap.min.css',
		'assets/css/argon.min.css',
		'style.css'
	];
	
	$merged_css = '';
	foreach ($css_files as $file) {
		$merged_css .= file_get_contents(get_template_directory() . '/' . $file);
	}
	
	file_put_contents(
		get_template_directory() . '/assets/argon_css_merged.css',
		$merged_css
	);
}

懒加载

图片懒加载通过 Lazy Load 库实现:

// argontheme.js
function initLazyload() {
	if (!argonConfig.lazyload) return;
	
	$('img[data-src]').lazyload({
		effect: argonConfig.lazyload_effect,
		threshold: argonConfig.lazyload_threshold,
		failure_limit: 10
	});
}

强制刷新缓存

提供强制刷新功能,用于更新后清除客户端缓存:

// functions.php
function argon_is_force_refresh_enabled() {
	$enabled_time = get_option('argon_force_refresh_enabled_time', 0);
	if ($enabled_time == 0) {
		return false;
	}
	// 检查是否超过 1 小时
	if (time() - $enabled_time > 3600) {
		// 自动关闭
		update_option('argon_force_refresh_enabled_time', 0);
		return false;
	}
	return true;
}

function argon_get_assets_version() {
	if (argon_is_force_refresh_enabled()) {
		$enabled_time = get_option('argon_force_refresh_enabled_time', 0);
		return $GLOBALS['theme_version'] . '.r' . $enabled_time;
	}
	return $GLOBALS['theme_version'];
}

缓存控制

针对不同类型的资源设置不同的缓存策略:

// functions.php
function argon_static_resource_headers() {
	if (is_admin() || argon_is_force_refresh_enabled()) {
		return;
	}
	
	$request_uri = $_SERVER['REQUEST_URI'] ?? '';
	$static_extensions = array('.css', '.js', '.jpg', '.jpeg', '.png', '.gif', '.svg', '.woff', '.woff2', '.ttf', '.eot', '.ico');
	
	$is_static = false;
	foreach ($static_extensions as $ext) {
		if (strpos($request_uri, $ext) !== false) {
			$is_static = true;
			break;
		}
	}
	
	if ($is_static && !headers_sent()) {
		// 静态资源缓存 1 年
		header('Cache-Control: public, max-age=31536000, immutable', true);
	}
}
add_action('send_headers', 'argon_static_resource_headers', 30);

移动端缓存控制

禁止移动端浏览器缓存 HTML 页面,避免内容更新不及时:

// functions.php
function argon_prevent_mobile_cache() {
	if (wp_is_mobile() && !is_admin()) {
		header('Cache-Control: no-cache, no-store, must-revalidate');
		header('Pragma: no-cache');
		header('Expires: 0');
	}
}
add_action('send_headers', 'argon_prevent_mobile_cache');

10. 安全机制

HTTP 安全头部

设置安全相关的 HTTP 头部:

// functions.php
function argon_security_headers() {
	if (is_admin()) {
		return;
	}
	
	if (!headers_sent()) {
		// 使用 Content-Security-Policy 替代 X-Frame-Options
		// 允许同源嵌入,防止点击劫持
		header("Content-Security-Policy: frame-ancestors 'self'", false);
		
		// 移除 X-Frame-Options如果存在
		header_remove('X-Frame-Options');
	}
}
add_action('send_headers', 'argon_security_headers', 20);

AJAX 请求验证

所有 AJAX 请求都需要验证 nonce

// functions.php
function ajax_post_comment() {
	// 验证 nonce
	check_ajax_referer('post_comment', 'nonce');
	
	// 验证验证码
	if (argon_is_comment_captcha_enabled()) {
		verify_captcha();
	}
	
	// 处理评论...
}
add_action('wp_ajax_ajax_post_comment', 'ajax_post_comment');
add_action('wp_ajax_nopriv_ajax_post_comment', 'ajax_post_comment');

内容过滤

使用 WordPress 内置函数过滤用户输入:

// 过滤 HTML 标签
$comment_content = wp_filter_kses($_POST['comment']);

// 转义输出
echo esc_html($user_name);
echo esc_attr($user_email);
echo esc_url($user_url);

权限检查

在执行敏感操作前检查用户权限:

// functions.php
function user_edit_comment() {
	check_ajax_referer('edit_comment', 'nonce');
	
	$comment_id = intval($_POST['id']);
	$comment = get_comment($comment_id);
	
	// 权限检查:管理员或评论作者本人
	if (!current_user_can('edit_comment', $comment_id) && 
	    $comment->user_id != get_current_user_id()) {
		wp_send_json(array('status' => 'failed', 'reason' => '权限不足'));
	}
	
	// 执行编辑操作...
}

验证码系统

评论与部分交互功能支持验证码验证,用于减少机器人提交与恶意请求。验证码启用逻辑采用“评论独立开关 + 全局开关”组合:

  • 评论验证码开关:argon_comment_captcha_mode,取值为 enabled / disabled / global
  • 全局验证码开关:argon_need_captcha(兼容旧选项 argon_comment_need_captcha

当前版本的验证码实现包含:

  • 算术验证码:通过 captcha_calculation 生成挑战题,get_comment_captcha() 输出题目,get_comment_captcha_answer() 用于校验答案
  • 极验验证码 (Geetest 4):通过 geetest_validate(...) 校验前端提交的四个字段lot_number/captcha_output/pass_token/gen_time

评论场景是否启用验证码由 argon_is_comment_captcha_enabled() 决定:

function argon_is_comment_captcha_enabled() {
    $mode = get_option('argon_comment_captcha_mode', 'global');
    if ($mode === 'enabled') {
        return true;
    } elseif ($mode === 'disabled') {
        return false;
    }
    return argon_is_captcha_enabled();
}

11. 友链管理系统

功能概述

Argon 主题内置了一套独立的友链管理系统,支持友链的申请、审核、分组和展示,无需依赖第三方插件。

数据存储

友链数据不使用 WordPress 的 Links Manager API已废弃而是存储在 argon_friend_links 选项中,数据结构为 JSON 数组。该数组既包含展示所需字段,也包含审核与可用性检测的状态字段:

$links = get_option('argon_friend_links', array());
// 结构示例:
// [
//     {
//         'id' => 'fl_5f...',
//         'name' => '站点名称',
//         'url' => 'https://example.com',
//         'avatar' => '...',
//         'description' => '...',
//         'category' => '',
//         'email' => '',
//         'message' => '',
//         'status' => 'approved',  // pending, approved
//         'verified' => false,
//         'is_wordpress' => false,
//         'accessible' => true,
//         'last_check' => 1700000000,
//         'created_at' => 1700000000,
//         'updated_at' => 1700000000
//     },
//     ...
// ]

核心逻辑

主要逻辑在 functions.php 中实现:

  • argon_add_friend_link($data): 添加新友链
  • argon_update_friend_link($id, $data): 更新友链信息
  • argon_handle_link_application_v3($post_data): 处理友链申请

自动获取站点信息

在申请友链和后台新增友链时,主题会自动获取目标网站的基础信息。实现入口为 argon_fetch_site_info($url),其返回结构包含可用性与安全拦截相关的状态字段:

$info = array(
    'favicon' => '',
    'title' => '',
    'description' => '',
    'author_avatar' => '',
    'is_wordpress' => false,
    'accessible' => false,
    'blocked_by_waf' => false,
    'error_reason' => ''
);

核心流程包括:

  1. 使用模拟浏览器的请求头与 UA 进行 wp_remote_gettimeout 约 20 秒,允许最多 5 次重定向)
  2. 根据 HTTP 状态码与页面内容特征识别 WAF 拦截403/503/关键字命中),并写入 blocked_by_waferror_reason
  3. 在可访问的前提下解析 <title>meta description,并通过多种 <link rel="icon"> 规则获取 favicon必要时回退到 /favicon.ico
  4. 尝试检测站点是否为 WordPress页面特征 + /wp-json/ 探测),若为 WordPress 则进一步尝试获取作者头像信息

申请频率限制与安全校验

为了防止滥用,申请入口 argon_handle_link_application_v3($post_data) 依次执行以下校验:

  1. IP 黑名单:读取 argon_global_blocked_ips,支持精确匹配 / 通配符 / CIDR
  2. 频率限制:按“用户标识符”限制提交频率
    • 已登录用户:user_{ID}
    • 未登录用户:对 IP + User-Agent 计算哈希并截断(用于避免单纯按 IP 误伤共享网络)
    • 计数使用 transientflink_apply_{identifier}
    • 默认限制来自选项:argon_flink_apply_limit(默认 3argon_flink_apply_period(默认 3600 秒)
  3. Nonce 验证:校验字段 argon_link_apply_nonceaction 为 argon_link_apply
  4. 可选验证码:当全局验证码开启时,会调用 argon_verify_captcha('flink') 对友链申请场景进行验证

12. 短代码与小工具系统

Argon 主题内置了丰富的小工具区域和短代码支持,增强了内容展示的灵活性。

小工具区域 (Sidebars)

主题在 functions.phpargon_widgets_init 函数中注册了三个主要的小工具区域:

  1. 左侧栏小工具 (leftbar-tools)

    • 显示在页面左侧边栏。
    • 如果设置了小工具,会在侧栏增加一个 Tab 标签页。
  2. 右侧栏小工具 (rightbar-tools)

    • 仅在 "Argon 主题选项" 中选择 "三栏布局" 时显示。
    • 位于页面右侧。
  3. 站点概览额外内容 (leftbar-siteinfo-extra-tools)

    • 用于在左侧栏站点概览卡片下方添加额外内容。

注册代码示例:

function argon_widgets_init(){
    register_sidebar(
        array(
            'name'          => __('左侧栏小工具', 'argon'),
            'id'            => 'leftbar-tools',
            // ...
        )
    );
    // ...
}
add_action('widgets_init', 'argon_widgets_init');

短代码系统 (Shortcodes)

主题定义了大量自定义短代码,用于在文章中快速插入特殊样式或功能组件。所有短代码均在 functions.php 中通过 add_shortcode 注册。

主要短代码列表

  • 布局与样式[br], [label], [progressbar], [checkbox], [collapse]/[fold]
  • 提示框[alert], [admonition]
  • 功能组件[timeline], [github], [video]
  • 元数据[post_time], [post_modified_time], [hide_reading_time]
  • 其他[friendlinks], [sfriendlinks], [hidden]/[spoiler], [ref]

实现示例Alert 短代码

[alert] 短代码用于显示带颜色的提示框,支持 coloricon 参数。

// 注册短代码
add_shortcode('alert','shortcode_alert');

// 回调函数实现
function shortcode_alert($attr, $content=""){
    // 预处理内容
    $content = shortcode_content_preprocess($attr, $content);
    
    // 构建 HTML
    $out = "<div class='alert";
    $color = isset( $attr['color'] ) ? $attr['color'] : 'indigo';
    
    // 根据颜色参数添加对应的 CSS 类
    switch ($color){
        case 'indigo': $out .= " alert-primary"; break;
        case 'green':  $out .= " alert-success"; break;
        // ...
    }
    
    $out .= "'>";
    // ...
    return $out;
}

13. 扩展接口与 Hooks

Argon 主题提供了一些自定义的 Action 和 Filter Hooks方便开发者在不修改核心文件的情况下扩展主题功能。

主要 Hooks 列表

Filters (过滤器)

  1. argon_banner_title_html

    • 作用:过滤 Banner 标题的 HTML 内容。
    • 位置header.php
    • 参数$banner_title (当前标题)
  2. argon_page_background_url

    • 作用:过滤页面背景图片的 URL。
    • 位置header.php
    • 参数$url (设置中的背景 URL)
  3. argon_email_types

    • 作用:过滤邮件通知类型列表,可用于修改默认邮件模板或添加新类型。
    • 位置email-templates/base.php
    • 参数$types (包含邮件类型配置的数组)

Actions (动作)

  1. argon_cache_cleared
    • 作用:当主题缓存被清除时触发(如保存设置时)。
    • 位置functions.php

使用示例:

// 修改 Banner 标题后缀
add_filter('argon_banner_title_html', function($title) {
    return $title . ' <small>(Dev Mode)</small>';
});

// 自定义背景图片逻辑
add_filter('argon_page_background_url', function($url) {
    if (is_page('special')) {
        return 'https://example.com/special-bg.jpg';
    }
    return $url;
});

14. 国际化与多语言支持

Argon 主题完全支持国际化I18n允许开发者轻松创建多语言版本。

核心配置

  • Text Domain: argon
  • 语言包路径: /languages
  • 加载逻辑: functions.php 中的 theme_slug_setup 函数。
function theme_slug_setup() {
    // ...
    load_theme_textdomain('argon', get_template_directory() . '/languages');
}

翻译指南

  1. PHP 文件中 使用 WordPress 标准本地化函数:

    // 返回翻译字符串
    $text = __('Hello World', 'argon');
    
    // 直接输出翻译字符串
    _e('Settings', 'argon');
    
    // 带有上下文的翻译
    _x('Post', 'noun', 'argon');
    
  2. 创建语言包

    • 当前仓库未提供 languages/argon.pot 模板文件。
    • 可使用 Poedit 扫描主题源代码生成新的 .poText Domain 选择 argon),完成翻译后生成 .mo
    • 将生成的 .po/.mo 文件放在 languages/ 目录下即可被加载。

开发指南

本地开发环境搭建

环境要求

  • PHP 7.0 或更高版本
  • WordPress 4.4 或更高版本
  • MySQL 5.6 或更高版本
  • 支持 .htaccess 的 Web 服务器Apache/Nginx

安装步骤

  1. 安装 WordPress
  2. 将主题文件夹放置到 wp-content/themes/argon/
  3. 在 WordPress 后台启用主题
  4. 访问主题设置页面进行配置

开发工具推荐

  • 代码编辑器VS Code、PhpStorm
  • 浏览器开发工具Chrome DevTools、Firefox Developer Tools
  • 本地服务器XAMPP、MAMP、Local by Flywheel
  • 版本控制Git

调试技巧

启用 WordPress 调试模式

wp-config.php 中添加:

define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);

查看错误日志

错误日志位于 wp-content/debug.log

浏览器控制台

JavaScript 错误会显示在浏览器控制台中。使用 console.log() 输出调试信息:

console.log('argonConfig:', argonConfig);
console.log('PJAX loading:', pjaxLoading);

网络请求调试

使用浏览器开发工具的 Network 面板查看 AJAX 请求:

  • 检查请求 URL 和参数
  • 查看响应内容和状态码
  • 分析请求耗时

PJAX 调试

监听 PJAX 事件输出调试信息:

$(document).on('pjax:send', function() {
	console.log('PJAX: 开始加载');
});

$(document).on('pjax:complete', function() {
	console.log('PJAX: 加载完成');
});

$(document).on('pjax:error', function(xhr, textStatus, error) {
	console.error('PJAX 错误:', error);
});

常见开发任务

添加新的主题选项

  1. settings.php 中添加表单字段:
<tr>
	<th>新选项</th>
	<td>
		<input type="text" name="argon_new_option" 
		       value="<?php echo esc_attr(get_option('argon_new_option', '')); ?>" />
		<p class="description">选项说明</p>
	</td>
</tr>
  1. 在需要使用的地方读取选项:
$new_option = get_option('argon_new_option', '默认值');

修改文章列表样式

文章列表有三种预览样式,对应三个模板文件:

  • template-parts/content-preview-1.php - 标准卡片样式
  • template-parts/content-preview-2.php - 大图样式
  • template-parts/content-preview-3.php - 简洁列表样式

修改对应文件即可改变样式。

添加自定义 CSS

在后台设置页面的"高级设置"选项卡中,有"自定义 CSS"文本框,输入的 CSS 会自动添加到页面中。

或者直接修改 style.css 文件。

添加自定义 JavaScript

在后台设置页面的"高级设置"选项卡中,有"自定义 JavaScript"文本框。

或者在 argontheme.js 文件末尾添加代码。

修改评论表单

评论表单在 comments.php 文件中定义。可以修改表单字段、布局和样式。

创建新的页面模板

  1. 创建新的 PHP 文件,例如 custom-page.php
  2. 在文件开头添加模板声明:
<?php
/*
Template Name: 自定义页面
*/
?>
  1. 编写页面内容
  2. 在 WordPress 后台编辑页面时,可以在"页面属性"中选择该模板

主题更新

更新检查器

主题使用 plugin-update-checkerPuc v4实现自动更新检查。更新源由选项 argon_update_source 控制,不同取值会切换到不同的元数据地址:

// functions.php
require_once(get_template_directory() . '/theme-update-checker/plugin-update-checker.php');
$argon_update_source = get_option('argon_update_source');
switch ($argon_update_source) {
	case "stop":
		break;
	case "fastgit":
		Puc_v4_Factory::buildUpdateChecker('https://api.solstice23.top/argon/info.json?source=fastgit', get_template_directory() . '/functions.php', 'argon');
		break;
	case "cfworker":
		Puc_v4_Factory::buildUpdateChecker('https://api.solstice23.top/argon/info.json?source=cfworker', get_template_directory() . '/functions.php', 'argon');
		break;
	case "solstice23top":
		Puc_v4_Factory::buildUpdateChecker('https://api.solstice23.top/argon/info.json?source=0', get_template_directory() . '/functions.php', 'argon');
		break;
	case "github":
	default:
		Puc_v4_Factory::buildUpdateChecker('https://raw.githubusercontent.com/solstice23/argon-theme/master/info.json', get_template_directory() . '/functions.php', 'argon');
}

更新流程

  1. 主题通过更新检查器向 WordPress 更新系统注册可用版本信息
  2. 在后台“仪表盘 → 更新”或“外观 → 主题”中显示更新提示
  3. 管理员点击更新后,由 WordPress 负责下载并覆盖主题文件

手动更新

  1. 下载最新版本的主题文件
  2. 备份当前主题文件和数据库
  3. 删除旧的主题文件夹
  4. 上传新的主题文件夹
  5. 在后台重新激活主题
  6. 检查设置是否正常

多语言支持

翻译文件

主题支持多语言,翻译文件位于 languages/ 目录:

  • zh_TW.po / zh_TW.mo - 繁体中文
  • en_US.po / en_US.mo - 英文
  • ru_RU.po / ru_RU.mo - 俄文

添加新语言

当前仓库未提供 languages/argon.pot 模板文件。新增语言时可采用两种方式之一:

  1. 使用 Poedit 扫描主题源代码生成新的 .poText Domain 选择 argon),完成翻译后生成 .mo
  2. 使用 WP-CLI i18n 工具自行生成 POT再在 Poedit 中基于 POT 创建语言包

生成的 .po/.mo 文件放置到 languages/ 目录即可被 load_theme_textdomain('argon', ... ) 加载

在代码中使用翻译

PHP 中使用 __() 函数:

echo __('文本内容', 'argon');

JavaScript 中使用全局翻译函数:

// header.php 中定义翻译表
var translation = {
	'确定': '<?php _e("确定", "argon"); ?>',
	'取消': '<?php _e("取消", "argon"); ?>'
};

// argontheme.js 中使用
function __(text) {
	return translation[text] || text;
}

alert(__('确定'));

常见问题

样式问题

样式不生效

  1. 检查浏览器缓存强制刷新Ctrl+F5
  2. 在后台设置中启用"强制刷新缓存"
  3. 检查 CSS 选择器优先级
  4. 使用浏览器开发工具检查元素样式

夜间模式颜色异常

  1. 检查 CSS 变量是否正确定义
  2. 确认 html.darkmode 类是否正确添加
  3. 检查自定义 CSS 是否覆盖了夜间模式样式

响应式布局错乱

  1. 检查媒体查询断点
  2. 确认元素宽度设置正确
  3. 使用浏览器开发工具的响应式模式测试

功能问题

PJAX 加载失败

  1. 检查浏览器控制台是否有 JavaScript 错误
  2. 确认目标页面的 HTML 结构正确
  3. 检查 PJAX 容器选择器是否匹配
  4. 尝试禁用 PJAX 功能排查问题

评论发送失败

  1. 检查 AJAX 请求是否成功
  2. 确认 nonce 验证是否通过
  3. 检查验证码是否正确
  4. 查看 PHP 错误日志

图片懒加载不工作

  1. 确认图片标签使用了 data-src 属性
  2. 检查 Lazy Load 库是否正确加载
  3. 确认懒加载功能已在后台启用
  4. 检查浏览器控制台是否有错误

代码高亮显示异常

  1. 确认 Highlight.js 已加载(浏览器控制台 window.hljs 存在)
  2. 确认代码高亮已启用(argon_enable_code_highlight 为 trueargonConfig.code_highlight.enable 为 true
  3. 确认高亮主题 CSS 已加载footer.php 会输出 highlight 样式链接)
  4. PJAX 场景下检查 pjax:complete 是否触发 highlightJsRender()

性能问题

页面加载缓慢

  1. 启用资源合并功能
  2. 开启图片懒加载
  3. 使用 CDN 加速静态资源
  4. 优化数据库查询
  5. 启用服务器缓存(如 Redis、Memcached
  6. 压缩图片大小

内存占用过高

  1. 减少同时加载的文章数量
  2. 优化图片尺寸
  3. 清理无用的插件和主题
  4. 增加 PHP 内存限制(在 wp-config.php 中设置 WP_MEMORY_LIMIT

JavaScript 执行卡顿

  1. 减少 DOM 操作频率
  2. 使用事件委托代替多个事件监听器
  3. 优化瀑布流布局计算
  4. 使用 requestAnimationFrame 优化动画

兼容性问题

插件冲突

  1. 逐个禁用插件排查冲突源
  2. 检查插件是否修改了主题依赖的 WordPress 核心功能
  3. 查看插件和主题的 JavaScript 是否有命名冲突
  4. 联系插件作者或主题作者寻求解决方案

浏览器兼容性

主题主要支持现代浏览器:

  • Chrome 60+
  • Firefox 60+
  • Safari 12+
  • Edge 79+

不支持 IE 浏览器。如需支持旧版浏览器,需要添加 polyfill。

PHP 版本兼容性

主题要求 PHP 7.0+。如果服务器 PHP 版本过低,需要升级 PHP 版本。

最佳实践

代码组织

模块化开发

将功能拆分为独立的模块,便于维护和复用:

// 评论模块
let CommentModule = {
	init: function() {
		this.bindEvents();
	},
	bindEvents: function() {
		$('#comment-submit').on('click', this.submitComment);
	},
	submitComment: function() {
		// 提交评论逻辑
	}
};

// 初始化
CommentModule.init();

避免全局污染

使用立即执行函数表达式IIFE封装代码

(function($) {
	'use strict';
	
	// 私有变量和函数
	let privateVar = 'value';
	
	function privateFunction() {
		// ...
	}
	
	// 公开接口
	window.MyModule = {
		publicMethod: function() {
			// ...
		}
	};
	
})(jQuery);

使用命名空间

避免函数名冲突:

let ArgonTheme = ArgonTheme || {};

ArgonTheme.Utils = {
	getCookie: function(name) {
		// ...
	},
	setCookie: function(name, value) {
		// ...
	}
};

性能优化

减少 HTTP 请求

  1. 合并 CSS 和 JavaScript 文件
  2. 使用 CSS Sprites 合并小图标
  3. 使用字体图标代替图片图标
  4. 启用浏览器缓存

优化资源加载

  1. 异步加载非关键 JavaScript
  2. 延迟加载图片和视频
  3. 使用 WebP 格式图片
  4. 压缩和混淆 JavaScript 代码

数据库优化

  1. 使用索引加速查询
  2. 避免 N+1 查询问题
  3. 使用对象缓存(如 Redis
  4. 定期清理无用数据

前端优化

  1. 减少 DOM 操作
  2. 使用 CSS3 动画代替 JavaScript 动画
  3. 避免强制同步布局
  4. 使用虚拟滚动处理长列表

安全实践

输入验证

  1. 验证所有用户输入
  2. 使用白名单而非黑名单
  3. 限制输入长度和格式
  4. 防止 SQL 注入和 XSS 攻击

输出转义

  1. 使用 esc_html() 转义 HTML 内容
  2. 使用 esc_attr() 转义 HTML 属性
  3. 使用 esc_url() 转义 URL
  4. 使用 esc_js() 转义 JavaScript 字符串

权限控制

  1. 检查用户权限后再执行敏感操作
  2. 使用 current_user_can() 验证权限
  3. 为 AJAX 请求添加 nonce 验证
  4. 限制文件上传类型和大小

数据保护

  1. 使用 HTTPS 加密传输
  2. 敏感数据加密存储
  3. 定期备份数据库
  4. 设置合理的文件权限

可维护性

代码注释

  1. 为复杂逻辑添加注释
  2. 使用 JSDoc 格式注释函数
  3. 注释应说明"为什么"而非"是什么"
  4. 保持注释与代码同步更新

版本控制

  1. 使用 Git 管理代码
  2. 编写清晰的提交信息
  3. 使用分支管理功能开发
  4. 定期合并和清理分支

文档编写

  1. 维护完整的开发文档
  2. 记录 API 接口和参数
  3. 提供使用示例
  4. 更新变更日志

代码审查

  1. 定期审查代码质量
  2. 检查是否遵循编码规范
  3. 识别潜在的性能问题
  4. 确保代码可读性

扩展开发

创建子主题

如果需要大量自定义修改,建议创建子主题:

  1. 创建子主题目录 wp-content/themes/argon-child/

  2. 创建 style.css

/*
Theme Name: Argon Child
Template: argon
Version: 1.0.0
*/
  1. 创建 functions.php
<?php
function argon_child_enqueue_styles() {
	wp_enqueue_style('argon-parent-style', get_template_directory_uri() . '/style.css');
}
add_action('wp_enqueue_scripts', 'argon_child_enqueue_styles');
  1. 在 WordPress 后台启用子主题

  2. 在子主题中覆盖父主题的模板文件或添加新功能

开发插件扩展

为主题开发配套插件:

<?php
/*
Plugin Name: Argon Extension
Description: Argon 主题扩展插件
Version: 1.0.0
*/

// 添加新功能
function argon_extension_feature() {
	// 功能代码
}
add_action('init', 'argon_extension_feature');

// 添加短代码
function argon_custom_shortcode($atts) {
	return '<div class="custom-content">自定义内容</div>';
}
add_shortcode('argon_custom', 'argon_custom_shortcode');

自定义 Widget

创建自定义侧边栏小工具:

<?php
class Argon_Custom_Widget extends WP_Widget {
	public function __construct() {
		parent::__construct(
			'argon_custom_widget',
			'Argon 自定义小工具',
			array('description' => '自定义小工具描述')
		);
	}
	
	public function widget($args, $instance) {
		echo $args['before_widget'];
		echo $args['before_title'];
		echo esc_html($instance['title']);
		echo $args['after_title'];
		
		// 小工具内容
		echo '<div class="custom-widget-content">';
		echo esc_html($instance['content']);
		echo '</div>';
		
		echo $args['after_widget'];
	}
	
	public function form($instance) {
		$title = !empty($instance['title']) ? $instance['title'] : '';
		$content = !empty($instance['content']) ? $instance['content'] : '';
		?>
		<p>
			<label for="<?php echo $this->get_field_id('title'); ?>">标题:</label>
			<input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" 
			       name="<?php echo $this->get_field_name('title'); ?>" 
			       type="text" value="<?php echo esc_attr($title); ?>">
		</p>
		<p>
			<label for="<?php echo $this->get_field_id('content'); ?>">内容:</label>
			<textarea class="widefat" id="<?php echo $this->get_field_id('content'); ?>" 
			          name="<?php echo $this->get_field_name('content'); ?>"><?php echo esc_textarea($content); ?></textarea>
		</p>
		<?php
	}
	
	public function update($new_instance, $old_instance) {
		$instance = array();
		$instance['title'] = sanitize_text_field($new_instance['title']);
		$instance['content'] = sanitize_text_field($new_instance['content']);
		return $instance;
	}
}

function register_argon_custom_widget() {
	register_widget('Argon_Custom_Widget');
}
add_action('widgets_init', 'register_argon_custom_widget');

添加自定义短代码

创建可在文章中使用的短代码:

// 简单短代码
function argon_alert_shortcode($atts, $content = null) {
	$atts = shortcode_atts(array(
		'type' => 'info',
		'title' => ''
	), $atts);
	
	$output = '<div class="alert alert-' . esc_attr($atts['type']) . '">';
	if (!empty($atts['title'])) {
		$output .= '<h4>' . esc_html($atts['title']) . '</h4>';
	}
	$output .= do_shortcode($content);
	$output .= '</div>';
	
	return $output;
}
add_shortcode('alert', 'argon_alert_shortcode');

// 使用方式:
// [alert type="warning" title="注意"]这是警告内容[/alert]

自定义文章类型

除了说说,还可以创建其他自定义文章类型:

function register_custom_post_type() {
	$args = array(
		'labels' => array(
			'name' => '作品集',
			'singular_name' => '作品'
		),
		'public' => true,
		'has_archive' => true,
		'rewrite' => array('slug' => 'portfolio'),
		'supports' => array('title', 'editor', 'thumbnail', 'excerpt'),
		'menu_icon' => 'dashicons-portfolio'
	);
	register_post_type('portfolio', $args);
}
add_action('init', 'register_custom_post_type');

添加自定义字段

为文章添加额外的元数据:

// 添加元框
function argon_add_custom_meta_box() {
	add_meta_box(
		'argon_custom_meta',
		'自定义字段',
		'argon_custom_meta_box_callback',
		'post',
		'normal',
		'high'
	);
}
add_action('add_meta_boxes', 'argon_add_custom_meta_box');

// 元框内容
function argon_custom_meta_box_callback($post) {
	wp_nonce_field('argon_save_custom_meta', 'argon_custom_meta_nonce');
	$value = get_post_meta($post->ID, '_argon_custom_field', true);
	?>
	<label for="argon_custom_field">自定义字段:</label>
	<input type="text" id="argon_custom_field" name="argon_custom_field" 
	       value="<?php echo esc_attr($value); ?>" style="width: 100%;">
	<?php
}

// 保存元数据
function argon_save_custom_meta($post_id) {
	if (!isset($_POST['argon_custom_meta_nonce'])) {
		return;
	}
	if (!wp_verify_nonce($_POST['argon_custom_meta_nonce'], 'argon_save_custom_meta')) {
		return;
	}
	if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
		return;
	}
	if (!current_user_can('edit_post', $post_id)) {
		return;
	}
	
	if (isset($_POST['argon_custom_field'])) {
		update_post_meta(
			$post_id,
			'_argon_custom_field',
			sanitize_text_field($_POST['argon_custom_field'])
		);
	}
}
add_action('save_post', 'argon_save_custom_meta');

测试与部署

本地测试

功能测试

  1. 测试所有页面模板是否正常显示
  2. 测试评论发送、回复、编辑功能
  3. 测试说说发布和显示
  4. 测试 PJAX 页面切换
  5. 测试夜间模式切换
  6. 测试响应式布局在不同设备上的表现
  7. 测试表单验证和错误提示

兼容性测试

  1. 在不同浏览器中测试Chrome、Firefox、Safari、Edge
  2. 测试移动端浏览器iOS Safari、Android Chrome
  3. 测试不同屏幕尺寸的显示效果
  4. 测试与常用插件的兼容性

性能测试

  1. 使用 Chrome DevTools 的 Lighthouse 进行性能评分
  2. 检查页面加载时间
  3. 分析资源加载瀑布图
  4. 测试大量数据时的性能表现

部署流程

准备工作

  1. 备份当前网站数据和数据库
  2. 检查服务器环境是否满足要求
  3. 准备主题文件和配置

上传主题

  1. 通过 FTP 上传主题文件到 wp-content/themes/argon/
  2. 或在 WordPress 后台上传主题 ZIP 包
  3. 确认文件权限正确(目录 755文件 644

配置主题

  1. 在 WordPress 后台启用主题
  2. 访问主题设置页面进行配置
  3. 设置主题色、布局等基本选项
  4. 配置评论系统和验证码
  5. 设置 AI 摘要服务(如需要)
  6. 配置性能优化选项

数据迁移

如果从其他主题迁移:

  1. 导出原主题的设置和数据
  2. 手动迁移必要的配置
  3. 检查文章格式是否正常
  4. 重新设置小工具和菜单
  5. 测试所有功能是否正常

上线检查

  1. 清除所有缓存浏览器、CDN、服务器
  2. 检查首页和主要页面显示
  3. 测试评论功能
  4. 检查移动端显示
  5. 验证 SEO 设置
  6. 测试表单提交
  7. 检查 HTTPS 证书

维护与监控

日常维护

  1. 定期备份网站数据和数据库
  2. 及时更新主题版本
  3. 更新 WordPress 核心和插件
  4. 清理垃圾评论和无用数据
  5. 优化数据库表

性能监控

  1. 监控网站加载速度
  2. 检查服务器资源使用情况
  3. 分析访问日志
  4. 监控错误日志
  5. 定期进行性能测试

安全维护

  1. 定期更新所有组件
  2. 检查文件完整性
  3. 监控异常登录尝试
  4. 定期更改管理员密码
  5. 检查用户权限设置
  6. 扫描恶意代码

故障排查

当出现问题时:

  1. 查看 WordPress 调试日志
  2. 检查 PHP 错误日志
  3. 查看浏览器控制台错误
  4. 检查服务器错误日志
  5. 禁用插件逐个排查
  6. 切换到默认主题测试
  7. 检查数据库连接
  8. 验证文件权限

参考资源

官方文档

开发工具

  • WordPress Debug Bar调试插件
  • Query Monitor性能监控插件
  • Theme Check主题检查插件
  • WP-CLIWordPress 命令行工具

学习资源

  • WordPress 主题开发手册
  • PHP 官方文档
  • JavaScript MDN 文档
  • CSS-Tricks 网站

社区支持

附录

常用 WordPress 函数

文章相关

the_title()              // 输出文章标题
the_content()            // 输出文章内容
the_excerpt()            // 输出文章摘要
the_permalink()          // 输出文章链接
the_post_thumbnail()     // 输出特色图片
get_the_date()           // 获取发布日期
get_the_author()         // 获取作者名称

评论相关

comments_number()        // 输出评论数量
wp_list_comments()       // 输出评论列表
comment_form()           // 输出评论表单
get_comment_author()     // 获取评论作者
comment_text()           // 输出评论内容

选项相关

get_option()             // 获取选项值
update_option()          // 更新选项值
delete_option()          // 删除选项
add_option()             // 添加选项

用户相关

is_user_logged_in()      // 检查用户是否登录
current_user_can()       // 检查用户权限
get_current_user_id()    // 获取当前用户 ID
wp_get_current_user()    // 获取当前用户对象

常用 jQuery 方法

// 选择器
$('#id')                 // ID 选择器
$('.class')              // 类选择器
$('element')             // 元素选择器

// DOM 操作
.html()                  // 获取或设置 HTML 内容
.text()                  // 获取或设置文本内容
.val()                   // 获取或设置表单值
.attr()                  // 获取或设置属性
.css()                   // 获取或设置样式
.addClass()              // 添加类
.removeClass()           // 移除类
.toggleClass()           // 切换类

// 事件
.on()                    // 绑定事件
.off()                   // 解绑事件
.click()                 // 点击事件
.change()                // 改变事件
.submit()                // 提交事件

// AJAX
$.ajax()                 // AJAX 请求
$.get()                  // GET 请求
$.post()                 // POST 请求

常用 CSS 类

Argon 主题基于 Bootstrap 4可以使用以下常用类

/* 布局 */
.container               // 容器
.row                     // 
.col-*                   // 

/* 间距 */
.m-*                     // margin
.p-*                     // padding
.mt-*, .mb-*, .ml-*, .mr-*  // 单边间距

/* 文本 */
.text-center             // 居中对齐
.text-left               // 左对齐
.text-right              // 右对齐
.text-primary            // 主色文本
.text-muted              // 灰色文本

/* 按钮 */
.btn                     // 按钮基类
.btn-primary             // 主按钮
.btn-secondary           // 次按钮
.btn-sm, .btn-lg         // 按钮尺寸

/* 卡片 */
.card                    // 卡片
.card-body               // 卡片内容
.card-header             // 卡片头部
.card-footer             // 卡片底部

主题钩子列表

Argon 主题提供的自定义钩子:

// 动作钩子
do_action('argon_before_header')      // 头部之前
do_action('argon_after_header')       // 头部之后
do_action('argon_before_content')     // 内容之前
do_action('argon_after_content')      // 内容之后
do_action('argon_before_footer')      // 底部之前
do_action('argon_after_footer')       // 底部之后
do_action('argon_before_comment')     // 评论之前
do_action('argon_after_comment')      // 评论之后

// 过滤钩子
apply_filters('argon_post_content', $content)        // 文章内容
apply_filters('argon_comment_content', $content)     // 评论内容
apply_filters('argon_excerpt_length', 200)           // 摘要长度
apply_filters('argon_theme_color', $color)           // 主题色

使用示例:

// 在头部之后添加内容
function custom_after_header() {
	echo '<div class="custom-notice">自定义通知</div>';
}
add_action('argon_after_header', 'custom_after_header');

// 修改摘要长度
function custom_excerpt_length($length) {
	return 150;
}
add_filter('argon_excerpt_length', 'custom_excerpt_length');

版本历史

  • v1.5.0 - 当前版本

    • 添加 AI 摘要功能
    • 优化性能和缓存机制
    • 改进安全性
    • 修复已知问题
  • v1.4.x - 功能增强

    • 添加说说功能
    • 改进评论系统
    • 优化移动端体验
  • v1.3.x - 稳定版本

    • 完善 PJAX 功能
    • 添加多种文章列表样式
    • 改进夜间模式
  • v1.2.x - 初始版本

    • 基础功能实现
    • Material Design 界面
    • 响应式布局

結語

本文檔用於內部開發協作,聚焦於主題架構、關鍵模組、開發規範與排查路徑,目標是讓開發者能以一致的方法理解、修改與驗證功能。

在日常開發與維護中,建議遵循以下原則:

  1. 以實際程式碼為準,文件同步更新,避免規格漂移
  2. 變更前先界定影響範圍頁面類型、PJAX、設定項、相依資源
  3. 變更後完成基本回歸(切換頁面、文章頁、評論、行動端、暗色模式)
  4. 優先保留相容性與可回退性,避免破壞既有站點行為
  5. 對安全與效能保持敏感(輸出轉義、權限檢查、資源載入與快取)

若需討論或提案,請依內部既定流程提交(需求/缺陷、代碼審查、發布/回滾),並附上可重現步驟與必要的日誌或截圖。