惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

宝玉的分享
宝玉的分享
NISL@THU
NISL@THU
E
Exploit-DB.com RSS Feed
L
LINUX DO - 热门话题
L
Lohrmann on Cybersecurity
K
Kaspersky official blog
Project Zero
Project Zero
Cisco Talos Blog
Cisco Talos Blog
T
The Exploit Database - CXSecurity.com
P
Palo Alto Networks Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
Threatpost
S
Schneier on Security
G
GRAHAM CLULEY
The Hacker News
The Hacker News
T
Threat Research - Cisco Blogs
Scott Helme
Scott Helme
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Privacy & Cybersecurity Law Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Cyberwarzone
Cyberwarzone
C
CERT Recently Published Vulnerability Notes
T
Tor Project blog
AWS News Blog
AWS News Blog
Simon Willison's Weblog
Simon Willison's Weblog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
爱范儿
爱范儿
P
Privacy International News Feed
云风的 BLOG
云风的 BLOG
P
Proofpoint News Feed
S
Securelist
G
Google Developers Blog
The Last Watchdog
The Last Watchdog
Google Online Security Blog
Google Online Security Blog
美团技术团队
F
Fortinet All Blogs
小众软件
小众软件
Recorded Future
Recorded Future
V
Visual Studio Blog
B
Blog RSS Feed
H
Help Net Security
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Google DeepMind News
Google DeepMind News
Blog — PlanetScale
Blog — PlanetScale
博客园 - 聂微东
Stack Overflow Blog
Stack Overflow Blog
Martin Fowler
Martin Fowler
Latest news
Latest news
Spread Privacy
Spread Privacy
H
Heimdal Security Blog

爱吃肉的猫

那就,再相逢 Butterfly的魔改教程:最新评论页 离歌不夜天 前端分享 - 滑动阻尼效果 音乐分享 - doi微醺氛围 Butterfly的魔改教程:动态相册页 近况记事 - 11 微信公众号:Ai大模型让回复更具智能化 近况记事 - 10 PWA:让你的网站变成桌面应用APP Healthy Love Butterfly的魔改教程:关于本站 近况记事 - 9 Butterfly的魔改教程:待办清单 TrollStore - 不掉签助手 近况记事 - 8 Twikoo评论回复邮件模版 过一个很特别的七夕 The Young Boy and the Sea Butterfly的魔改教程:文章订阅页 思考题目:混乱是阶梯 近况记事 - 7 Butterfly的魔改教程:即刻短文页 Butterfly的魔改教程:loading加载动画 差旅游记 再见,不惑之年:二十又一 近况记事 - 6 Butterfly的魔改教程:自定页数跳转 堆友AI作图:3D资源设计平台,堆出你的未来 【QD-Today】自建私有自动签到服务 Long time no see Butterfly的魔改教程:聊天记录页 Butterfly的魔改教程:个性定位信息 近况记事 - 5 Butterfly的魔改教程:好物推荐页 CDN加速 二刷《想见你》 网络言论不是法外之地 近况记事 - 4 深夜训斥 近况记事 - 3 近况记事 - 2 日常打理的那些事 Butterfly的魔改教程:随机阅读一篇文章 随笔 · 封 布柒糖FM项目进展报告 清明路雨纷纷 TA - 仲夏夜的荒原 重构记录 - 4 近况记事 Butterfly的魔改教程:评论弹窗 2021款 Model Y 近两年用车总结 重构记录 - 3 百日祭 避风的港湾 Emoji表情大全 iCat-APP 开源记录 Butterfly的调整教程:文章外挂标签美化 iOS修改 - 万铲铲的致富之路 Markdown 基础教程 从你的全世界路过 小米摄像头!避!雷! VuePress 搭建教程 Hexo跳过指定文件渲染 百度贴吧每日自动签到 重构记录 - 1 GitHub Desktop提交报错 快速批量处理重命名 Git连接仓库常用命令 Ubuntu处理deb命令 掘金自动签到并挖矿 一个简洁的橙色调个人简介 我的猫以前也是流浪猫 布柒糖FM 最新指北 初学写个了油猴脚本 幽灵404页面 PC游戏 · 植物大战僵尸 语言包 · 越狱篇 砸壳多开 · 越狱篇 HuiRan Cursors 手动关闭Win10自动更新 iPhone XR 完美越狱 成功实例 三年的跌撞 关于《小橘妈妈》 魔改前置教程:添加自定义css和js文件 Hexo 博客添加RSS插件 Butterfly的魔改教程:导航栏魔改美化
Butterfly的魔改教程:右键菜单
亦小封 · 2024-04-01 · via 爱吃肉的猫
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
.js-pjax
#rightMenu
.rightMenu-group.rightMenu-small
.rightMenu-item#menu-backward
i.MeuiCat.icon-arrow-left-line
.rightMenu-item#menu-forward
i.MeuiCat.icon-arrow-right-line
.rightMenu-item#menu-refresh
i.MeuiCat.icon-restart-line
.rightMenu-item#menu-top
i.MeuiCat.icon-arrow-up-line
.rightMenu-group.rightMenuPost
if theme.readmode
.rightMenu-item#menu-reading
i.MeuiCat.icon-read-fill
span= '阅读模式'
//- .rightMenu-item#menu-commentBarrage
//- i.MeuiCat.icon-chat-fill
//- span= '评论弹窗'
.rightMenu-item#menu-postlink
i.MeuiCat.icon-external-link-fill
span= '分享本文'
.rightMenu-group.rightMenuPlugin
if theme.comments.use
.rightMenu-item#menu-commenttext
i.MeuiCat.icon-chat-new-fill
span= '引用评论'
.rightMenu-item#menu-copytext
i.MeuiCat.icon-copy-fill
span= '复制内容'
.rightMenu-item#menu-pastetext
i.MeuiCat.icon-clipboard-fill
span= '粘贴内容'
//- if theme.search.use
//- .rightMenu-item#menu-search
//- i.MeuiCat.icon-search-line
//- span= '站内搜索'
.rightMenu-item#menu-searchBaidu
i.MeuiCat.icon-baidu-fill
span= '百度搜索'
.rightMenu-item#menu-newwindow
i.MeuiCat.icon-window-fill
span= '新建窗口打开'
.rightMenu-item#menu-copylink
i.MeuiCat.icon-link-m-line
span= '复制链接地址'
.rightMenu-item#menu-copyimg
i.MeuiCat.icon-copy-fill
span= '复制此图片'
.rightMenu-item#menu-downloadimg
i.MeuiCat.icon-download-cloud-fill
span= '下载此图片'
.rightMenu-group.rightMenuOther
//- a.rightMenu-item#menu-randomPost
//- i.MeuiCat.icon-dice-fill
//- span= '随便逛逛'
if theme.darkmode.enable
.rightMenu-item#menu-darkmode
i.MeuiCat.icon-moon-clear-fill
span= '显示模式'
if theme.translate.enable
a.rightMenu-item#menu-translate
i.MeuiCat.icon-panben-line
span= '繁简转换'
.rightMenu-item#menu-asidehide
i.MeuiCat.icon-side-bar-fill
span= '边栏控制'
.rightMenu-group
a.rightMenu-item(href="/privacy/")
i.MeuiCat.icon-shield-user-fill
span= '隐私协议'
a.rightMenu-item(href="/cc/")
i.MeuiCat.icon-creative-commons-fill
span= '版权协议'
#rightMenu-mask
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






