// ==UserScript==
// @name highlight-my-interest
// @name:zh-CN 高亮关键词
// @description highlight keywords in my favorites
// @description:zh-CN 高亮特定网页中感兴趣的关键词
// @version 0.2.2
// @author jferroal
// @license GPL-3.0
// @grant none
// @require https://greasyfork.org/scripts/31793-jmul/code/JMUL.js?version=209567
// @include http://*
// @include https://*
// @run-at document-end
// @namespace https://greasyfork.org/users/34556-jferroal
// ==/UserScript==
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
let JMUL = window.JMUL || {};
const Map = (list, fn) => {
let result = [];
if (list && list.length) {
for (let i = 0; i < list.length; i += 1) {
result.push(fn(list[ i ]));
}
}
return result;
};
class TextElement {
constructor (element) {
this.element = new JMUL.Element(element);
this.innerText = this.element.innerText;
this.shouldHighlight = false;
}
detect () {
for (const keyword of TextElement.keywords) {
const keywordPattern = new RegExp(keyword, 'gi');
if (keywordPattern.test(this.innerText)) {
this.shouldHighlight = true;
break;
}
}
return this;
}
highlight () {
if (this.shouldHighlight) {
this.element.setCss(TextElement.highlightStyle);
}
}
static init (setting) {
TextElement.highlightStyle = {
background: setting.highlightBgColor,
color: setting.highlightTxtColor,
};
}
static setKeywords (keywords) {
TextElement.keywords = keywords;
}
static findAll () {
return TextElement.targetTagNames.reduce((res, tagName) => {
const tags = document.getElementsByTagName(tagName);
return res.concat(Map(tags, (e) => new TextElement(e)));
}, []);
}
}
TextElement.targetTagNames = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'p', 'a', 'pre', 'blockquote', 'summary' ];
module.exports = TextElement;
},{}],2:[function(require,module,exports){
const KeywordService = require('./keyword.service');
const SettingService = require('./setting.service');
const TextElement = require('./element');
const Config = {};
(function () {
let highlightedCount = 0;
// const href = window.location.href;
const href = 'https://sspai.com';
loadSetting().then((setting) => {
KeywordService.init(setting, href);
TextElement.init(setting);
highlight()
});
window.addEventListener('scroll', highlight);
function loadSetting () {
SettingService.init(Config);
return SettingService.load();
}
function highlight () {
const elements = TextElement.findAll();
if (elements.length === highlightedCount) return;
KeywordService.list().then((keywords) => {
TextElement.setKeywords(keywords);
elements.map((e) => e.detect().highlight());
highlightedCount = elements.length;
});
}
})();
},{"./element":1,"./keyword.service":3,"./setting.service":5}],3:[function(require,module,exports){
class KeywordService {
static init (setting, href) {
KeywordService.Setting = setting;
const sites = Object.keys(KeywordService.Setting.keywords);
if (sites && sites.length) {
KeywordService.keywords = sites.reduce((res, site) => {
const sitePattern = new RegExp(site, 'gi');
return res.concat((sitePattern.test(href) && KeywordService.Setting.keywords[ site ]) || []);
}, []);
}
}
static list () {
return Promise.resolve(KeywordService.keywords);
}
}
module.exports = KeywordService;
},{}],4:[function(require,module,exports){
class Setting {
constructor (jsonBody) {
Object.assign(this, jsonBody);
}
}
module.exports = { Setting };
},{}],5:[function(require,module,exports){
const Setting = require('./setting').Setting;
const { Request } = window.JMUL || { JMUL: {} };
const DefaultKeywords = [
'书籍',
'效率',
'google.*?',
'nexus.*?',
'爬虫',
'python.*?',
'angular.*?',
'node',
'javascript',
'ukulele',
/gtd.*?/gi,
'工作流',
'日程',
'英雄联盟',
'vps',
'服务器',
'书单',
'免费',
'限免',
'数据分析',
'自由职业',
'lol',
'react',
'mobx',
];
const DefaultResponseHandler = (_response) => {
let response = _response;
if (typeof _response === 'object' && _response.responseText) {
response = _response.responseText;
}
return new Setting(JSON.parse(response));
};
class SettingService {
static init (config) {
SettingService.loadUrl = config.loadUrl;
SettingService.method = config.method || 'GET';
SettingService.contentType = config.contentType || 'application/json';
SettingService.data = config.data || {};
SettingService.resHandler = config.resHandler || DefaultResponseHandler;
}
static load () {
if (!SettingService.loadUrl) return Promise.resolve(SettingService.DefaultSetting);
const request = new Request({ headers: { 'content-type': SettingService.contentType } });
request.setUrl(SettingService.loadUrl);
request.setMethod(SettingService.method);
request.setData(SettingService.data);
return request.send().then((response) => {
return SettingService.resHandler(response.responseText);
});
}
}
SettingService.DefaultSetting = {
highlightBgColor: '#FFDA5E',
highlightTxtColor: 'black',
keywords: {
'https://sspai.com/*': DefaultKeywords,
'https://toutiao.io/*': DefaultKeywords,
'http://www.inoreader.com/*': DefaultKeywords,
},
};
module.exports = SettingService;
},{"./setting":4}]},{},[2]);