您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
read log
// ==UserScript== // @name read_log // @include *wikipedia* // @supportURL https://github.com/sxlgkxk/browser_script/issues // @version 0.3 // @description read log // @namespace http://sxlgkxk.github.io/ // @author sxlgkxk // @icon http://sxlgkxk.github.io/im/avatar.jpg // @license MIT // @grant GM_getValue // @grant GM_setValue // @grant GM_xmlhttpRequest // ==/UserScript== (function () { let blockWidth = 10 let blockPadding = 3 // weeksCount=53 let weeksCount = 30 // 393, 94 let canvasWidth = (blockWidth + blockPadding) * weeksCount + blockPadding let canvasHeight = (blockWidth + blockPadding) * 7 + blockPadding //-------------------------------- common functions -------------------------------- function addScript(src) { let scripts_dom = document.createElement('script'); scripts_dom.src = src; scripts_dom.type = 'text/javascript'; document.getElementsByTagName('head')[0].appendChild(scripts_dom); } addScript('https://unpkg.com/axios/dist/axios.min.js') function getScrollPercent() { let h = document.documentElement, b = document.body, st = 'scrollTop', sh = 'scrollHeight'; return ((h[st] || b[st]) / ((h[sh] || b[sh])) * 100).toFixed(2); } function getGistToken() { let gist_token = localStorage.getItem('gist_token') if (gist_token != null && gist_token.length > 10) { gist_token = prompt('gist_token?') if (gist_token) { localStorage.setItem('gist_token', gist_token) } } return gist_token } async function gist_get_async(gist_id, filename) { // gist_get_async("cfa70a44bb181edbb2be19dacbcf6808", "read_log.json").then((content)=>{console.log(content)}) let response = await axios.get("https://api.github.com/gists/" + gist_id) let data = response.data let content = data.files[filename].content return content } async function gist_set_async(gist_id, filename, content) { // gist_set_async("cfa70a44bb181edbb2be19dacbcf6808", "read_log.json", "[]").then((content)=>{console.log(content)}) let files = {} files[filename] = { "content": content } let gist_token = getGistToken() return await axios.patch("https://api.github.com/gists/" + gist_id, { files: files }, { headers: { Authorization: "token " + gist_token } }) } function addStyle(html) { let style = document.createElement("div") document.body.before(style) style.innerHTML = `<style>` + html + `</style>` } //-------------------------------- code snippets -------------------------------- addStyle(` #wpmArea{ position: absolute; right: 10px; left:10px; background-color: rgba(255, 255, 255, 0.2); } #heatmap{ background-color: #0d1117; margin: 0 auto; display:block; } table#history_table { border-collapse: collapse; width: 100%; } #history_table th, #history_table td { text-align: left; padding: 8px; } button.pagiBtn{ background-color: #333; color: #fff; margin: 4px; padding-left: 15px; padding-right: 15px; padding-top: 9px; padding-bottom: 9px; } `) for (let i = 1; i <= 31; i++) { addStyle(`td.historyDay` + i + `{background-color: rgba(` + Math.floor(Math.random() * 255) + `,` + Math.floor(Math.random() * 255) + `,` + Math.floor(Math.random() * 255) + `, 0.5);}`) } function getColor(count) { let colors = [ "#161b22", "#cef1dd", "#9ee3bb", "#6dd499", "#3cc677", "#33a865", "#2a8b53", "#216d41" ] let max_count = 60 * 8 return colors[Math.ceil(Math.min(count / max_count, 1) * (colors.length - 1))] } function setBlock(x, y, count, ctx) { ctx.fillStyle = getColor(count); ctx.fillRect(x * (blockWidth + blockPadding) - blockWidth, y * (blockWidth + blockPadding) - blockWidth, blockWidth, blockWidth); } function getRegularWeekday(date) { let weekday = date.getDay() return weekday ? weekday : 7 } function sum(array) { return array.reduce((partialSum, a) => partialSum + a, 0) } function refreshHeatmap() { let log = localStorage.getItem('readlog') log = log ? JSON.parse(log) : {} let now = new Date(); let now1 = new Date(now - getRegularWeekday(now) * 3600 * 24 * 1000) let canvas = document.querySelector('canvas#heatmap') let ctx = canvas.getContext('2d'); ctx.clearRect(0, 0, canvas.width, canvas.height); for (let i = 0; i < 365; i++) { let date = new Date(now - i * 3600 * 24 * 1000) let weekday = getRegularWeekday(date) let y = weekday let date1 = new Date(date - getRegularWeekday(date) * 3600 * 24 * 1000) let x = weeksCount - (now1 - date1) / 1000 / 3600 / 24 / 7 let dateStr = getDateStr(date) let uuid = getUuid() let data = log[dateStr] let count = data ? sum(Object.values(data)) : 0 setBlock(x, y, count, ctx) } } function getUuid() { let uuid = localStorage.getItem('uuid') if (!uuid) { uuid = String(Math.random()).substring(2, 4) localStorage.setItem('uuid', uuid) } return uuid } function getHistoryDateStr(date = null) { date = new Date(date) let month = String(date.getMonth() + 1) let day = String(date.getDate()) return month + "." + day } function getDateStr(date = null) { date = date ? date : new Date() let year = String(date.getFullYear()).substring(2, 4) let month = String(date.getMonth() + 1).padStart(2, '0') let day = String(date.getDate()).padStart(2, '0') return year + month + day } function updateLocalLog(uuid, date) { let log = localStorage.getItem('readlog') log = log ? JSON.parse(log) : {} if (!log[date]) log[date] = {} if (!log[date][uuid]) log[date][uuid] = 0 log[date][uuid] += 1 localStorage.setItem('readlog', JSON.stringify(log)) } function updateGist() { let gist_id = "cfa70a44bb181edbb2be19dacbcf6808" let filename = "read_log.json" let log = localStorage.getItem('readlog') log = log ? JSON.parse(log) : {} // pull gist_get_async(gist_id, filename).then((content) => { let remoteLog = JSON.parse(content) for (let [date, data] of Object.entries(remoteLog)) { if (!log[date]) { log[date] = data; continue } for (let [uuid, count] of Object.entries(data)) { if (uuid != getUuid()) { log[date][uuid] = count } } } // push gist_set_async(gist_id, filename, JSON.stringify(log)).then((response) => { alert("update success") }) localStorage.setItem('readlog', JSON.stringify(log)) refreshHeatmap() }) } //-------------------------------- statistics -------------------------------- // chapter_dom = document.querySelector("div.chapter-detail") // if (!chapter_dom) chapter_dom = document.body // heatmap_panel = document.createElement("div") // chapter_dom.before(heatmap_panel) // heatmap_panel.innerHTML = `<canvas id="heatmap" width="` + canvasWidth + `" height="` + canvasHeight + `"></canvas>` // canvas = document.querySelector("canvas#heatmap") // canvas.onclick = updateGist // refreshHeatmap() //-------------------------------- wpm -------------------------------- // function log(){ // addLine() // uuid=getUuid() // date=getDateStr() // updateLocalLog(uuid, date) // lastGistUpdateDate=localStorage.getItem('lastGistUpdateDate') // if (!lastGistUpdateDate || lastGistUpdateDate!=date){ // updateGist() // localStorage.setItem('lastGistUpdateDate', date) // } // refreshHeatmap() // } // document.log=log // setInterval(()=>{document.log()},1000*60) // refreshHeatmap() addStyle(` canvas#wpmCanvas { background-color: #333; position: fixed; bottom: 0px; right: 100px; width: 50px; height: 50px; opacity: 0.8; z-index: 3000; } `) // wpm_dom = document.createElement('div') // document.body.before(wpm_dom) // wpm_dom.innerHTML = `<canvas id="wpmCanvas" width="50px" height="50px"></canvas>` // let wpmQueue=[0] function drawWpmCanvas(){ // console.log('draw') let canvas = document.querySelector("canvas#wpmCanvas") let ctx = canvas.getContext('2d'); ctx.clearRect(0, 0, canvas.width, canvas.height); // lines ctx.beginPath(); ctx.moveTo(50,50-50*Math.min(wpmQueue[wpmQueue.length-1]/500, 1)); for(let i=wpmQueue.length-1;i>=0;i--){ let y=50*Math.min(wpmQueue[i]/500,1); let x=50-(wpmQueue.length-1-i)*5-5; ctx.lineTo(x, 50-y); // console.log(x, y) } ctx.strokeStyle = "white"; ctx.stroke(); // draw wpm number ctx.font = "16px Arial bold"; ctx.fillStyle = "#9aa83a"; ctx.fillText(wpmQueue[wpmQueue.length-1], 5, 21); } // drawWpmCanvas() // let wpmArea = document.createElement("div") // wpmArea.id="wpmArea" // wpmArea.classList.add("wpmArea") // wpmArea.style.top = "0px" // wpmArea.style.height = "0px" // document.body.before(wpmArea) let forceUpdateWpmArea=false; let lastStartTime=new Date().getTime() function updateWpmArea(){ let _lineStart=parseInt(wpmArea.style.top.replace("px","")) let _lineEnd=_lineStart+parseInt(wpmArea.style.height.replace("px","")) let lineEnd=document.documentElement["scrollTop"]+window.innerHeight*0.2 let lineStart=Math.min(_lineEnd, lineEnd)-1; // queue push if(new Date().getTime()-lastStartTime>1000*60 || forceUpdateWpmArea){ forceUpdateWpmArea=false; lastStartTime=new Date().getTime() wpmArea.style.top=lineStart+"px" wpmQueue.push(wpmArea[wpmQueue.length-1]) } wpmArea.style.height=(lineEnd-_lineStart)+"px" let words_cnt=countWords(_lineStart, lineEnd) // console.log(_lineStart, lineEnd, words_cnt) wpmQueue[wpmQueue.length-1]=Math.round(words_cnt/((new Date().getTime()-lastStartTime)/1000/60)) // drawWpmCanvas() } // let wpmInterval=setInterval(updateWpmArea, 1000) // document.querySelector('canvas#wpmCanvas').onclick = function(){ // forceUpdateWpmArea=true; // updateWpmArea() // updateWpmArea() // } function countWords(lineStart, lineEnd){ let items=document.querySelector('div.chapterContent') if(!items) return 0; items=items.querySelectorAll('p') let words_cnt=0; for(let item of items){ let top=item.offsetTop; let text=item.innerText; let height=item.offsetHeight; let _words_cnt=text.split(" ").length; let end=top+height; if(lineStart > end || lineEnd < top) continue; if(lineStart<top && lineEnd>end){ words_cnt+=_words_cnt; // console.log("1: "+text) }else if(lineStart<top && lineEnd>top){ words_cnt+=_words_cnt*(lineEnd-top)/height; // console.log("2: "+text) }else if(lineStart<end && lineEnd>end){ words_cnt+=_words_cnt*(end-lineStart)/height; // console.log("3: "+text) }else if(lineStart>top && lineEnd<end){ words_cnt+=_words_cnt*(lineEnd-lineStart)/height; // console.log("4: "+text) } } return Math.round(words_cnt) } let cnt=countWords(0, 100000) console.log(cnt) //-------------------------------- history -------------------------------- let chapter_dom = document.querySelector("div.chapter-detail") if (!chapter_dom) chapter_dom = document.body let history_panel = document.createElement("div") chapter_dom.before(history_panel) history_panel.innerHTML = `<div> <table id="history_table"> </table> <button id="history_prev" class="pagiBtn">\<</button> <button id="history_next" class="pagiBtn">\></button> <input id="history_input" type="text" value="1" size="3"> <button id="history_go" class="pagiBtn">go</button> </div>` let history_data = localStorage.getItem('history_data') history_data = history_data ? JSON.parse(history_data) : {} history_data[location.href] = { date: new Date().getTime(), title: document.title.replace(" - Wikipedia", ''), url: location.href } localStorage.setItem('history_data', JSON.stringify(history_data)) let history_list = Object.values(history_data).sort((a, b) => { return b.date - a.date }) function setHistoryTable(page) { page = page ? page : 1 let history_pageSize = 10 let history_table = document.querySelector("#history_table") history_table.innerHTML = "" let start = (page - 1) * history_pageSize let end = Math.min(start + history_pageSize, history_list.length) for (let i = start; i < end; i++) { let day = new Date(history_list[i].date).getDate() history_table.innerHTML += `<tr> <td class="historyDay`+ day + `">` + getHistoryDateStr(history_list[i].date) + `</td> <td><a href="`+ history_list[i].url + `">` + history_list[i].title + `</a></td> </tr>` } } setHistoryTable(1) document.querySelector('#history_prev').onclick = () => { let history_page = document.querySelector('#history_input').value; setHistoryTable(--history_page); document.querySelector('#history_input').value = history_page } document.querySelector('#history_next').onclick = () => { let history_page = document.querySelector('#history_input').value; setHistoryTable(++history_page); document.querySelector('#history_input').value = history_page } document.querySelector('#history_go').onclick = () => { let history_page = document.querySelector('#history_input').value; setHistoryTable(history_page); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址