class RightMenu {
constructor() {
this.selectTextNow = ""
this.domhref = ""
this.domImgSrc = ""
this.globalEvent = null
this.downloadimging = false
this.rmWidth = 0
this.rmHeight = 0
this.toLocal = btf.saveToLocal.get('rightside-status')
this.isEnabled = !this.toLocal || this.toLocal !== 'off' ? true : false
this.initialize()
window.rightMenu = undefined
}

initialize() {
window.addEventListener('load', () => {
this.addRightMenuClickEvent()
document.onmouseup = document.ondbclick = this.selceText.bind(this)
btf.addGlobalFn('pjaxComplete', () => { this.addRightMenuClickEvent() }, 'addRightMenuClickEvent')
})

window.oncontextmenu = (e) => this.onContextMenu(e)
}

enable() {
this.isEnabled = true
typeof !window.rightMenu && (window.rightMenu = {
getSelectTextNow: () => rightMenu.getSelectTextNow()
})
}

disable() {
this.isEnabled = false
typeof window.rightMenu && (window.rightMenu = undefined)
}

addRightMenuClickEvent() {
const menuItems = {
"rightMenu-mask": [this.hideRightMenu.bind(this)],
"menu-backward": [() => { window.history.back(); this.hideRightMenu() }],
"menu-forward": [() => { window.history.forward(); this.hideRightMenu() }],
"menu-refresh": [() => { this.hideRightMenu(); window.location.reload() }],
"menu-top": [() => { this.hideRightMenu(); btf.scrollToDest(0, 500) }],
"menu-darkmode": [() => { this.hideRightMenu(); document.querySelector('#darkmode').click() }],
"menu-translate": [() => { this.hideRightMenu(); typeof rightSideFn === 'object' && rightSideFn.translateLink() }],
"menu-reading": [() => { this.hideRightMenu(); document.querySelector('#readmode').click() }],
"menu-postlink": [this.copyPostUrl.bind(this)],
"menu-search": [this.hideRightMenu.bind(this)],
"menu-asidehide": [() => { this.hideRightMenu(); document.querySelector('#hide-aside-btn').click() }],
"menu-copytext": [() => { this.rightmenuCopyText(this.selectTextNow); GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow("复制成功,复制和转载请标注本文地址") }],
"menu-commenttext": [() => { commentText(this.selectTextNow); this.hideRightMenu() }],
"menu-searchBaidu": [this.searchBaidu.bind(this)],
"menu-newwindow": [() => { window.open(this.domhref); this.hideRightMenu() }],
"menu-copylink": [() => { this.rightmenuCopyText(this.domhref); GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow("已复制链接地址") }],
"menu-pastetext": [this.pasteText.bind(this)],
"menu-copylinkimg": [() => { this.rightmenuCopyText(this.domImgSrc); GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow("已复制图片链接") }],
"menu-copyimg": [() => { this.copyImage(this.domImgSrc) }],
"menu-downloadimg": [() => { this.downloadImage(this.domImgSrc, "MeuiCat") }],
"menu-commentBarrage": [() => { this.hideRightMenu(); typeof comment === 'object' && comment.closeBarrage() }],
"menu-randomPost": [() => { this.hideRightMenu(); toRandomPost() }]
}

for (let id in menuItems) {
const element = document.getElementById(id)
if (element) menuItems[id].forEach(fn => { element.addEventListener("click", fn) })
}

document.getElementById("rightMenu-mask").addEventListener("contextmenu", () => {
this.hideRightMenu()
return false
})
}

reloadrmSize() {
const menu = document.getElementById("rightMenu")
this.rmWidth = menu.offsetWidth
this.rmHeight = menu.offsetHeight
}

showRightMenu(more, mouseY = 0, mouseX = 0) {
const rightMenu = document.getElementById("rightMenu")

if (more) {
rightMenu.style.display = "block"
this.reloadrmSize()

mouseX + this.rmWidth + 20 > window.innerWidth && (mouseX -= this.rmWidth + 20)
mouseY + this.rmHeight > window.innerHeight && (mouseY -= mouseY + this.rmHeight - window.innerHeight + 20)
rightMenu.style.top = mouseY + "px"
rightMenu.style.left = mouseX + "px"

document.getElementById("rightMenu-mask").style.display = "flex"
this.stopMaskScroll()
} else {
rightMenu.style.display = "none"
}
}

hideRightMenu() {
this.showRightMenu(false)
document.getElementById("rightMenu-mask").style.display = "none"
}

getSelectTextNow() {
return this.selectTextNow
}

stopMaskScroll() {
const elements = ["rightMenu-mask", "rightMenu"]
elements.forEach(id => {
const element = document.getElementById(id)
if (element) element.addEventListener("mousewheel", this.hideRightMenu.bind(this), false)
})
}

selceText() {
this.selectTextNow = window.getSelection ? window.getSelection().toString() : document.selection ? document.selection.createRange().text : ""
}

copyPostUrl() {
this.copyUrl(window.location.href)
GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow("复制本页链接地址成功", false, 2000)
this.hideRightMenu()
}

searchBaidu() {
GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow("即将跳转到百度搜索", false, 2000)
setTimeout(() => { window.open("https://www.baidu.com/s?wd=" + this.selectTextNow) }, 2000)
this.hideRightMenu()
}

pasteText() {
if (navigator.clipboard) navigator.clipboard.readText().then((text) => this.insertAtCaret(this.globalEvent.target, text))
this.hideRightMenu()
}

insertAtCaret(input, text) {
const start = input.selectionStart
const end = input.selectionEnd
if (document.selection) {
input.focus()
document.selection.createRange().text = text
input.focus()
} else if (start || start === 0) {
const scrollTop = input.scrollTop
input.value = input.value.substring(0, start) + text + input.value.substring(end, input.value.length)
input.focus()
input.selectionStart = start + text.length
input.selectionEnd = start + text.length
input.scrollTop = scrollTop
} else {
input.value += text
input.focus()
}
}

rightmenuCopyText(text) {
if (navigator.clipboard) navigator.clipboard.writeText(text)
this.hideRightMenu()
}

imageToBlob(imgSrc, options = {}) {
const { fileName, action = "download", callback } = options
const canvas = document.createElement("canvas")
const context = canvas.getContext("2d")
const img = new Image()

img.crossOrigin = 'anonymous'
img.src = imgSrc

return new Promise((resolve, reject) => {
img.onload = function () {
canvas.width = img.width
canvas.height = img.height
context.drawImage(this, 0, 0)

if (action === 'copy') {
canvas.toBlob((blob) => {
const item = new ClipboardItem({ "image/png": blob })
navigator.clipboard.write([item]).then(() => {
callback && callback("复制成功!图片已添加盲水印,请遵守版权协议")
resolve()
})
}, "image/png", 0.75)
} else if (action === 'download') {
const dataURL = canvas.toDataURL("image/png")
const a = document.createElement("a")
const event = new MouseEvent("click")
a.download = fileName || "image.png"
a.href = dataURL
a.dispatchEvent(event)
callback && callback("图片已添加盲水印,请遵守版权协议")
resolve()
}
}

img.onerror = () => {
callback && callback("图片加载失败,请检查跨域或网络连接")
reject(new Error("Image load error"))
}
})
}

copyImage(imgSrc) {
this.hideRightMenu()
const time = window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1" ? 0 : 5000
if (this.downloadimging) return GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow("有正在进行中的任务,请稍后再试", false, time)
this.downloadimging = true

setTimeout(() => {
this.imageToBlob(imgSrc, {
action: "copy",
callback: (msg) => {
GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow(msg)
this.downloadimging = false
}
})
}, time)
}

downloadImage(imgSrc, fileName) {
this.hideRightMenu()
if (this.downloadimging) return GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow("有正在进行中的下载,请稍后再试")
this.downloadimging = true
GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow("正在下载中,请稍后", false, 10000)

setTimeout(() => {
this.imageToBlob(imgSrc, {
action: "download",
fileName: fileName,
callback: (msg) => {
GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow(msg)
this.downloadimging = false
}
})
}, 10000)
}

onContextMenu(e) {
if (this.isEnabled && document.body.clientWidth > 768) {
const mouseX = e.clientX + 12,
mouseY = e.clientY,
target = e.target,
menus = {
rightMenuPost: document.querySelector(".rightMenuPost"),
rightMenuPlugin: document.querySelector(".rightMenuPlugin"),
rightMenuOther: document.querySelector(".rightMenuOther"),
},
menuItems = {
menuCopyText: { element: document.getElementById("menu-copytext"), condition: () => this.selectTextNow && window.getSelection },
menuCommentText: { element: document.getElementById("menu-commenttext"), condition: () => this.selectTextNow && document.getElementById("post-comment") },
menuSearch: { element: document.getElementById("menu-search"), condition: () => this.selectTextNow },
menuSearchBaidu: { element: document.getElementById("menu-searchBaidu"), condition: () => this.selectTextNow },
menuNewWindow: { element: document.getElementById("menu-newwindow"), condition: () => !!target.href },
menuCopyLink: { element: document.getElementById("menu-copylink"), condition: () => !!target.href },
menuCopyImage: { element: document.getElementById("menu-copyimg"), condition: () => !!target.currentSrc },
menuDownloadImage: { element: document.getElementById("menu-downloadimg"), condition: () => !!target.currentSrc },
menuPasteText: { element: document.getElementById("menu-pastetext"), condition: () => ["input", "textarea"].includes(target.tagName.toLowerCase()) },
}

this.domhref = target.href || ""
this.domImgSrc = target.src || ""

Object.values(menuItems).forEach(({ element, condition }) => { if (element) element.style.display = condition() ? "block" : "none" })

const isTextSelected = Object.values(menuItems).some(({ condition }) => condition())
menus.rightMenuPost.style.display = isTextSelected || !!target.href || !!target.currentSrc ? "none" : document.querySelector("#body-wrap.post") ? "block" : "none"
menus.rightMenuPlugin.style.display = isTextSelected ? "block" : "none"
menus.rightMenuOther.style.display = isTextSelected ? "none" : "block"

const isReadMode = document.querySelector(".read-mode");
["menu-commentBarrage", "menu-postlink", "menu-randomPost", "menu-asidehide"].forEach((id) => {
const element = document.getElementById(id)
if (element) element.style.display = isReadMode ? "none" : "block"
})

this.showRightMenu(e, mouseY, mouseX)
e.preventDefault()
return false
} else {
return true
}
}
}

const rightMenu = new RightMenu()

复制图片下载图片 这两个功能都需要浏览器支持ClipboardItemAPI,并且图片服务器正确设置CORS跨域。
如遇错误提示,大概率就是涉及到跨域问题。自行设置解决。