forked from langren1353/GM_script
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAutoHighLight.user.js
More file actions
410 lines (407 loc) · 17.2 KB
/
AutoHighLight.user.js
File metadata and controls
410 lines (407 loc) · 17.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
// ==UserScript==
// @name AC-baidu: 优化百度、搜狗、谷歌搜索结果之关键词自动高亮
// @description 1.自动提取搜索页面的搜索关键词 2.对关键词自动进行高亮处理 W键可以取消高亮 3.动态获取动态的搜索关键词,重新高亮显示
// @icon https://coding.net/u/zb227/p/zbImg/git/raw/master/img0/icon.jpg
// @author AC
// @create 2018-05-25
// @version 2.2
// @include *
// @exclude *://www.bilibili.com/*
// @home-url https://greasyfork.org/zh-TW/scripts/368418
// @home-url2 https://github.com/langren1353/GM_script
// @namespace 1353464539@qq.com
// @copyright 2017, AC
// @lastmodified 2019-08-09
// @feedback-url https://greasyfork.org/zh-TW/scripts/368418
// @note 2019.08.09-V2.2 排除bilibili的地址,避免导致bilibili无法播放
// @note 2019.06.05-V2.1 修复样式加载刚开始的时候还是黑色的,颜色没有及时更新的问题 其次优化脚本的处理速速,减少不必要的查询和处理
// @note 2018.10.08-V2.0 修复多次触发导致的卡顿现象;修复搜索时高亮的问题
// @note 2018.10.03-V1.9 修复由于<span>标签导致的:1.样式被界面污染 2.特定关键词被百度重定向脚本删除;修复在部分代码界面导致的高亮失效问题;修复高亮导致的标题栏被格式化
// @note 2018.07.21-V1.8 修复由于很快的高亮导致的高亮代码被个格式化为普通文本
// @note 2018.07.06-V1.7 修复csdn的问题和w3cschool页面的代码问题
// @note 2018.06.20-V1.6 修复上次更新导致的严重bug,页面卡死问题
// @note 2018.06.18-V1.5 修复在部分csdn网页代码上,高亮不起作用
// @note 2018.06.15-V1.4 修复在CSDN代码中,高亮处理之后导致的多了一部分文字的问题;减少了多次调用可能出现的冲突问题;依旧添加G键也是高亮效果
// @note 2018.06.04-V1.3 1.修复百度翻页之后偶尔不自动高亮的问题;2.新增一定的页面高亮效果的调整;优化关键词的数量,数量到达一定程度,之后的关键词不做高亮处理
// @note 2018.05.31-V1.2 修复由于分词不准的问题导致的丢词问题;修复停止高亮然后又自动启动的问题;修复下划线分割问题;修复左右尖括号转换问题;新增W高亮时复制文字内容
// @note 2018.05.26-V1.1 修复垃圾代码,上个版本真的是垃圾代码,运行又慢,占用又高,还特么定时运行,但就是数据出现很慢,现在应该没有这个问题了
// @note 2018.05.25-V1.0 从百度重定向脚本中拆分出来
// @run-at document-body
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_setClipboard
// ==/UserScript==
var isDebug = true; // 本次更新是否有新功能需要展示
var debugX = isDebug ? console.log.bind(console) : function(){};
function sayLength(){
debugX(document.querySelectorAll(".c-container").length);
}
(function () {
'use strict';
var startTime = new Date().getTime();
var renderStartTime = 5000; // 5秒钟 & 强制刷新应该优先于定时操作
var HightLightColorList = ["#FFFF80", "#90EE90", "#33FFFF", "#FF6600", "#FF69B4", "#20B2AA", "#8470FF"];
var isSearchWindowActive = true; // 搜索窗口是否激活
var OnlyDBCheck = false; // 是否为双击事件
var enableDBSelectText = false;
var oldTextSelectInterval = -1;
var hasInitBtnBind = false;
var hasInitBtnBind_DOM = false;
var dataRapidLock = false;
var dataConflictLock = false;
var disableHighLight = false; // 是否禁用highLight
var SiteTypeID; // 标记当前是哪个站点[百度=1;搜狗=2;3=好搜;谷歌=4;必应=5;知乎=6;其他=7]
var SiteType={
BAIDU:1,
SOGOU:2,
SO:3,
GOOGLE:4,
BING:5,
ZHIHU:6,
OTHERS:7
};
/*在搜索引擎上面会刷新当前搜索关键词内容*/
if (location.host.indexOf("www.baidu.com") > -1) {
SiteTypeID = SiteType.BAIDU;
} else if (location.host.indexOf("sogou") > -1) {
SiteTypeID = SiteType.SOGOU;
} else if (location.host.indexOf("so.com") > -1) {
SiteTypeID = SiteType.SO;
} else if (location.host.indexOf("google") > -1) {
SiteTypeID = SiteType.GOOGLE;
} else if (location.host.indexOf("bing") > -1) {
SiteTypeID = SiteType.BING;
} else if (location.host.indexOf("zhihu.com") > -1) {
SiteTypeID = SiteType.ZHIHU;
} else {
SiteTypeID = SiteType.OTHERS;
}
setTimeout(function(){
DoHighLightWithSearchText(GM_getValue("searchKeyWords", ""));
}, renderStartTime);
function DoHighLightWithSearchText(searchValue){
WordAutoHighLight(searchValue);
}
function AC_addStyle(css, className, addToTarget, isReload){ // 添加CSS代码,不考虑文本载入时间,带有className
var tout = setInterval(function(){
if(addToTarget == null) addToTarget = "head";
if(isReload == null) isReload = false;
if(document.querySelector(addToTarget) != null){
clearInterval(tout);
var checkNode = document.querySelector("."+className) || null;
if(isReload == false && checkNode != null){
// 节点存在,并且不准备覆盖
return;
}
if(checkNode!= null && css == checkNode.innerHTML) {
// checkNode可访问 & 内容相同 == > else 没有节点 || 内容不同
return;
}
safeRemove("."+className);
var cssNode = document.createElement("style");
if(className != null)
cssNode.className = className;
cssNode.innerHTML = css;
try{
document.querySelector(addToTarget).appendChild(cssNode);
}catch (e){debugX(e.message);}
}
}, 50);
}
function safeRemove(cssSelector){
try {
document.querySelector(cssSelector).remove();
}catch (e){}
}
function WordAutoHighLight(searchText){
if(!hasInitBtnBind){
hasInitBtnBind = true;
setTimeout(function(){
// 似乎过早的绑定可能出现问题,例如www.huomao.com中h5视频的LOGO一直在
document.addEventListener('keydown', DoHighLight, true);
}, 800);
}
var enableCharCode1 = 'G';
var enableCharCode2 = 'W';
var keySets = new Object();
var counter = 0;
doHighLightTextS(searchText);
function DoHighLight(e) { // 手动W触发
var target = e.target;
var selectedText = getSelectedText(target);
var s_keyup = (e.type === 'keydown') && (enableCharCode1.charCodeAt(0)==e.keyCode || enableCharCode2.charCodeAt(0)==e.keyCode);// 是按下特殊按键
if (s_keyup) {
if(typeof(selectedText) == "undefined" || selectedText == null || selectedText == ""){
try{clearInterval(oldTextSelectInterval);}catch (e){debugX(e);}
debugX("不准亮");
GM_setValue("searchKeyWords", ""); // 置空
hasInitBtnBind_DOM = false;
disableHighLight = true;
safeRemove(".AC-highLightRule");
document.removeEventListener('DOMSubtreeModified', DOMRapidHighLightFunc, false);
unHighLightAll_Text();
}else{
GM_setClipboard(selectedText);
enableDBSelectText = true;
disableHighLight = false;
OnlyDBCheck = true;
doHighLightTextS(selectedText, true);
}
}
}
function doHighLightTextS(selectedText, dbclick) {
if(typeof(selectedText) == "undefined" || selectedText == null || selectedText == "") return;
unHighLightAll_Text();
if(dbclick){
GM_setValue("searchKeyWords", selectedText);
debugX("双击:" + selectedText + keySets.keywords);
}
initKeySets(selectedText);
doHighLightAll_CSS();
doHighLightAll_Text();
setTimeout(function(){doHighLightAll_Text();}, 1500);
if(hasInitBtnBind_DOM == false){
hasInitBtnBind_DOM = true;
document.addEventListener('DOMSubtreeModified', DOMRapidHighLightFunc, false);
}
}
// bug-卡顿严重
function DOMRapidHighLightFunc(e) {
if(dataRapidLock == false){
dataRapidLock = true;
doHighLightAll_CSS();
doHighLightAll_Text();
setTimeout(function(){dataRapidLock = false;}, 1000); // 每两秒的时候可以触发一次
}
}
function getSelectedText(target) {
function getTextSelection() {
var selectedText = '';
if (target.getAttribute("type")) {
if (target.getAttribute("type").toLowerCase() === "checkbox") return '';
}
var value = target.value;
if (value) {
var startPos = target.selectionStart;
var endPos = target.selectionEnd;
if (!isNaN(startPos) && !isNaN(endPos)) selectedText = value.substring(startPos, endPos);
return selectedText;
} else return '';
}
var selectedText = window.getSelection().toString();
if (!selectedText) selectedText = getTextSelection();
return selectedText;
}
function getBLen(str) {
if (str == null) return 0;
if (typeof str != "string"){
str += "";
}
return str.replace(/[^\x00-\xff]/g,"01").length;
}
function reSplitKeySet(keySet){
var data = keySet
.split(/\b |[\u0000-\u002F\u003A-\u0040\u005B-\u005e\u007B-\u00FF\uFF00-\uFFFF\u3000-\u303F]/g)
.join('ACsCA')
.replace(/[^\u4E00-\u9FA5|0-9|a-z|A-Z_]+/g, "")
.replace(/(ACsCA){2}/g, "ACsCA")
.replace(/(^ACsCA|ACsCA$)/g, "")
.split("ACsCA");
var newData = new Array();
for(var i = 0, j = 0; i < data.length; i++){
if(data[i].length > 1){
newData[j++] = data[i];
}
}
return newData;
}
// 初始化点击的文字信息
function initKeySets(selection){
// 1.split通过特殊字符和字符边界分割串[非[0-9A-Za-z]特殊字符]
// 2.通过特定字符连接原始串,
// 3.1移除多次重复的特定串,非常用串移除,避免空串
// 3.2移除开头或者结尾的特定串,避免分割后出现空白数据,
// 4.按特定串分割
keySets.keywords = reSplitKeySet(selection);
keySets.length = keySets.keywords.length;
keySets.textcolor = new Array();
keySets.visible = new Array();
for(var i=0; i < keySets.keywords.length; i++){
keySets.textcolor[i] = "rgb(0,0,0)";
keySets.visible[i] = "true";
}
}
function doHighLightAll_CSS(){
var selection = GM_getValue("searchKeyWords", "");
// debugX("执行高亮"+selection);
keySets.keywords = reSplitKeySet(selection);
// 这个要后处理,这样的话keywords才会有数据,否则的话由于没有数据,初始的颜色就不会显示
if (keySets.visible[0] == "true"){
var rule = ".acWHSet{display:inline!important;box-shadow: -3px 0px 3px 0.15px rgba(0, 0, 0, 0.15);";
if (keySets.textcolor.length > 0) rule += "color:"+keySets.textcolor[0]+";";
rule += "font-weight:inherit;}";
for(var i = 0; i < keySets.keywords.length; i++){
rule += ".acWHSet[data='"+keySets.keywords[i].toLocaleLowerCase()+"']{background-color:"+HightLightColorList[i % HightLightColorList.length]+";}";
}
// debugX("触发重置CSS");
AC_addStyle(rule, "AC-highLightRule", "body", true);
}
}
function doHighLightAll_Text(){
if(dataConflictLock == true) return;
dataConflictLock = true;
doHighLightAll_Text_Inner();
dataConflictLock = false;
}
// BUG- 卡顿严重,注意时间消耗
function doHighLightAll_Text_Inner(){
if(keySets.keywords.length == 0) {
return; // 退出1
}
var patExp = "";
for(var index=0, sizeCount = 0; index<keySets.keywords.length-1 && index < 8 && sizeCount < 50; index++) {
patExp += keySets.keywords[index]+"|";
sizeCount += keySets.keywords[index].length;
}
patExp += keySets.keywords[index];
var pat = new RegExp("("+patExp+")", "gi");
var XhighLight = document.createElement('XhighLight');
var evalRule = './/text()[normalize-space() != "" ' +
'and not(parent::XhighLight[@txhidy15]) ' +
'and not(parent::title)' +
'and not(ancestor::style) ' +
'and not(ancestor::script) ' +
'and not(ancestor::textarea) ' +
'and not(ancestor::div[@id="thdtopbar"]) ' +
'and not(ancestor::div[@id="kwhiedit"]) ' +
'and not(parent::XhighLight[@txhidy15]) ' +
'and not(ancestor::pre) '+ // CSDN的代码文字,未初始化之前的1--->不作处理
((new Date().getTime() - startTime > renderStartTime || OnlyDBCheck == true)?
('or ((ancestor::pre) and not(parent::XhighLight[@txhidy15]) and ('+ // EG.http://www.w3school.com.cn/xpath/xpath_syntax.asp
'(ancestor::code[@class]) '+ // EG.http://lib.csdn.net/article/android/8894
'or (ancestor::div[contains(@class, "cnblogs_code")] ) '+ // EG.https://blog.csdn.net/freeape/article/details/50485067
"))") : "") +
']';
var snapElements = document.evaluate(evalRule, document.body, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
if (!snapElements.snapshotItem(0)) {
return;
} // 退出2
try{
for (var i = 0, len = snapElements.snapshotLength; i < len; i++) {
var node = snapElements.snapshotItem(i);
if (node.nodeValue.length > 1 && pat.test(node.nodeValue)) {
if(node.className!= null && node.className.indexOf("acWHSet") > 0) return;
// if (node.parentNode.outerHTML != null && node.parentNode.outerHTML.indexOf("THmo acWHSet") >= 0) return;
// debugX("start");
// debugX(node.children);
// debugX(node.className);
// debugX(node.parentNode);
var sp = XhighLight.cloneNode(true);
var findResult = node.nodeValue.replace(/[<>"&]/g, function(match){
switch(match){
case "<": return "<";
case ">": return ">";
case "&": return "&";
case "\"":return """;
}
});
// debugX("1."+findResult);
// var repNodeHTML = findResult.replace(pat, '<XhighLight class="THmo acWHSet" data="$1" txhidy15="acWHSet">$1</XhighLight>');
var repNodeHTML = findResult.replace(pat, function(matchT, _$1) {
var lowerData = _$1.toLocaleLowerCase();
return '<XhighLight class="THmo acWHSet" data="' + lowerData + '" txhidy15="acWHSet">'+ _$1 +'</XhighLight>';
});
// debugX("2."+repNodeHTML);
sp.innerHTML = repNodeHTML;
if(node.parentNode == null) continue;
node.parentNode.replaceChild(sp, node);
sp.outerHTML = sp.innerHTML;
}
}
// var attributeDataResetList = document.querySelectorAll(".acWHSet");
// for(var i = 0; i < attributeDataResetList.length; i++){
// attributeDataResetList[i].setAttribute("data", attributeDataResetList[i].innerHTML.toLocaleLowerCase());
// }
}catch (e) {
debugX(e);
}
return;
}
function unHighLightAll_Text(){
try{
var tgts = document.querySelectorAll('XhighLight[txhidy15="acWHSet"]');
for (var i=0; i<tgts.length; i++){
var parnode = tgts[i].parentNode, parpar = parnode.parentNode, tgtspan;
if (parnode.hasAttribute("thdcontain") && parnode.innerHTML == tgts[i].outerHTML){
parnode.outerHTML = tgts[i].textContent.replace(/</g, '<').replace(/>/g, '>');
tgtspan = parpar;
} else {
tgts[i].outerHTML = tgts[i].textContent.replace(/</g, '<').replace(/>/g, '>');
tgtspan = parnode;
}
tgtspan.normalize();
if (tgtspan.hasAttribute("thdcontain")){
parnode = tgtspan.parentNode;
if (parnode){
if (parnode.hasAttribute("thdcontain") && parnode.innerHTML == tgtspan.outerHTML && tgtspan.querySelectorAll('XhighLight[txhidy15]').length == 0){
parnode.outerHTML = tgtspan.innerHTML;
} else if (parnode.innerHTML == tgtspan.outerHTML && tgtspan.querySelectorAll('XhighLight[txhidy15]').length == 0) {
parnode.innerHTML = tgtspan.innerHTML;
}
}
}
}
var oldTgs = document.querySelectorAll("XhighLight[thdcontain='true']");
counter = 0;
for(var i=0; i < oldTgs.length; i++){
var curTg = oldTgs[i];
markChildandRemove(curTg);
}
}catch (e){}
}
function markChildandRemove(node){
try{
if(node.tagName.toLowerCase() == "xhighlight"){
node.outerHTML = node.innerHTML;
}
var childList = node.childNodes;
for(var i=0; i < childList.length; i++){
counter++;
var node = childList[i];
markChildandRemove(node);
if(node.tagName.toLowerCase() == "xhighlight"){
node.outerHTML = node.innerHTML;
}
}
}catch (e){}
}
}
// 如果是搜索引擎的话
if(SiteTypeID != SiteType.OTHERS){ // 启用自动高亮
// 持续拿到搜索关键词,存入GM中,避免切换页面导致的关键词丢失
DoHighLightWithSearchText(GM_getValue("searchKeyWords", ""));
setInterval(function(){
if(document.hidden == true){ // 只要是搜索窗口不激活,那么flag=false
isSearchWindowActive = false;
enableDBSelectText = false;
}
// (窗口激活状态;或者是窗口之前是不激活,现在激活了) && 必须要非 禁用高亮状态
if((isSearchWindowActive == true || (isSearchWindowActive == false && document.hidden == false)) && !disableHighLight) {
var searchValue = (window.location.search.substr(1) + "").split("&");
for (var i = 0; i < searchValue.length; i++) {
var key_value = searchValue[i].split("=");
if (/^(wd|q|query)$/.test(key_value[0])) {
var searchWords = decodeURI(key_value[1]).toLocaleLowerCase().replace(/\+/g, " ");
if(GM_getValue("searchKeyWords", "") != searchWords && enableDBSelectText == false){ // 避免重复掉用,一直刷新关键词
GM_setValue("searchKeyWords", searchWords);
DoHighLightWithSearchText(GM_getValue("searchKeyWords", ""));
}
break;
}
}
}
}, 200);
}else{
DoHighLightWithSearchText(GM_getValue("searchKeyWords", ""));
}
})();