您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
"Set date color according to date 根据网页上日期的新旧程度, 给日期进行着色, 比如说已经是5年前的一个日期会成为红色, 以便提醒阅览者,注意信息可能过于陈旧。"
当前为
// ==UserScript== // @name colorDate // @namespace https://github.com/mika-cn/user-scripts // @description "Set date color according to date 根据网页上日期的新旧程度, 给日期进行着色, 比如说已经是5年前的一个日期会成为红色, 以便提醒阅览者,注意信息可能过于陈旧。" // @version 1.1.1 // @grant none // @include * // @author mika // ==/UserScript== (function(){ 'use strict'; /* * 获取文本节点迭代器 */ function getTextNodeIterator(){ return document.createNodeIterator( document.body, NodeFilter.SHOW_TEXT, function(node) { if(['script', 'style', 'datetext', 'datespan'].indexOf(node.parentNode.nodeName.toLowerCase()) > -1){ return NodeFilter.FILTER_REJECT; }else{ return NodeFilter.FILTER_ACCEPT; } } ); } /* * 根据规则(判断是否是日期),获取满足的节点 */ function getMatchNode(){ var nodes = []; var currentNode; var nodeIterator = getTextNodeIterator(); while (currentNode = nodeIterator.nextNode()) { var v = currentNode.nodeValue; var rule = rules.some(function(rule){ return !!v.match(rule.regExp); }); if(rule){ nodes.push(currentNode); } } return nodes; } /* * 时长阀值与色值 */ var day = 24 * 60 * 60 * 1000; var year = 365 * day; var colors = [ {color: "#ff0000", threshold: 5 * year}, {color: "#ff5f00", threshold: 3 * year}, {color: "#d700ff", threshold: 1 * year}, {color: "#8700ff", threshold: 183 * day}, {color: "#00af00", threshold: 7 * day}, {color: "#00d700", threshold: 1 * day}, ]; var monthPart = (` Jan|January| Feb|February| Mar|March| Apr|April| May| Jun|June| Jul|July| Aug|Augest| Sep|Sept|September| Oct|October| Nov|November| Dec|December `).replace(/\n\s*/gm, ''); /* * 判断规则 */ var rules = [ {key: "01", regExp: /\d{4}-[01]?\d-[0-3]?\d/mg}, {key: "01", regExp: /\d{4}\/[01]?\d\/[0-3]?\d/mg}, {key: "02", regExp: /\d{4}-[01]{1}\d(?!-\d[0-3]?\d)/mg}, {key: "02", regExp: /\d{4}\/[01]{1}\d(?!\/\d[0-3]?\d)/mg}, {key: "03", regExp: /(?:\s|^)[01]{1}\d-[0-3]{1}\d/mg}, {key: "01", regExp: new RegExp("(?:"+ monthPart +") [0-3]?\\d[,\\s]{1}\\s?\\d{4}", 'igm')}, {key: "01", regExp: /\d{4}年[01]?\d月[0-3]?\d日/mg}, {key: "02", regExp: /\d{4}年[01]?\d月(?!^[0-3]?\d日)/mg}, {key: "03", regExp: /(?:\s|^)[01]?\d月[0-3]?\d日/mg}, {key: "04", regExp: /\d+\s?天前/mg}, {key: "04", regExp: /\d+\s?days?\sago/mg}, {key: "05", regExp: /\d+\s?月前/mg}, {key: "05", regExp: /\d+\s?months?\sago/mg}, {key: "06", regExp: new RegExp("(?:"+ monthPart +")['\\s]{1}[0-3]{1}\\d(?![,\\s]{1}\\s?\\d{4})", 'igm')}, {key: "07", regExp: /\d+\s?年前/mg}, {key: "07", regExp: /\d+\s?years?\sago/mg}, ]; /* * 根据不同的正则,返回处理函数 */ function getHandler(key){ switch(key){ case "01" : return handler_01(); case "02" : return handler_02(); case "03" : return handler_03(); case "04" : return handler_04(); case "05" : return handler_05(); case "06" : return handler_06(); case "07" : return handler_07(); default: return function(match){ return match;}; } } function handler_01(){ return function(match){ var dateStr = match.replace(/年|月/g, '-').replace("日", ''); return replace(match, dateStr); }; } function handler_02(){ return function(match){ var dateStr = match.replace(/年|\//g, '-').replace("月", '') + "-01"; return replace(match, dateStr); }; } function handler_03(){ return function(match){ var dateStr = (new Date()).getFullYear().toString() + "-" + match.trim().replace(/月/g, '-').replace("日", ''); return replace(match, dateStr); }; } function handler_04(){ return function(match){ var n = parseInt(match.match(/\d+/)[0]); return replace(match, (new Date() - n * day)); }; } function handler_05(){ return function(match){ var n = parseInt(match.match(/\d+/)[0]); return replace(match, (new Date() - n * 30 * day)); }; } function handler_06(){ return function(match){ return replace(match, match.replace(/'/, ' ') + " " + (new Date()).getFullYear().toString()); }; } function handler_07(){ return function(match){ var n = parseInt(match.match(/\d+/)[0]); return replace(match, (new Date() - n * 365 * day)); }; } /* * 处理函数, 根据时长阀值着色 */ function replace(match, dateStr){ try{ var result = match; var diff = Date.now() - new Date(dateStr); colors.some(function(item){ if(diff >= item.threshold){ result = "<datespan style='color:"+ item.color +";'>" + match +"</datespan>"; return true; } return false; }); return result; }catch(e){ return match; } } // 主函数 function colorDate(){ var nodes = getMatchNode(); nodes.forEach(function(node){ // replace child node var newNode = document.createElement("datetext"); var html = node.nodeValue; rules.forEach(function(rule){ var match = html.match(rule.regExp); if(match){ html = html.replace(rule.regExp, getHandler(rule.key)); } }); newNode.innerHTML = html; node.parentNode.replaceChild(newNode, node); }); } /* * 创建延迟调用对象 * 用来防止短时间内被调用多次 */ var createDelayCall = function(fn, delay){ var dc = {}; dc.action = fn; dc.clearTimeout = function(){ if(dc.timeoutId){ clearTimeout(dc.timeoutId); } }; dc.run = function(){ dc.clearTimeout(); dc.timeoutId = setTimeout(function(){ dc.action(); dc.clearTimeout(); }, delay); }; return dc; }; /* * 判断变更是否来自脚本 */ function isColorDateMotation(mutationRecords){ return mutationRecords.every(function(record){ return record.type === "childList" && record.addedNodes.length > 0 && record.addedNodes[0].nodeName.toLowerCase() === "datetext"; }); } /* * 初始化 mutationObserver */ function initMutationObserver(){ var observer = new MutationObserver(function(mutationRecords){ if(isColorDateMotation(mutationRecords)){ // 本脚本产生的变更,不触发 // console.log("Ignore motation") }else{ delayColorDate.run(); } }); observer.observe(document, { attributes: false, childList: true, subtree: true }); //console.log("init mutationObserver"); } var delayColorDate = createDelayCall(colorDate, 400); // 监听变更,触发着色 (适用于动态网页,如: ajax加载内容后产生变更) initMutationObserver(); // 静态网页加载过程中不会产生变更, 直接调用 setTimeout(colorDate, 400); setTimeout(colorDate, 1000); setTimeout(colorDate, 4000); })();