write = array('CustomInlineTags_Plugin', 'parseTagsOnSave'); Typecho_Plugin::factory('Widget_Contents_Page_Edit')->write = array('CustomInlineTags_Plugin', 'parseTagsOnSave'); // 添加内容解析钩子 Typecho_Plugin::factory('Widget_Abstract_Contents')->contentEx = array('CustomInlineTags_Plugin', 'parseContent'); Typecho_Plugin::factory('Widget_Abstract_Contents')->excerptEx = array('CustomInlineTags_Plugin', 'parseContent'); // 添加编辑器脚本 - 关键:使用header钩子添加脚本 Typecho_Plugin::factory('admin/header.php')->header = array('CustomInlineTags_Plugin', 'addHeader'); Typecho_Plugin::factory('admin/write-post.php')->bottom = array('CustomInlineTags_Plugin', 'addEditorButton'); Typecho_Plugin::factory('admin/write-page.php')->bottom = array('CustomInlineTags_Plugin', 'addEditorButton'); return _t('插件已激活'); } /** * 禁用插件 */ public static function deactivate() { return _t('插件已禁用'); } /** * 插件配置面板 */ public static function config(Typecho_Widget_Helper_Form $form) { // 标签样式设置 $style = new Typecho_Widget_Helper_Form_Element_Textarea('tagStyle', NULL, "display: inline-block;\nbackground: #f0f0f0;\ncolor: #333;\npadding: 2px 8px;\nmargin: 0 4px;\nborder-radius: 12px;\nfont-size: 0.9em;\nfont-weight: normal;\ntext-decoration: none;", _t('标签样式'), _t('自定义标签的CSS样式')); $form->addInput($style); // 标签前缀 $prefix = new Typecho_Widget_Helper_Form_Element_Text('tagPrefix', NULL, '#', _t('标签前缀'), _t('在标签前显示的前缀符号')); $form->addInput($prefix); // 是否启用标签链接 $enableLink = new Typecho_Widget_Helper_Form_Element_Radio('enableLink', array( '1' => _t('启用'), '0' => _t('禁用') ), '1', _t('启用标签链接'), _t('点击标签是否跳转到标签页面')); $form->addInput($enableLink); // 伪静态标签链接格式 $tagUrlFormat = new Typecho_Widget_Helper_Form_Element_Text('tagUrlFormat', NULL, '/tag-{slug}.html', _t('标签链接格式'), _t('根据你的伪静态设置填写标签链接格式,{slug}会被替换为标签slug')); $form->addInput($tagUrlFormat); // 是否新窗口打开 $openNewWindow = new Typecho_Widget_Helper_Form_Element_Radio('openNewWindow', array( '1' => _t('是'), '0' => _t('否') ), '1', _t('新窗口打开'), _t('点击标签是否在新窗口打开')); $form->addInput($openNewWindow); } /** * 个人配置面板 */ public static function personalConfig(Typecho_Widget_Helper_Form $form) {} /** * 获取所有标签 */ private static function getAllTags() { if (!empty(self::$_allTags)) { return self::$_allTags; } try { $db = Typecho_Db::get(); $rows = $db->fetchAll($db->select('name') ->from('table.metas') ->where('type = ?', 'tag') ->order('name', Typecho_Db::SORT_ASC)); foreach ($rows as $row) { self::$_allTags[] = $row['name']; } } catch (Exception $e) { self::$_allTags = array(); } return self::$_allTags; } /** * 添加头部资源 */ public static function addHeader() { // 只在写文章/页面页面添加 if (strpos($_SERVER['REQUEST_URI'], 'write-post') !== false || strpos($_SERVER['REQUEST_URI'], 'write-page') !== false) { // 获取所有标签并转为JSON $allTags = self::getAllTags(); $tagsJson = json_encode($allTags); echo ''; // 在JavaScript中嵌入标签数据 echo ''; } } /** * 添加编辑器按钮 - 带标签联想搜索(本地搜索版) */ public static function addEditorButton() { ?> is('single')) { return $content; } // 获取插件配置 $options = Helper::options()->plugin('CustomInlineTags'); $prefix = $options->tagPrefix ?: '#'; $style = $options->tagStyle ?: "display: inline-block; background: #f0f0f0; color: #333; padding: 2px 8px; margin: 0 4px; border-radius: 12px; font-size: 0.9em; font-weight: normal; text-decoration: none;"; $className = 'custom-inline-tag'; $enableLink = isset($options->enableLink) ? $options->enableLink : '1'; $tagUrlFormat = isset($options->tagUrlFormat) ? $options->tagUrlFormat : '/tag-{slug}.html'; $openNewWindow = isset($options->openNewWindow) ? $options->openNewWindow : '1'; // 替换短代码为HTML $content = preg_replace_callback( '/\[tag\]([^\[\]]+?)\[\/tag\]/', function($matches) use ($prefix, $style, $className, $enableLink, $tagUrlFormat, $openNewWindow, $widget) { $tagName = htmlspecialchars(trim($matches[1]), ENT_QUOTES, 'UTF-8'); $displayName = $prefix . $tagName; if ($enableLink == '1' && $widget instanceof Widget_Archive) { // 获取标签链接 $tagUrl = ''; try { $db = Typecho_Db::get(); $tag = $db->fetchRow($db->select() ->from('table.metas') ->where('type = ?', 'tag') ->where('name = ?', $tagName) ->limit(1)); if ($tag) { // 使用Typecho的标签链接生成方法 if (method_exists($widget, 'permalink')) { // 创建临时对象获取标签链接 $reflection = new ReflectionClass($widget); $params = $reflection->getProperty('_params'); $params->setAccessible(true); $widgetParams = $params->getValue($widget); // 临时修改参数获取标签链接 $originalParams = $widgetParams; $widgetParams['type'] = 'tag'; $widgetParams['slug'] = $tag['slug']; // 尝试获取标签链接 try { $tagUrl = $widget->permalink; } catch (Exception $e) { // 如果失败,使用自定义格式 $tagSlug = urlencode($tag['slug']); $tagUrl = str_replace('{slug}', $tagSlug, $tagUrlFormat); $tagUrl = Typecho_Common::url($tagUrl, Helper::options()->index); } // 恢复原始参数 $params->setValue($widget, $originalParams); } else { // 使用自定义格式 $tagSlug = urlencode($tag['slug']); $tagUrl = str_replace('{slug}', $tagSlug, $tagUrlFormat); $tagUrl = Typecho_Common::url($tagUrl, Helper::options()->index); } } } catch (Exception $e) { // 出错时不添加链接 error_log('CustomInlineTags Error: ' . $e->getMessage()); } if ($tagUrl) { // 构建链接属性 $linkAttributes = sprintf('href="%s" class="%s" data-tag="%s" style="%s" title="查看标签相关文章"', htmlspecialchars($tagUrl), $className, $tagName, $style ); // 如果启用了新窗口打开,添加target="_blank" if ($openNewWindow == '1') { $linkAttributes .= ' target="_blank"'; } return sprintf('%s', $linkAttributes, $displayName ); } } // 如果不启用链接或找不到标签 return sprintf( '%s', $className, $tagName, $style, $displayName ); }, $content ); return $content; } /** * 保存文章时提取标签并保存到数据库 */ public static function parseTagsOnSave($contents, $widget) { $content = $contents['text']; $tags = array(); // 从短代码中提取标签 preg_match_all('/\[tag\]([^\[\]]+?)\[\/tag\]/', $content, $matches); if (!empty($matches[1])) { foreach ($matches[1] as $tag) { $tag = trim($tag); if (!empty($tag) && !in_array($tag, $tags)) { $tags[] = $tag; } } } // 如果找到了标签,添加到文章的标签字段 if (!empty($tags)) { // 获取现有的标签 $existingTags = isset($contents['tags']) ? $contents['tags'] : ''; $existingTagsArray = array_filter(array_map('trim', explode(',', $existingTags))); // 合并标签并去重 $allTags = array_unique(array_merge($existingTagsArray, $tags)); // 更新标签字段 $contents['tags'] = implode(',', $allTags); } return $contents; } }