diff --git a/Plugin.php b/Plugin.php
new file mode 100644
index 0000000..b9f214b
--- /dev/null
+++ b/Plugin.php
@@ -0,0 +1,1244 @@
+contentEx = array('ImageCaptionWatermark_Plugin', 'parseContent');
+ Typecho_Plugin::factory('Widget_Abstract_Contents')->excerptEx = array('ImageCaptionWatermark_Plugin', 'parseContent');
+ Typecho_Plugin::factory('Widget_Archive')->footer = array('ImageCaptionWatermark_Plugin', 'addFooter');
+
+ return '插件已激活,请到设置页面配置参数。';
+ }
+
+ /**
+ * 禁用插件
+ */
+ public static function deactivate()
+ {
+ return '插件已禁用';
+ }
+
+ /**
+ * 插件配置面板
+ */
+ public static function config(Typecho_Widget_Helper_Form $form)
+ {
+ // 标题设置部分
+ $titleEnable = new Typecho_Widget_Helper_Form_Element_Radio(
+ 'titleEnable',
+ array('1' => '开启', '0' => '关闭'),
+ '1',
+ '启用图片标题',
+ '是否自动为文章中的图片添加标题'
+ );
+ $form->addInput($titleEnable);
+
+ $titlePosition = new Typecho_Widget_Helper_Form_Element_Select(
+ 'titlePosition',
+ array(
+ 'bottom-center' => '底部居中',
+ 'bottom-right' => '右下角',
+ 'bottom-left' => '左下角',
+ 'top-center' => '顶部居中',
+ 'top-right' => '右上角',
+ 'top-left' => '左上角'
+ ),
+ 'bottom-center',
+ '标题显示位置',
+ '标题在图片上的显示位置'
+ );
+ $form->addInput($titlePosition);
+
+ $titleMinWidth = new Typecho_Widget_Helper_Form_Element_Text(
+ 'titleMinWidth',
+ NULL,
+ '300',
+ '标题最小图片宽度',
+ '页面显示宽度大于此值(像素)的图片才显示标题'
+ );
+ $titleMinWidth->input->setAttribute('style', 'width: 120px;');
+ $form->addInput($titleMinWidth->addRule('isInteger', '请输入整数'));
+
+ // 新增:标题最小高度
+ $titleMinHeight = new Typecho_Widget_Helper_Form_Element_Text(
+ 'titleMinHeight',
+ NULL,
+ '300',
+ '标题最小图片高度',
+ '页面显示高度大于此值(像素)的图片才显示标题'
+ );
+ $titleMinHeight->input->setAttribute('style', 'width: 120px;');
+ $form->addInput($titleMinHeight->addRule('isInteger', '请输入整数'));
+
+ $titleChineseOnly = new Typecho_Widget_Helper_Form_Element_Radio(
+ 'titleChineseOnly',
+ array('1' => '开启', '0' => '关闭'),
+ '1',
+ '仅显示中文标题',
+ '开启:如果图片alt/title中没有中文,则不显示标题
关闭:显示所有标题'
+ );
+ $form->addInput($titleChineseOnly);
+
+ $titleColor = new Typecho_Widget_Helper_Form_Element_Text(
+ 'titleColor',
+ NULL,
+ '#FFFFFF',
+ '标题文字颜色',
+ '标题文字的颜色'
+ );
+ $titleColor->input->setAttribute('style', 'width: 150px;');
+ $form->addInput($titleColor);
+
+ $titleBgColor = new Typecho_Widget_Helper_Form_Element_Text(
+ 'titleBgColor',
+ NULL,
+ 'rgba(0,0,0,0.85)',
+ '标题背景颜色',
+ '标题背景的颜色'
+ );
+ $titleBgColor->input->setAttribute('style', 'width: 150px;');
+ $form->addInput($titleBgColor);
+
+ // 新增:标题背景透明度
+ $titleBgOpacity = new Typecho_Widget_Helper_Form_Element_Text(
+ 'titleBgOpacity',
+ NULL,
+ '0.85',
+ '标题背景透明度',
+ '0-1之间,1为不透明'
+ );
+ $titleBgOpacity->input->setAttribute('style', 'width: 100px;');
+ $titleBgOpacity->input->setAttribute('placeholder', '0.0-1.0');
+ $form->addInput($titleBgOpacity);
+
+ // 修改:标题显示分类
+ $titleIncludeCategories = new Typecho_Widget_Helper_Form_Element_Text(
+ 'titleIncludeCategories',
+ NULL,
+ '',
+ '标题显示分类',
+ '仅在此分类下的文章显示图片标题,留空表示所有分类都显示
多个分类用逗号间隔,如:技术,生活'
+ );
+ $titleIncludeCategories->input->setAttribute('style', 'width: 300px;');
+ $form->addInput($titleIncludeCategories);
+
+ $titleFontSize = new Typecho_Widget_Helper_Form_Element_Text(
+ 'titleFontSize',
+ NULL,
+ '14',
+ '标题字体大小',
+ '标题文字的大小(像素)'
+ );
+ $titleFontSize->input->setAttribute('style', 'width: 120px;');
+ $form->addInput($titleFontSize->addRule('isInteger', '请输入整数'));
+
+ $titlePadding = new Typecho_Widget_Helper_Form_Element_Text(
+ 'titlePadding',
+ NULL,
+ '8px 15px',
+ '标题内边距',
+ '标题的内边距,格式:上下 左右'
+ );
+ $titlePadding->input->setAttribute('style', 'width: 150px;');
+ $form->addInput($titlePadding);
+
+ // 新增:是否跳过横排组内的图片标题
+ $skipFlexGroupTitles = new Typecho_Widget_Helper_Form_Element_Radio(
+ 'skipFlexGroupTitles',
+ array('1' => '跳过', '0' => '不跳过'),
+ '1',
+ '跳过横排组内的图片标题',
+ '开启:在横排图片组(flex-group)中不显示单张图片的标题,只显示组标题
关闭:同时显示组标题和单图标题'
+ );
+ $form->addInput($skipFlexGroupTitles);
+
+ // 水印设置部分
+ $watermarkEnable = new Typecho_Widget_Helper_Form_Element_Radio(
+ 'watermarkEnable',
+ array('1' => '开启', '0' => '关闭'),
+ '1',
+ '启用图片水印',
+ '是否自动为文章中的图片添加水印'
+ );
+ $form->addInput($watermarkEnable);
+
+ $watermarkText = new Typecho_Widget_Helper_Form_Element_Text(
+ 'watermarkText',
+ NULL,
+ 'SHITOUCUO.COM',
+ '水印文字内容',
+ '水印文字的内容'
+ );
+ $watermarkText->input->setAttribute('style', 'width: 300px;');
+ $form->addInput($watermarkText);
+
+ $watermarkPosition = new Typecho_Widget_Helper_Form_Element_Select(
+ 'watermarkPosition',
+ array(
+ 'top-left' => '左上角',
+ 'top-center' => '顶部居中',
+ 'top-right' => '右上角',
+ 'center' => '正中央',
+ 'bottom-left' => '左下角',
+ 'bottom-center' => '底部居中',
+ 'bottom-right' => '右下角'
+ ),
+ 'top-center',
+ '水印显示位置',
+ '避免与标题重叠,建议使用顶部位置'
+ );
+ $form->addInput($watermarkPosition);
+
+ $watermarkMinWidth = new Typecho_Widget_Helper_Form_Element_Text(
+ 'watermarkMinWidth',
+ NULL,
+ '200',
+ '水印最小图片宽度',
+ '页面显示宽度大于此值(像素)的图片才添加水印'
+ );
+ $watermarkMinWidth->input->setAttribute('style', 'width: 120px;');
+ $form->addInput($watermarkMinWidth->addRule('isInteger', '请输入整数'));
+
+ // 新增:水印最小高度
+ $watermarkMinHeight = new Typecho_Widget_Helper_Form_Element_Text(
+ 'watermarkMinHeight',
+ NULL,
+ '500',
+ '水印最小图片高度',
+ '页面显示高度大于此值(像素)的图片才添加水印'
+ );
+ $watermarkMinHeight->input->setAttribute('style', 'width: 120px;');
+ $form->addInput($watermarkMinHeight->addRule('isInteger', '请输入整数'));
+
+ // 修改:水印显示分类
+ $watermarkIncludeCategories = new Typecho_Widget_Helper_Form_Element_Text(
+ 'watermarkIncludeCategories',
+ NULL,
+ '',
+ '水印显示分类',
+ '仅在此分类下的文章显示图片水印,留空表示所有分类都显示
多个分类用逗号间隔,如:技术,生活'
+ );
+ $watermarkIncludeCategories->input->setAttribute('style', 'width: 300px;');
+ $form->addInput($watermarkIncludeCategories);
+
+ $watermarkOpacity = new Typecho_Widget_Helper_Form_Element_Text(
+ 'watermarkOpacity',
+ NULL,
+ '0.7',
+ '水印透明度',
+ '0-1之间,1为不透明'
+ );
+ $watermarkOpacity->input->setAttribute('style', 'width: 100px;');
+ $watermarkOpacity->input->setAttribute('placeholder', '0.0-1.0');
+ $form->addInput($watermarkOpacity);
+
+ $watermarkFontSize = new Typecho_Widget_Helper_Form_Element_Text(
+ 'watermarkFontSize',
+ NULL,
+ '24',
+ '水印字体大小',
+ '文字水印的字体大小(像素)'
+ );
+ $watermarkFontSize->input->setAttribute('style', 'width: 100px;');
+ $form->addInput($watermarkFontSize->addRule('isInteger', '请输入整数'));
+
+ $watermarkFontColor = new Typecho_Widget_Helper_Form_Element_Text(
+ 'watermarkFontColor',
+ NULL,
+ 'rgba(255,255,255,0.9)',
+ '水印文字颜色',
+ '文字水印的颜色'
+ );
+ $watermarkFontColor->input->setAttribute('style', 'width: 150px;');
+ $form->addInput($watermarkFontColor);
+
+ // 性能设置部分
+ $batchSize = new Typecho_Widget_Helper_Form_Element_Text(
+ 'batchSize',
+ NULL,
+ '10',
+ '批量处理数量',
+ '每次同时处理的图片数量,减少一次性处理压力'
+ );
+ $batchSize->input->setAttribute('style', 'width: 120px;');
+ $form->addInput($batchSize->addRule('isInteger', '请输入整数'));
+
+ $processDelay = new Typecho_Widget_Helper_Form_Element_Text(
+ 'processDelay',
+ NULL,
+ '100',
+ '处理延迟(ms)',
+ '图片加载后延迟处理的时间(毫秒)'
+ );
+ $processDelay->input->setAttribute('style', 'width: 120px;');
+ $form->addInput($processDelay->addRule('isInteger', '请输入整数'));
+
+ $debugMode = new Typecho_Widget_Helper_Form_Element_Radio(
+ 'debugMode',
+ array('1' => '开启', '0' => '关闭'),
+ '0',
+ '调试模式',
+ '开启后在控制台显示处理信息(调试完成后建议关闭)'
+ );
+ $form->addInput($debugMode);
+ }
+
+ /**
+ * 个人用户配置面板
+ */
+ public static function personalConfig(Typecho_Widget_Helper_Form $form)
+ {
+ // 不需要个人配置
+ }
+
+ /**
+ * 处理文章内容
+ */
+ public static function parseContent($content, $widget, $lastResult)
+ {
+ $content = empty($lastResult) ? $content : $lastResult;
+
+ if ($widget instanceof Widget_Archive) {
+ $content = self::parseImages($content, $widget);
+ }
+
+ return $content;
+ }
+
+ /**
+ * 解析图片并添加标题和水印
+ */
+ private static function parseImages($text, $widget)
+ {
+ $options = Helper::options();
+ $config = $options->plugin('ImageCaptionWatermark');
+
+ if (!$config) {
+ return $text;
+ }
+
+ // 获取当前文章分类
+ $currentCategories = array();
+ if ($widget->categories && is_array($widget->categories)) {
+ foreach ($widget->categories as $category) {
+ if (isset($category['name'])) {
+ $currentCategories[] = $category['name'];
+ }
+ }
+ }
+
+ // 处理显示分类设置
+ $titleIncludeCategories = array();
+ if (!empty($config->titleIncludeCategories) && trim($config->titleIncludeCategories) !== '') {
+ $titleIncludeCategories = array_map('trim', explode(',', $config->titleIncludeCategories));
+ }
+
+ $watermarkIncludeCategories = array();
+ if (!empty($config->watermarkIncludeCategories) && trim($config->watermarkIncludeCategories) !== '') {
+ $watermarkIncludeCategories = array_map('trim', explode(',', $config->watermarkIncludeCategories));
+ }
+
+ // 检查当前分类是否在显示列表中
+ $isTitleIncluded = true; // 默认显示,除非设置了显示分类且当前分类不在其中
+ $isWatermarkIncluded = true; // 默认显示,除非设置了显示分类且当前分类不在其中
+
+ // 如果设置了显示分类,则检查当前分类是否在其中
+ if (!empty($titleIncludeCategories)) {
+ $isTitleIncluded = false;
+ foreach ($currentCategories as $category) {
+ if (in_array($category, $titleIncludeCategories)) {
+ $isTitleIncluded = true;
+ break;
+ }
+ }
+ }
+
+ if (!empty($watermarkIncludeCategories)) {
+ $isWatermarkIncluded = false;
+ foreach ($currentCategories as $category) {
+ if (in_array($category, $watermarkIncludeCategories)) {
+ $isWatermarkIncluded = true;
+ break;
+ }
+ }
+ }
+
+ // 匹配图片标签
+ $text = preg_replace_callback('/]*>/i', function($matches) use ($config, $isTitleIncluded, $isWatermarkIncluded) {
+ $imgTag = $matches[0];
+
+ // 跳过特定图片
+ if (preg_match('/class=["\'][^"\']*(no-watermark|no-caption)[^"\']*["\']/i', $imgTag)) {
+ return $imgTag;
+ }
+
+ // 检查图片是否在横排组中(通过父元素判断)
+ $skipTitle = false;
+ if ($config->skipFlexGroupTitles == '1') {
+ // 检查img标签周围是否有flexphoto-group的迹象
+ if (strpos($imgTag, 'no-title') !== false ||
+ preg_match('/class=["\'][^"\']*no-title[^"\']*["\']/i', $imgTag)) {
+ $skipTitle = true;
+ }
+ }
+
+ $newTag = $imgTag;
+
+ // 获取图片URL
+ $imgUrl = '';
+ if (preg_match('/src=["\']([^"\']+)["\']/', $imgTag, $srcMatch)) {
+ $imgUrl = $srcMatch[1];
+ }
+
+ // 获取标题(从alt或title属性)
+ $caption = '';
+ $hasChinese = false;
+
+ if (!$skipTitle) { // 只有需要显示标题时才处理
+ if (preg_match('/alt=["\']([^"\']*)["\']/', $imgTag, $altMatch)) {
+ $caption = $altMatch[1];
+ $hasChinese = self::hasChineseText($caption);
+ } elseif (preg_match('/title=["\']([^"\']*)["\']/', $imgTag, $titleMatch)) {
+ $caption = $titleMatch[1];
+ $hasChinese = self::hasChineseText($caption);
+ }
+ }
+
+ // 如果开启了仅显示中文标题,且没有中文,则清空标题
+ if ($config->titleChineseOnly == '1' && !$hasChinese) {
+ $caption = '';
+ } else {
+ // 提取中文部分
+ $caption = self::extractChineseText($caption);
+ }
+
+ // 添加水印数据属性(如果当前分类在显示列表中)
+ $watermarkData = '';
+ if ($isWatermarkIncluded && $config->watermarkEnable == '1' && !empty($config->watermarkText)) {
+ $watermarkClass = 'icw-watermark';
+ $watermarkData = ' data-watermark="' . htmlspecialchars($config->watermarkText) . '"';
+ $watermarkData .= ' data-watermark-position="' . htmlspecialchars($config->watermarkPosition) . '"';
+ $watermarkData .= ' data-watermark-minwidth="' . intval($config->watermarkMinWidth) . '"';
+ $watermarkData .= ' data-watermark-minheight="' . intval($config->watermarkMinHeight) . '"';
+
+ $newTag = preg_replace('/
titleEnable == '1' && !empty($caption) && !empty($imgUrl)) ||
+ ($isWatermarkIncluded && $config->watermarkEnable == '1' && !empty($imgUrl))) {
+
+ $wrapperClass = 'icw-wrapper';
+
+ // 添加标题数据(如果当前分类在显示列表中且需要显示标题)
+ $titleData = '';
+ if (!$skipTitle && $isTitleIncluded && $config->titleEnable == '1' && !empty($caption)) {
+ $titleData .= ' data-caption="' . htmlspecialchars($caption) . '"';
+ $titleData .= ' data-position="' . htmlspecialchars($config->titlePosition) . '"';
+ $titleData .= ' data-minwidth="' . intval($config->titleMinWidth) . '"';
+ $titleData .= ' data-minheight="' . intval($config->titleMinHeight) . '"';
+ $titleData .= ' data-chinese-only="' . $config->titleChineseOnly . '"';
+
+ if ($isWatermarkIncluded && $config->watermarkEnable == '1') {
+ $wrapperClass .= ' icw-has-both';
+ } else {
+ $wrapperClass .= ' icw-title-only';
+ }
+ } elseif ($isWatermarkIncluded && $config->watermarkEnable == '1') {
+ $wrapperClass .= ' icw-watermark-only';
+ }
+
+ // 如果是横排组内的图片,添加特殊标记
+ if ($skipTitle) {
+ $wrapperClass .= ' icw-in-flexgroup';
+ }
+
+ $newTag = '