This commit is contained in:
132
HighlightSearchKeywords/Plugin.php
Normal file
132
HighlightSearchKeywords/Plugin.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
|
||||
|
||||
/**
|
||||
* 高亮页面中的搜索关键字 【<a href="https://github.com/typecho-fans/plugins" target="_blank">TF</a>社区维护版】
|
||||
*
|
||||
* @package HighlightSearchKeywords
|
||||
* @author 羽中, gouki
|
||||
* @version 0.1.3
|
||||
* @link https://github.com/typecho-fans/plugins/tree/master/HighlightSearchKeywords
|
||||
*
|
||||
* 0.1.3 修正内部搜索无效问题,恢复自带样式
|
||||
*
|
||||
* 更新日志:
|
||||
* 0.1.0 高亮从google,yahoo,baidu过来的关键字
|
||||
* 0.1.1 文件名hightlight.js写错,改为highlight.js
|
||||
* 0.1.2 増加网站内部搜索关键字高亮
|
||||
*/
|
||||
class HighlightSearchKeywords_Plugin implements Typecho_Plugin_Interface
|
||||
{
|
||||
|
||||
/**
|
||||
* 激活插件方法,如果激活失败,直接抛出异常
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
* @throws Typecho_Plugin_Exception
|
||||
*/
|
||||
public static function activate ()
|
||||
{
|
||||
Typecho_Plugin::factory('Widget_Abstract_Contents')->filter = array('HighlightSearchKeywords_Plugin', 'parse');
|
||||
Typecho_Plugin::factory('Widget_Archive')->header = array('HighlightSearchKeywords_Plugin', 'header');
|
||||
Typecho_Plugin::factory('Widget_Archive')->footer = array('HighlightSearchKeywords_Plugin', 'footer');
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁用插件方法,如果禁用失败,直接抛出异常
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
* @throws Typecho_Plugin_Exception
|
||||
*/
|
||||
public static function deactivate(){}
|
||||
|
||||
/**
|
||||
* 获取插件配置面板
|
||||
*
|
||||
* @access public
|
||||
* @param Typecho_Widget_Helper_Form $form 配置面板
|
||||
* @return void
|
||||
*/
|
||||
public static function config(Typecho_Widget_Helper_Form $form){}
|
||||
|
||||
/**
|
||||
* 个人用户的配置面板
|
||||
*
|
||||
* @access public
|
||||
* @param Typecho_Widget_Helper_Form $form
|
||||
* @return void
|
||||
*/
|
||||
public static function personalConfig(Typecho_Widget_Helper_Form $form){}
|
||||
|
||||
|
||||
/**
|
||||
* 定义来源地址变量:httpd_referer
|
||||
*
|
||||
* @access public
|
||||
* @return unknown
|
||||
*/
|
||||
public static function header()
|
||||
{
|
||||
$referer = self::getHttpReferer();
|
||||
echo "<style type=\"text/css\">.searchword { background-color: yellow; }</style>";
|
||||
echo "<script>var httpd_referer='{$referer}';</script>";
|
||||
}
|
||||
|
||||
/**
|
||||
* 引入涉及的JS,并自动初始化
|
||||
*
|
||||
* @access public
|
||||
* @return unknown
|
||||
*/
|
||||
public static function footer()
|
||||
{
|
||||
$highlightJS = Helper::options()->pluginUrl . "/HighlightSearchKeywords/src/highlight.js";
|
||||
echo "<script type='text/javascript' src='{$highlightJS}'></script>";
|
||||
}
|
||||
|
||||
/**
|
||||
* 取得页面来源,基本上只针对google,baidu和yahoo
|
||||
*
|
||||
* @access private
|
||||
* @return string
|
||||
*/
|
||||
private static function getHttpReferer()
|
||||
{
|
||||
if(isset($_GET['highlight'])){
|
||||
return urldecode(trim($_GET['highlight']));
|
||||
}
|
||||
$request = Typecho_Request::getInstance();
|
||||
if( $referer = $request->getReferer() ){
|
||||
parse_str( parse_url( $referer , PHP_URL_QUERY ) , $query);
|
||||
if(isSet( $query['q'] ) ){
|
||||
return $query['q'];
|
||||
}else if ( isSet( $query['p'] ) ){
|
||||
return $query['p'];
|
||||
}else if ( isSet( $query['wd'] ) ){//baidu
|
||||
if(!$query['wd']){
|
||||
return '';
|
||||
}
|
||||
return iconv( 'gb2312', 'utf-8', urldecode( $query['wd'] ) ); //百度过来是gb2312,要转成utf-8
|
||||
//return urlencode(iconv( 'gb2312', 'utf-8', urldecode( $query['wd'] ) ));
|
||||
}
|
||||
}
|
||||
if(preg_match('|/search/(.*?)/|i', urldecode($request->getPathInfo()) , $result)){
|
||||
return $result[1];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
public static function parse($text, $widget, $lastResult){
|
||||
$text = empty($lastResult) ? $text : $lastResult;
|
||||
if ($widget instanceof Widget_Archive && Typecho_Router::$current == 'search') {
|
||||
if($highlight = self::getHttpReferer()){
|
||||
$_GET['highlight'] = $highlight;
|
||||
$text['permalink'] .= "?". http_build_query($_GET);
|
||||
}
|
||||
}
|
||||
return $text;
|
||||
}
|
||||
}
|
||||
66
HighlightSearchKeywords/README.md
Normal file
66
HighlightSearchKeywords/README.md
Normal file
@@ -0,0 +1,66 @@
|
||||
<a href="https://typecho-fans.github.io">
|
||||
<img src="https://typecho-fans.github.io/text-logo.svg" alt="TF Logo" title="Typecho Fans开源作品社区" align="right" height="100" />
|
||||
</a>
|
||||
|
||||
HighlightSearchKeywords v0.1.3 - 社区维护版
|
||||
======================
|
||||
<h4 align="center">—— 高亮页面中来自搜索引擎或站内搜索的关键字,主要通过原生Js配合页面请求实现。</h4>
|
||||
|
||||
<p align="center">
|
||||
<a href="#使用说明">使用说明</a> •
|
||||
<a href="#版本历史">版本历史</a> •
|
||||
<a href="#贡献作者">贡献作者</a> •
|
||||
<a href="#附注链接">附注/链接</a> •
|
||||
<a href="#授权协议">授权协议</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
## 使用说明
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
###### 默认为搜索结果页面中的关键字添加黄色背景(可在插件Plugin.php第74行自行修改),支持从百度等搜索引擎到达的页面,方便访客迅速定位检索内容。
|
||||
|
||||
**使用方法**:
|
||||
##### 1. 下载本插件,放在 `usr/plugins/` 目录中,确保文件夹名为 HighlightSearchKeywords;
|
||||
##### 2. 激活插件;
|
||||
##### 3. 使用站内或外部搜索字词即可看到高亮效果。
|
||||
|
||||
**注意事项**:
|
||||
* ##### 如果站内搜索使用Ajax可尝试为form添加class值`searchhi`自行调试,相关代码在src/highlight.js的第101行。
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## 版本历史
|
||||
|
||||
* v0.1.3 (20-07-12 [@jzwalk](https://github.com/jzwalk))
|
||||
* 修正内部搜索无效问题,恢复自带样式。
|
||||
* v0.1.2 (不详 [@gouki](https://neatstudio.com))
|
||||
* 増加网站内部搜索关键字高亮。
|
||||
* v0.1.1 (不详 [@gouki](https://neatstudio.com))
|
||||
* 文件名hightlight.js写错,改为highlight.js。
|
||||
* v0.1.0 (10-06-16 [@gouki](https://neatstudio.com))
|
||||
* 高亮从google,yahoo,baidu过来的关键字。
|
||||
|
||||
## 贡献作者
|
||||
|
||||
[](https://github.com/jzwalk) | [](https://neatstudio.com)
|
||||
:---:|:---:
|
||||
[jzwalk](https://github.com/jzwalk) (2020) | [gouki](https://neatstudio.com) (2010)
|
||||
|
||||
## 附注/链接
|
||||
|
||||
* [原版](https://neatstudio.com/show-1339-1.shtml) - 实现高亮搜索关键字功能。
|
||||
|
||||
插件使用核心年代久远,外部搜索高亮是否仍有效未严格测试,欢迎社区成员继续参与更新!
|
||||
|
||||
## 授权协议
|
||||
|
||||
TF目录下的社区维护版作品如果没有明确声明,默认采用与Typecho相同的[GPLv2](https://github.com/typecho/typecho/blob/master/LICENSE.txt)开源协议。(要求提及出处,保持开源并注明修改。)
|
||||
|
||||
> HighlightSearchKeywords原作未附协议声明,原作者保留所有权利。 © [gouki](https://neatstudio.com)
|
||||
124
HighlightSearchKeywords/src/highlight.js
Normal file
124
HighlightSearchKeywords/src/highlight.js
Normal file
@@ -0,0 +1,124 @@
|
||||
/* http://www.kryogenix.org/code/browser/searchhi/ */
|
||||
/* Modified 20021006 to fix query string parsing and add case insensitivity */
|
||||
/* Modified 20070316 to stop highlighting inside nosearchhi nodes */
|
||||
/* Modified 20081217 to do in-page searching and wrap up in an object */
|
||||
/* Modified 20081218 to scroll to first hit like
|
||||
http://www.woolyss.free.fr/js/searchhi_Woolyss.js and say when not found */
|
||||
|
||||
searchhi = {
|
||||
highlightWord: function(node,word) {
|
||||
// Iterate into this nodes childNodes
|
||||
if (node.hasChildNodes) {
|
||||
for (var hi_cn=0;hi_cn<node.childNodes.length;hi_cn++) {
|
||||
searchhi.highlightWord(node.childNodes[hi_cn],word);
|
||||
}
|
||||
}
|
||||
|
||||
// And do this node itself
|
||||
if (node.nodeType == 3) { // text node
|
||||
tempNodeVal = node.nodeValue.toLowerCase();
|
||||
tempWordVal = word.toLowerCase();
|
||||
if (tempNodeVal.indexOf(tempWordVal) != -1) {
|
||||
var pn = node.parentNode;
|
||||
// check if we're inside a "nosearchhi" zone
|
||||
var checkn = pn;
|
||||
while (checkn.nodeType != 9 &&
|
||||
checkn.nodeName.toLowerCase() != 'body') {
|
||||
// 9 = top of doc
|
||||
if (checkn.className.match(/\bnosearchhi\b/)) { return; }
|
||||
checkn = checkn.parentNode;
|
||||
}
|
||||
if (pn.className != "searchword") {
|
||||
// word has not already been highlighted!
|
||||
var nv = node.nodeValue;
|
||||
var ni = tempNodeVal.indexOf(tempWordVal);
|
||||
// Create a load of replacement nodes
|
||||
var before = document.createTextNode(nv.substr(0,ni));
|
||||
var docWordVal = nv.substr(ni,word.length);
|
||||
var after = document.createTextNode(nv.substr(ni+word.length));
|
||||
var hiwordtext = document.createTextNode(docWordVal);
|
||||
var hiword = document.createElement("span");
|
||||
hiword.className = "searchword";
|
||||
hiword.appendChild(hiwordtext);
|
||||
pn.insertBefore(before,node);
|
||||
pn.insertBefore(hiword,node);
|
||||
pn.insertBefore(after,node);
|
||||
pn.removeChild(node);
|
||||
searchhi.found += 1;
|
||||
if (searchhi.found == 1) pn.scrollIntoView();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
googleSearchHighlight: function( str ) {
|
||||
// var ref = document.referrer;
|
||||
// if (ref.indexOf('?') == -1) return;
|
||||
// var qs = ref.substr(ref.indexOf('?')+1);
|
||||
// var qsa = qs.split('&');
|
||||
// for (var i=0;i<qsa.length;i++) {
|
||||
// var qsip = qsa[i].split('=');
|
||||
// if (qsip.length == 1) continue;
|
||||
// if (qsip[0] == 'q' || qsip[0] == 'p') { // q= for Google, p= for Yahoo
|
||||
// var wordstring = unescape(qsip[1].replace(/\+/g,' '));
|
||||
// searchhi.process(wordstring);
|
||||
// }
|
||||
// if (qsip[0] == 'wd') { // wd= for baidu
|
||||
// if(qsip[1]=='') continue;
|
||||
// var xx=new GB2312UTF8();
|
||||
// var wordstring=xx.Gb2312ToUtf8( qsip[1].replace(/\+/g,' '));
|
||||
// searchhi.process(wordstring);
|
||||
//// execScript('wd = DeCodeAnsi("'+qsip[1]+'")','vbscript');
|
||||
//// words = decodeURI(wd.replace(/\+/g,' ')).split(/\s+/);
|
||||
//// for (w=0;whighlightWord(document.getElementsByTagName("body")[0],words[w]);
|
||||
// }
|
||||
// }
|
||||
if(str=='')return;
|
||||
var wordstring = unescape( str.replace(/\+/g,' '));
|
||||
searchhi.process(wordstring);
|
||||
},
|
||||
|
||||
process: function(wordstring) {
|
||||
|
||||
searchhi.found = 0;
|
||||
var words = wordstring.split(/\s+/);
|
||||
for (w=0;w<words.length;w++) {
|
||||
searchhi.highlightWord(document.getElementsByTagName("body")[0],words[w]);
|
||||
}
|
||||
if (searchhi.found === 0) {
|
||||
searchhi.nohits();
|
||||
}
|
||||
},
|
||||
|
||||
nohits: function() {
|
||||
},
|
||||
|
||||
init: function() {
|
||||
if (!document.createElement || !document.getElementsByTagName) return;
|
||||
// hook up forms of type searchhi
|
||||
var frms = document.getElementsByTagName("form");
|
||||
for (var i=0; i<frms.length; i++) {
|
||||
if (frms[i].className.match(/\bsearchhi\b/)) {
|
||||
frms[i].onsubmit = function() {
|
||||
var inps = this.getElementsByTagName("input");
|
||||
for (var j=0; j<inps.length; j++) {
|
||||
if (inps[j].type == "text") {
|
||||
searchhi.process(inps[j].value);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
// highlight search engine referrer results
|
||||
searchhi.googleSearchHighlight(httpd_referer);
|
||||
}
|
||||
};
|
||||
|
||||
(function(i) {var u =navigator.userAgent;var e=/*@cc_on!@*/false; var st =
|
||||
setTimeout;if(/webkit/i.test(u)){st(function(){var dr=document.readyState;
|
||||
if(dr=="loaded"||dr=="complete"){i()}else{st(arguments.callee,10);}},10);}
|
||||
else if((/mozilla/i.test(u)&&!/(compati)/.test(u)) || (/opera/i.test(u))){
|
||||
document.addEventListener("DOMContentLoaded",i,false); } else if(e){ (
|
||||
function(){var t=document.createElement('doc:rdy');try{t.doScroll('left');
|
||||
i();t=null;}catch(e){st(arguments.callee,0);}})();}else{window.onload=i;}})(searchhi.init);
|
||||
Reference in New Issue
Block a user