From e965f6ed68f56682f4f83aae31962b34c604feba Mon Sep 17 00:00:00 2001 From: XIGE <710062962@qq.com> Date: Mon, 23 Feb 2026 17:21:48 +0800 Subject: [PATCH] 1.0 --- Plugin.php | 872 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 872 insertions(+) create mode 100644 Plugin.php diff --git a/Plugin.php b/Plugin.php new file mode 100644 index 0000000..1581467 --- /dev/null +++ b/Plugin.php @@ -0,0 +1,872 @@ +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; + } +} \ No newline at end of file