🏷️ 小鱼标签 (UTags) - 为链接添加用户标签

这是个超实用的工具,能给用户、帖子、视频等链接添加自定义标签和备注信息。比如,可以给论坛的用户或帖子添加标签,易于识别他们或屏蔽他们的帖子和回复。支持 V2EX, X, Reddit, Greasy Fork, GitHub, B站, 抖音, 小红书, 知乎, 掘金, 豆瓣, 吾爱破解, pixiv, LINUX DO, 小众软件, NGA 等网站。

目前为 2025-03-02 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name 🏷️ UTags - Add usertags to links
  3. // @name:zh-CN 🏷️ 小鱼标签 (UTags) - 为链接添加用户标签
  4. // @namespace https://utags.pipecraft.net/
  5. // @homepageURL https://github.com/utags/utags#readme
  6. // @supportURL https://github.com/utags/utags/issues
  7. // @version 0.12.8
  8. // @description Add custom tags or notes to links such as users, posts and videos. For example, tags can be added to users or posts on a forum, making it easy to identify them or block their posts and replies. It works on X (Twitter), Reddit, Facebook, Threads, Instagram, Youtube, TikTok, GitHub, Greasy Fork, Hacker News, pixiv and numerous other websites.
  9. // @description:zh-CN 这是个超实用的工具,能给用户、帖子、视频等链接添加自定义标签和备注信息。比如,可以给论坛的用户或帖子添加标签,易于识别他们或屏蔽他们的帖子和回复。支持 V2EX, X, Reddit, Greasy Fork, GitHub, B站, 抖音, 小红书, 知乎, 掘金, 豆瓣, 吾爱破解, pixiv, LINUX DO, 小众软件, NGA 等网站。
  10. // @icon data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%23ff6361' class='bi bi-tags-fill' viewBox='0 0 16 16'%3E %3Cpath d='M2 2a1 1 0 0 1 1-1h4.586a1 1 0 0 1 .707.293l7 7a1 1 0 0 1 0 1.414l-4.586 4.586a1 1 0 0 1-1.414 0l-7-7A1 1 0 0 1 2 6.586V2zm3.5 4a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z'/%3E %3Cpath d='M1.293 7.793A1 1 0 0 1 1 7.086V2a1 1 0 0 0-1 1v4.586a1 1 0 0 0 .293.707l7 7a1 1 0 0 0 1.414 0l.043-.043-7.457-7.457z'/%3E %3C/svg%3E
  11. // @author Pipecraft
  12. // @license MIT
  13. // @match https://x.com/*
  14. // @match https://twitter.com/*
  15. // @match https://github.com/*
  16. // @match https://www.reddit.com/*
  17. // @match https://www.instagram.com/*
  18. // @match https://www.threads.net/*
  19. // @match https://*.facebook.com/*
  20. // @match https://*.youtube.com/*
  21. // @match https://www.tiktok.com/*
  22. // @match https://*.bilibili.com/*
  23. // @match https://*.biligame.com/*
  24. // @match https://greasyfork.org/*
  25. // @match https://lobste.rs/*
  26. // @match https://news.ycombinator.com/*
  27. // @match https://*.v2ex.com/*
  28. // @match https://*.v2ex.co/*
  29. // @match https://*.zhihu.com/*
  30. // @match https://*.weibo.com/*
  31. // @match https://*.weibo.cn/*
  32. // @match https://*.douban.com/*
  33. // @match https://www.52pojie.cn/*
  34. // @match https://juejin.cn/*
  35. // @match https://mp.weixin.qq.com/*
  36. // @match https://www.xiaohongshu.com/*
  37. // @match https://sspai.com/*
  38. // @match https://www.douyin.com/*
  39. // @match https://podcasts.google.com/*
  40. // @match https://sleazyfork.org/*
  41. // @match https://tilde.news/*
  42. // @match https://www.journalduhacker.net/*
  43. // @match https://rebang.today/*
  44. // @match https://myanimelist.net/*
  45. // @match https://www.pixiv.net/*
  46. // @match https://linux.do/*
  47. // @match https://meta.appinn.net/*
  48. // @match https://meta.discourse.org/*
  49. // @match https://community.openai.com/*
  50. // @match https://community.cloudflare.com/*
  51. // @match https://bbs.nga.cn/*
  52. // @match https://nga.178.com/*
  53. // @match https://ngabbs.com/*
  54. // @match https://www.dlsite.com/*
  55. // @match https://keylol.com/*
  56. // @match https://kemono.su/*
  57. // @match https://coomer.su/*
  58. // @match https://nekohouse.su/*
  59. // @match https://rule34video.com/*
  60. // @match https://rule34gen.com/*
  61. // @match https://community.wanikani.com/*
  62. // @match https://panda.chaika.moe/*
  63. // @match https://bbs.tampermonkey.net.cn/*
  64. // @match https://discuss.flarum.org/*
  65. // @match https://discuss.flarum.org.cn/*
  66. // @match https://www.nodeloc.com/*
  67. // @match https://freesmth.net/*
  68. // @match https://freesmth.uk/*
  69. // @match https://veryfb.com/*
  70. // @match https://www.nodeseek.com/*
  71. // @match https://*.inoreader.com/*
  72. // @match https://kater.me/*
  73. // @match https://bbs.viva-la-vita.org/*
  74. // @match https://v2hot.pipecraft.net/*
  75. // @match https://utags.pipecraft.net/*
  76. // @match https://*.pipecraft.net/*
  77. // @run-at document-start
  78. // @grant GM.getValue
  79. // @grant GM.setValue
  80. // @grant GM_addValueChangeListener
  81. // @grant GM_removeValueChangeListener
  82. // @grant GM_addElement
  83. // @grant GM.registerMenuCommand
  84. // ==/UserScript==
  85. //
  86. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  87. //// The Official Installation URLs ////
  88. //// 官方安装网址 ////
  89. //// ////
  90. //// * https://greasyfork.org/scripts/460718-utags-add-usertags-to-links ////
  91. //// ** downloadURL https://update.greasyfork.org/scripts/460718/%F0%9F%8F%B7%EF%B8%8F%20UTags%20-%20Add%20usertags%20to%20links.user.js ////
  92. //// * https://scriptcat.org/script-show-page/2784 ////
  93. //// ** downloadURL https://scriptcat.org/scripts/code/2784/%F0%9F%8F%B7%EF%B8%8F+UTags+-+Add+usertags+to+links.user.js ////
  94. //// * https://github.com/utags/utags ////
  95. //// ** downloadURL https://github.com/utags/utags/raw/main/build/userscript-prod/utags.user.js ////
  96. //// * https://gist.github.com/PipecraftNet/38d90a567ff04660f2a1b5430af9ae96 ////
  97. //// ** downloadURL https://gist.github.com/PipecraftNet/38d90a567ff04660f2a1b5430af9ae96/raw/utags.user.js ////
  98. //// ////
  99. //// ////
  100. //// Extension Version ////
  101. //// 浏览器扩展版本 ////
  102. //// * Chrome Web Store - https://chromewebstore.google.com/detail/utags-add-usertags-to-lin/kofjcnaphffjoookgahgjidofbdplgig ////
  103. //// * Edge Add-ons - https://microsoftedge.microsoft.com/addons/detail/utags-add-usertags-to-l/bhlbflbehfoccjjenpekilgabbjjnphe ////
  104. //// * Firefox Addon Store - https://addons.mozilla.org/firefox/addon/utags/ ////
  105. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  106. //
  107. ;(() => {
  108. "use strict"
  109. var listeners = {}
  110. var getValue = async (key) => {
  111. const value = await GM.getValue(key)
  112. return value && value !== "undefined" ? JSON.parse(value) : void 0
  113. }
  114. var setValue = async (key, value) => {
  115. if (value !== void 0) {
  116. const newValue = JSON.stringify(value)
  117. if (listeners[key]) {
  118. const oldValue = await GM.getValue(key)
  119. await GM.setValue(key, newValue)
  120. if (newValue !== oldValue) {
  121. for (const func of listeners[key]) {
  122. func(key, oldValue, newValue)
  123. }
  124. }
  125. } else {
  126. await GM.setValue(key, newValue)
  127. }
  128. }
  129. }
  130. var _addValueChangeListener = (key, func) => {
  131. listeners[key] = listeners[key] || []
  132. listeners[key].push(func)
  133. return () => {
  134. if (listeners[key] && listeners[key].length > 0) {
  135. for (let i3 = listeners[key].length - 1; i3 >= 0; i3--) {
  136. if (listeners[key][i3] === func) {
  137. listeners[key].splice(i3, 1)
  138. }
  139. }
  140. }
  141. }
  142. }
  143. var addValueChangeListener = (key, func) => {
  144. if (typeof GM_addValueChangeListener !== "function") {
  145. console.warn("Do not support GM_addValueChangeListener!")
  146. return _addValueChangeListener(key, func)
  147. }
  148. const listenerId = GM_addValueChangeListener(key, func)
  149. return () => {
  150. GM_removeValueChangeListener(listenerId)
  151. }
  152. }
  153. var doc = document
  154. var win = window
  155. var uniq = (array) => [...new Set(array)]
  156. if (typeof String.prototype.replaceAll !== "function") {
  157. String.prototype.replaceAll = String.prototype.replace
  158. }
  159. var $ = (selectors, element) => (element || doc).querySelector(selectors)
  160. var $$ = (selectors, element) => [
  161. ...(element || doc).querySelectorAll(selectors),
  162. ]
  163. var getRootElement = (type) =>
  164. type === 1
  165. ? doc.head || doc.body || doc.documentElement
  166. : type === 2
  167. ? doc.body || doc.documentElement
  168. : doc.documentElement
  169. var createElement = (tagName, attributes) =>
  170. setAttributes(doc.createElement(tagName), attributes)
  171. var addElement = (parentNode, tagName, attributes) => {
  172. if (typeof parentNode === "string") {
  173. return addElement(null, parentNode, tagName)
  174. }
  175. if (!tagName) {
  176. return
  177. }
  178. if (!parentNode) {
  179. parentNode = /^(script|link|style|meta)$/.test(tagName)
  180. ? getRootElement(1)
  181. : getRootElement(2)
  182. }
  183. if (typeof tagName === "string") {
  184. const element = createElement(tagName, attributes)
  185. parentNode.append(element)
  186. return element
  187. }
  188. setAttributes(tagName, attributes)
  189. parentNode.append(tagName)
  190. return tagName
  191. }
  192. var addEventListener = (element, type, listener, options) => {
  193. if (!element) {
  194. return
  195. }
  196. if (typeof type === "object") {
  197. for (const type1 in type) {
  198. if (Object.hasOwn(type, type1)) {
  199. element.addEventListener(type1, type[type1])
  200. }
  201. }
  202. } else if (typeof type === "string" && typeof listener === "function") {
  203. element.addEventListener(type, listener, options)
  204. }
  205. }
  206. var removeEventListener = (element, type, listener, options) => {
  207. if (!element) {
  208. return
  209. }
  210. if (typeof type === "object") {
  211. for (const type1 in type) {
  212. if (Object.hasOwn(type, type1)) {
  213. element.removeEventListener(type1, type[type1])
  214. }
  215. }
  216. } else if (typeof type === "string" && typeof listener === "function") {
  217. element.removeEventListener(type, listener, options)
  218. }
  219. }
  220. var getAttribute = (element, name) =>
  221. element && element.getAttribute ? element.getAttribute(name) : null
  222. var setAttribute = (element, name, value) =>
  223. element && element.setAttribute ? element.setAttribute(name, value) : void 0
  224. var setAttributes = (element, attributes) => {
  225. if (element && attributes) {
  226. for (const name in attributes) {
  227. if (Object.hasOwn(attributes, name)) {
  228. const value = attributes[name]
  229. if (value === void 0) {
  230. continue
  231. }
  232. if (/^(value|textContent|innerText)$/.test(name)) {
  233. element[name] = value
  234. } else if (/^(innerHTML)$/.test(name)) {
  235. element[name] = createHTML(value)
  236. } else if (name === "style") {
  237. setStyle(element, value, true)
  238. } else if (/on\w+/.test(name)) {
  239. const type = name.slice(2)
  240. addEventListener(element, type, value)
  241. } else {
  242. setAttribute(element, name, value)
  243. }
  244. }
  245. }
  246. }
  247. return element
  248. }
  249. var addClass = (element, className) => {
  250. if (!element || !element.classList) {
  251. return
  252. }
  253. element.classList.add(className)
  254. }
  255. var removeClass = (element, className) => {
  256. if (!element || !element.classList) {
  257. return
  258. }
  259. element.classList.remove(className)
  260. }
  261. var hasClass = (element, className) => {
  262. if (!element || !element.classList) {
  263. return false
  264. }
  265. return element.classList.contains(className)
  266. }
  267. var setStyle = (element, values, overwrite) => {
  268. if (!element) {
  269. return
  270. }
  271. const style = element.style
  272. if (typeof values === "string") {
  273. style.cssText = overwrite ? values : style.cssText + ";" + values
  274. return
  275. }
  276. if (overwrite) {
  277. style.cssText = ""
  278. }
  279. for (const key in values) {
  280. if (Object.hasOwn(values, key)) {
  281. style[key] = values[key].replace("!important", "")
  282. }
  283. }
  284. }
  285. var isUrl = (text) => /^https?:\/\//.test(text)
  286. var throttle = (func, interval) => {
  287. let timeoutId = null
  288. let next = false
  289. const handler = (...args) => {
  290. if (timeoutId) {
  291. next = true
  292. } else {
  293. func.apply(void 0, args)
  294. timeoutId = setTimeout(() => {
  295. timeoutId = null
  296. if (next) {
  297. next = false
  298. handler()
  299. }
  300. }, interval)
  301. }
  302. }
  303. return handler
  304. }
  305. if (typeof Object.hasOwn !== "function") {
  306. Object.hasOwn = (instance, prop) =>
  307. Object.prototype.hasOwnProperty.call(instance, prop)
  308. }
  309. var extendHistoryApi = () => {
  310. const pushState = history.pushState
  311. const replaceState = history.replaceState
  312. history.pushState = function () {
  313. pushState.apply(history, arguments)
  314. window.dispatchEvent(new Event("pushstate"))
  315. window.dispatchEvent(new Event("locationchange"))
  316. }
  317. history.replaceState = function () {
  318. replaceState.apply(history, arguments)
  319. window.dispatchEvent(new Event("replacestate"))
  320. window.dispatchEvent(new Event("locationchange"))
  321. }
  322. window.addEventListener("popstate", function () {
  323. window.dispatchEvent(new Event("locationchange"))
  324. })
  325. }
  326. var getOffsetPosition = (element, referElement) => {
  327. const position = { top: 0, left: 0 }
  328. referElement = referElement || doc.body
  329. while (element && element !== referElement) {
  330. position.top += element.offsetTop
  331. position.left += element.offsetLeft
  332. element = element.offsetParent
  333. }
  334. return position
  335. }
  336. var parseInt10 = (number, defaultValue) => {
  337. if (typeof number === "number" && !Number.isNaN(number)) {
  338. return number
  339. }
  340. if (typeof defaultValue !== "number") {
  341. defaultValue = Number.NaN
  342. }
  343. if (!number) {
  344. return defaultValue
  345. }
  346. const result = Number.parseInt(number, 10)
  347. return Number.isNaN(result) ? defaultValue : result
  348. }
  349. var rootFuncArray = []
  350. var headFuncArray = []
  351. var bodyFuncArray = []
  352. var headBodyObserver
  353. var startObserveHeadBodyExists = () => {
  354. if (headBodyObserver) {
  355. return
  356. }
  357. headBodyObserver = new MutationObserver(() => {
  358. if (doc.head && doc.body) {
  359. headBodyObserver.disconnect()
  360. }
  361. if (doc.documentElement && rootFuncArray.length > 0) {
  362. for (const func of rootFuncArray) {
  363. func()
  364. }
  365. rootFuncArray.length = 0
  366. }
  367. if (doc.head && headFuncArray.length > 0) {
  368. for (const func of headFuncArray) {
  369. func()
  370. }
  371. headFuncArray.length = 0
  372. }
  373. if (doc.body && bodyFuncArray.length > 0) {
  374. for (const func of bodyFuncArray) {
  375. func()
  376. }
  377. bodyFuncArray.length = 0
  378. }
  379. })
  380. headBodyObserver.observe(doc, {
  381. childList: true,
  382. subtree: true,
  383. })
  384. }
  385. var runWhenHeadExists = (func) => {
  386. if (!doc.head) {
  387. headFuncArray.push(func)
  388. startObserveHeadBodyExists()
  389. return
  390. }
  391. func()
  392. }
  393. var runWhenDomReady = (func) => {
  394. if (doc.readyState === "interactive" || doc.readyState === "complete") {
  395. return func()
  396. }
  397. const handler = () => {
  398. if (doc.readyState === "interactive" || doc.readyState === "complete") {
  399. func()
  400. removeEventListener(doc, "readystatechange", handler)
  401. }
  402. }
  403. addEventListener(doc, "readystatechange", handler)
  404. }
  405. var isVisible = (element) => {
  406. if (typeof element.checkVisibility === "function") {
  407. return element.checkVisibility()
  408. }
  409. return element.offsetParent !== null
  410. }
  411. var isTouchScreen = () => "ontouchstart" in win
  412. var escapeHTMLPolicy =
  413. typeof trustedTypes !== "undefined" &&
  414. typeof trustedTypes.createPolicy === "function"
  415. ? trustedTypes.createPolicy("beuEscapePolicy", {
  416. createHTML: (string) => string,
  417. })
  418. : void 0
  419. var createHTML = (html) => {
  420. return escapeHTMLPolicy ? escapeHTMLPolicy.createHTML(html) : html
  421. }
  422. var addElement2 =
  423. typeof GM_addElement === "function"
  424. ? (parentNode, tagName, attributes) => {
  425. if (typeof parentNode === "string") {
  426. return addElement2(null, parentNode, tagName)
  427. }
  428. if (!tagName) {
  429. return
  430. }
  431. if (!parentNode) {
  432. parentNode = /^(script|link|style|meta)$/.test(tagName)
  433. ? getRootElement(1)
  434. : getRootElement(2)
  435. }
  436. if (typeof tagName === "string") {
  437. let attributes2
  438. if (attributes) {
  439. const entries1 = []
  440. const entries2 = []
  441. for (const entry of Object.entries(attributes)) {
  442. if (/^(on\w+|innerHTML)$/.test(entry[0])) {
  443. entries2.push(entry)
  444. } else {
  445. entries1.push(entry)
  446. }
  447. }
  448. attributes = Object.fromEntries(entries1)
  449. attributes2 = Object.fromEntries(entries2)
  450. }
  451. const element = GM_addElement(null, tagName, attributes)
  452. setAttributes(element, attributes2)
  453. parentNode.append(element)
  454. return element
  455. }
  456. setAttributes(tagName, attributes)
  457. parentNode.append(tagName)
  458. return tagName
  459. }
  460. : addElement
  461. var addStyle = (styleText) =>
  462. addElement2(null, "style", { textContent: styleText })
  463. var registerMenuCommand = (name, callback, accessKey) => {
  464. if (window !== top) {
  465. return
  466. }
  467. if (typeof GM.registerMenuCommand !== "function") {
  468. console.warn("Do not support GM.registerMenuCommand!")
  469. return
  470. }
  471. GM.registerMenuCommand(name, callback, accessKey)
  472. }
  473. var style_default =
  474. '#browser_extension_settings_container{--browser-extension-settings-background-color: #f2f2f7;--browser-extension-settings-text-color: #444444;--browser-extension-settings-link-color: #217dfc;--sb-track-color: #00000000;--sb-thumb-color: #33334480;--sb-size: 2px;--font-family: "helvetica neue", "microsoft yahei", arial, sans-serif;position:fixed;top:10px;right:30px;max-height:90%;height:600px;overflow:hidden;display:none;z-index:100000;border-radius:5px;-webkit-box-shadow:0px 10px 39px 10px rgba(62,66,66,.22);-moz-box-shadow:0px 10px 39px 10px rgba(62,66,66,.22);box-shadow:0px 10px 39px 10px rgba(62,66,66,.22) !important}#browser_extension_settings_container .browser_extension_settings_wrapper{display:flex;height:100%;overflow:hidden;background-color:var(--browser-extension-settings-background-color);font-family:var(--font-family)}#browser_extension_settings_container .browser_extension_settings_wrapper h1,#browser_extension_settings_container .browser_extension_settings_wrapper h2{border:none;color:var(--browser-extension-settings-text-color);padding:0;font-family:var(--font-family);line-height:normal;letter-spacing:normal}#browser_extension_settings_container .browser_extension_settings_wrapper h1{font-size:26px;font-weight:800;margin:18px 0}#browser_extension_settings_container .browser_extension_settings_wrapper h2{font-size:18px;font-weight:600;margin:14px 0}#browser_extension_settings_container .browser_extension_settings_wrapper footer{display:flex;justify-content:center;flex-direction:column;font-size:11px;margin:10px auto 0px;background-color:var(--browser-extension-settings-background-color);color:var(--browser-extension-settings-text-color);font-family:var(--font-family)}#browser_extension_settings_container .browser_extension_settings_wrapper footer a{color:var(--browser-extension-settings-link-color) !important;font-family:var(--font-family);text-decoration:none;padding:0}#browser_extension_settings_container .browser_extension_settings_wrapper footer p{text-align:center;padding:0;margin:2px;line-height:13px;font-size:11px;color:var(--browser-extension-settings-text-color);font-family:var(--font-family)}#browser_extension_settings_container .browser_extension_settings_wrapper a.navigation_go_previous{color:var(--browser-extension-settings-link-color);cursor:pointer;display:none}#browser_extension_settings_container .browser_extension_settings_wrapper a.navigation_go_previous::before{content:"< "}#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container{overflow-x:auto;box-sizing:border-box;padding:10px 15px;background-color:var(--browser-extension-settings-background-color);color:var(--browser-extension-settings-text-color)}#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .installed_extension_list div,#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .related_extension_list div{background-color:#fff;font-size:14px;border-top:1px solid #ccc;padding:6px 15px 6px 15px}#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .installed_extension_list div a,#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .installed_extension_list div a:visited,#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .related_extension_list div a,#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .related_extension_list div a:visited{display:flex;justify-content:space-between;align-items:center;cursor:pointer;text-decoration:none;color:var(--browser-extension-settings-text-color);font-family:var(--font-family)}#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .installed_extension_list div a:hover,#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .installed_extension_list div a:visited:hover,#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .related_extension_list div a:hover,#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .related_extension_list div a:visited:hover{text-decoration:none;color:var(--browser-extension-settings-text-color)}#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .installed_extension_list div a span,#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .installed_extension_list div a:visited span,#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .related_extension_list div a span,#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .related_extension_list div a:visited span{margin-right:10px;line-height:24px;font-family:var(--font-family)}#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .installed_extension_list div.active,#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .installed_extension_list div:hover,#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .related_extension_list div.active,#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .related_extension_list div:hover{background-color:#e4e4e6}#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .installed_extension_list div.active a,#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .related_extension_list div.active a{cursor:default}#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .installed_extension_list div:first-of-type,#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .related_extension_list div:first-of-type{border-top:none;border-top-right-radius:10px;border-top-left-radius:10px}#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .installed_extension_list div:last-of-type,#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container .related_extension_list div:last-of-type{border-bottom-right-radius:10px;border-bottom-left-radius:10px}#browser_extension_settings_container .thin_scrollbar{scrollbar-color:var(--sb-thumb-color) var(--sb-track-color);scrollbar-width:thin}#browser_extension_settings_container .thin_scrollbar::-webkit-scrollbar{width:var(--sb-size)}#browser_extension_settings_container .thin_scrollbar::-webkit-scrollbar-track{background:var(--sb-track-color);border-radius:10px}#browser_extension_settings_container .thin_scrollbar::-webkit-scrollbar-thumb{background:var(--sb-thumb-color);border-radius:10px}#browser_extension_settings_main{min-width:250px;overflow-y:auto;overflow-x:hidden;box-sizing:border-box;padding:10px 15px;background-color:var(--browser-extension-settings-background-color);color:var(--browser-extension-settings-text-color);font-family:var(--font-family)}#browser_extension_settings_main h2{text-align:center;margin:5px 0 0}#browser_extension_settings_main .option_groups{background-color:#fff;padding:6px 15px 6px 15px;border-radius:10px;display:flex;flex-direction:column;margin:10px 0 0}#browser_extension_settings_main .option_groups .action{font-size:14px;padding:6px 0 6px 0;color:var(--browser-extension-settings-link-color);cursor:pointer}#browser_extension_settings_main .bes_external_link{font-size:14px;padding:6px 0 6px 0}#browser_extension_settings_main .bes_external_link a,#browser_extension_settings_main .bes_external_link a:visited,#browser_extension_settings_main .bes_external_link a:hover{color:var(--browser-extension-settings-link-color);font-family:var(--font-family);text-decoration:none;cursor:pointer}#browser_extension_settings_main .option_groups textarea{font-size:12px;margin:10px 0 10px 0;height:100px;width:100%;border:1px solid #a9a9a9;border-radius:4px;box-sizing:border-box}#browser_extension_settings_main .switch_option,#browser_extension_settings_main .select_option{display:flex;justify-content:space-between;align-items:center;padding:6px 0 6px 0;font-size:14px}#browser_extension_settings_main .option_groups>*{border-top:1px solid #ccc}#browser_extension_settings_main .option_groups>*:first-child{border-top:none}#browser_extension_settings_main .bes_option>.bes_icon{width:24px;height:24px;margin-right:10px}#browser_extension_settings_main .bes_option>.bes_title{margin-right:10px;flex-grow:1}#browser_extension_settings_main .bes_option>.bes_select{box-sizing:border-box;background-color:#fff;height:24px;padding:0 2px 0 2px;margin:0;border-radius:6px;border:1px solid #ccc}#browser_extension_settings_main .option_groups .bes_tip{position:relative;margin:0;padding:0 15px 0 0;border:none;max-width:none;font-size:14px}#browser_extension_settings_main .option_groups .bes_tip .bes_tip_anchor{cursor:help;text-decoration:underline}#browser_extension_settings_main .option_groups .bes_tip .bes_tip_content{position:absolute;bottom:15px;left:0;background-color:#fff;color:var(--browser-extension-settings-text-color);text-align:left;padding:10px;display:none;border-radius:5px;-webkit-box-shadow:0px 10px 39px 10px rgba(62,66,66,.22);-moz-box-shadow:0px 10px 39px 10px rgba(62,66,66,.22);box-shadow:0px 10px 39px 10px rgba(62,66,66,.22) !important}#browser_extension_settings_main .option_groups .bes_tip .bes_tip_anchor:hover+.bes_tip_content,#browser_extension_settings_main .option_groups .bes_tip .bes_tip_content:hover{display:block}#browser_extension_settings_main .option_groups .bes_tip p,#browser_extension_settings_main .option_groups .bes_tip pre{margin:revert;padding:revert}#browser_extension_settings_main .option_groups .bes_tip pre{font-family:Consolas,panic sans,bitstream vera sans mono,Menlo,microsoft yahei,monospace;font-size:13px;letter-spacing:.015em;line-height:120%;white-space:pre;overflow:auto;background-color:#f5f5f5;word-break:normal;overflow-wrap:normal;padding:.5em;border:none}#browser_extension_settings_main .bes_switch_container{--button-width: 51px;--button-height: 24px;--toggle-diameter: 20px;--color-off: #e9e9eb;--color-on: #34c759;width:var(--button-width);height:var(--button-height);position:relative;padding:0;margin:0;flex:none;user-select:none}#browser_extension_settings_main input[type=checkbox]{opacity:0;width:0;height:0;position:absolute}#browser_extension_settings_main .bes_switch{width:100%;height:100%;display:block;background-color:var(--color-off);border-radius:calc(var(--button-height)/2);border:none;cursor:pointer;transition:all .2s ease-out}#browser_extension_settings_main .bes_switch::before{display:none}#browser_extension_settings_main .bes_slider{width:var(--toggle-diameter);height:var(--toggle-diameter);position:absolute;left:2px;top:calc(50% - var(--toggle-diameter)/2);border-radius:50%;background:#fff;box-shadow:0px 3px 8px rgba(0,0,0,.15),0px 3px 1px rgba(0,0,0,.06);transition:all .2s ease-out;cursor:pointer}#browser_extension_settings_main input[type=checkbox]:checked+.bes_switch{background-color:var(--color-on)}#browser_extension_settings_main input[type=checkbox]:checked+.bes_switch .bes_slider{left:calc(var(--button-width) - var(--toggle-diameter) - 2px)}#browser_extension_side_menu{min-height:80px;width:30px;opacity:0;position:fixed;top:80px;right:0;padding-top:20px;z-index:10000}#browser_extension_side_menu:hover{opacity:1}#browser_extension_side_menu button{cursor:pointer;width:24px;height:24px;padding:0;border:none;background-color:rgba(0,0,0,0);background-image:none}#browser_extension_side_menu button svg{width:24px;height:24px}#browser_extension_side_menu button:hover{opacity:70%}#browser_extension_side_menu button:active{opacity:100%}@media(max-width: 500px){#browser_extension_settings_container{right:10px}#browser_extension_settings_container .browser_extension_settings_wrapper a.navigation_go_previous{display:block}#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container{display:none}#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container.bes_active{display:block}#browser_extension_settings_container .browser_extension_settings_wrapper .extension_list_container.bes_active+div{display:none}}'
  475. function createSwitch(options = {}) {
  476. const container = createElement("label", { class: "bes_switch_container" })
  477. const checkbox = createElement(
  478. "input",
  479. options.checked ? { type: "checkbox", checked: "" } : { type: "checkbox" }
  480. )
  481. addElement2(container, checkbox)
  482. const switchElm = createElement("span", { class: "bes_switch" })
  483. addElement2(switchElm, "span", { class: "bes_slider" })
  484. addElement2(container, switchElm)
  485. if (options.onchange) {
  486. addEventListener(checkbox, "change", options.onchange)
  487. }
  488. return container
  489. }
  490. function createSwitchOption(icon, text, options) {
  491. if (typeof text !== "string") {
  492. return createSwitchOption(void 0, icon, text)
  493. }
  494. const div = createElement("div", { class: "switch_option bes_option" })
  495. if (icon) {
  496. addElement2(div, "img", { src: icon, class: "bes_icon" })
  497. }
  498. addElement2(div, "span", { textContent: text, class: "bes_title" })
  499. div.append(createSwitch(options))
  500. return div
  501. }
  502. var besVersion = 55
  503. var openButton =
  504. '<svg viewBox="0 0 60.2601318359375 84.8134765625" version="1.1" xmlns="http://www.w3.org/2000/svg" class=" glyph-box" style="height: 9.62969px; width: 6.84191px;"><g transform="matrix(1 0 0 1 -6.194965820312518 77.63671875)"><path d="M66.4551-35.2539C66.4551-36.4746 65.9668-37.5977 65.0391-38.4766L26.3672-76.3672C25.4883-77.1973 24.4141-77.6367 23.1445-77.6367C20.6543-77.6367 18.7012-75.7324 18.7012-73.1934C18.7012-71.9727 19.1895-70.8496 19.9707-70.0195L55.5176-35.2539L19.9707-0.488281C19.1895 0.341797 18.7012 1.41602 18.7012 2.68555C18.7012 5.22461 20.6543 7.12891 23.1445 7.12891C24.4141 7.12891 25.4883 6.68945 26.3672 5.81055L65.0391-32.0312C65.9668-32.959 66.4551-34.0332 66.4551-35.2539Z"></path></g></svg>'
  505. var openInNewTabButton =
  506. '<svg viewBox="0 0 72.127685546875 72.2177734375" version="1.1" xmlns="http://www.w3.org/2000/svg" class=" glyph-box" style="height: 8.19958px; width: 8.18935px;"><g transform="matrix(1 0 0 1 -12.451127929687573 71.3388671875)"><path d="M84.5703-17.334L84.5215-66.4551C84.5215-69.2383 82.7148-71.1914 79.7852-71.1914L30.6641-71.1914C27.9297-71.1914 26.0742-69.0918 26.0742-66.748C26.0742-64.4043 28.1738-62.4023 30.4688-62.4023L47.4609-62.4023L71.2891-63.1836L62.207-55.2246L13.8184-6.73828C12.9395-5.85938 12.4512-4.73633 12.4512-3.66211C12.4512-1.31836 14.5508 0.878906 16.9922 0.878906C18.1152 0.878906 19.1895 0.488281 20.0684-0.439453L68.5547-48.877L76.6113-58.0078L75.7324-35.2051L75.7324-17.1387C75.7324-14.8438 77.7344-12.6953 80.127-12.6953C82.4707-12.6953 84.5703-14.6973 84.5703-17.334Z"></path></g></svg>'
  507. var settingButton =
  508. '<svg viewBox="0 0 16 16" version="1.1">\n<path d="M8 0a8.2 8.2 0 0 1 .701.031C9.444.095 9.99.645 10.16 1.29l.288 1.107c.018.066.079.158.212.224.231.114.454.243.668.386.123.082.233.09.299.071l1.103-.303c.644-.176 1.392.021 1.82.63.27.385.506.792.704 1.218.315.675.111 1.422-.364 1.891l-.814.806c-.049.048-.098.147-.088.294.016.257.016.515 0 .772-.01.147.038.246.088.294l.814.806c.475.469.679 1.216.364 1.891a7.977 7.977 0 0 1-.704 1.217c-.428.61-1.176.807-1.82.63l-1.102-.302c-.067-.019-.177-.011-.3.071a5.909 5.909 0 0 1-.668.386c-.133.066-.194.158-.211.224l-.29 1.106c-.168.646-.715 1.196-1.458 1.26a8.006 8.006 0 0 1-1.402 0c-.743-.064-1.289-.614-1.458-1.26l-.289-1.106c-.018-.066-.079-.158-.212-.224a5.738 5.738 0 0 1-.668-.386c-.123-.082-.233-.09-.299-.071l-1.103.303c-.644.176-1.392-.021-1.82-.63a8.12 8.12 0 0 1-.704-1.218c-.315-.675-.111-1.422.363-1.891l.815-.806c.05-.048.098-.147.088-.294a6.214 6.214 0 0 1 0-.772c.01-.147-.038-.246-.088-.294l-.815-.806C.635 6.045.431 5.298.746 4.623a7.92 7.92 0 0 1 .704-1.217c.428-.61 1.176-.807 1.82-.63l1.102.302c.067.019.177.011.3-.071.214-.143.437-.272.668-.386.133-.066.194-.158.211-.224l.29-1.106C6.009.645 6.556.095 7.299.03 7.53.01 7.764 0 8 0Zm-.571 1.525c-.036.003-.108.036-.137.146l-.289 1.105c-.147.561-.549.967-.998 1.189-.173.086-.34.183-.5.29-.417.278-.97.423-1.529.27l-1.103-.303c-.109-.03-.175.016-.195.045-.22.312-.412.644-.573.99-.014.031-.021.11.059.19l.815.806c.411.406.562.957.53 1.456a4.709 4.709 0 0 0 0 .582c.032.499-.119 1.05-.53 1.456l-.815.806c-.081.08-.073.159-.059.19.162.346.353.677.573.989.02.03.085.076.195.046l1.102-.303c.56-.153 1.113-.008 1.53.27.161.107.328.204.501.29.447.222.85.629.997 1.189l.289 1.105c.029.109.101.143.137.146a6.6 6.6 0 0 0 1.142 0c.036-.003.108-.036.137-.146l.289-1.105c.147-.561.549-.967.998-1.189.173-.086.34-.183.5-.29.417-.278.97-.423 1.529-.27l1.103.303c.109.029.175-.016.195-.045.22-.313.411-.644.573-.99.014-.031.021-.11-.059-.19l-.815-.806c-.411-.406-.562-.957-.53-1.456a4.709 4.709 0 0 0 0-.582c-.032-.499.119-1.05.53-1.456l.815-.806c.081-.08.073-.159.059-.19a6.464 6.464 0 0 0-.573-.989c-.02-.03-.085-.076-.195-.046l-1.102.303c-.56.153-1.113.008-1.53-.27a4.44 4.44 0 0 0-.501-.29c-.447-.222-.85-.629-.997-1.189l-.289-1.105c-.029-.11-.101-.143-.137-.146a6.6 6.6 0 0 0-1.142 0ZM11 8a3 3 0 1 1-6 0 3 3 0 0 1 6 0ZM9.5 8a1.5 1.5 0 1 0-3.001.001A1.5 1.5 0 0 0 9.5 8Z"></path>\n</svg>'
  509. function initI18n(messageMaps, language) {
  510. language = (language || navigator.language).toLowerCase()
  511. const language2 = language.slice(0, 2)
  512. let messagesDefault
  513. let messagesLocal
  514. for (const entry of Object.entries(messageMaps)) {
  515. const langs = new Set(
  516. entry[0]
  517. .toLowerCase()
  518. .split(",")
  519. .map((v) => v.trim())
  520. )
  521. const value = entry[1]
  522. if (langs.has(language)) {
  523. messagesLocal = value
  524. }
  525. if (langs.has(language2) && !messagesLocal) {
  526. messagesLocal = value
  527. }
  528. if (langs.has("en")) {
  529. messagesDefault = value
  530. }
  531. if (langs.has("en-us") && !messagesDefault) {
  532. messagesDefault = value
  533. }
  534. }
  535. if (!messagesLocal) {
  536. messagesLocal = {}
  537. }
  538. if (!messagesDefault || messagesDefault === messagesLocal) {
  539. messagesDefault = {}
  540. }
  541. return function (key, ...parameters) {
  542. let text = messagesLocal[key] || messagesDefault[key] || key
  543. if (parameters && parameters.length > 0 && text !== key) {
  544. for (let i3 = 0; i3 < parameters.length; i3++) {
  545. text = text.replaceAll(
  546. new RegExp("\\{".concat(i3 + 1, "\\}"), "g"),
  547. String(parameters[i3])
  548. )
  549. }
  550. }
  551. return text
  552. }
  553. }
  554. var messages = {
  555. "settings.title": "Settings",
  556. "settings.otherExtensions": "Other Extensions",
  557. "settings.displaySettingsButtonInSideMenu":
  558. "Display Settings Button in Side Menu",
  559. "settings.menu.settings": "\u2699\uFE0F Settings",
  560. "settings.extensions.utags.title":
  561. "\u{1F3F7}\uFE0F UTags - Add usertags to links",
  562. "settings.extensions.links-helper.title": "\u{1F517} Links Helper",
  563. "settings.extensions.v2ex.rep.title":
  564. "V2EX.REP - \u4E13\u6CE8\u63D0\u5347 V2EX \u4E3B\u9898\u56DE\u590D\u6D4F\u89C8\u4F53\u9A8C",
  565. "settings.extensions.v2ex.min.title":
  566. "v2ex.min - V2EX Minimalist (\u6781\u7B80\u98CE\u683C)",
  567. "settings.extensions.replace-ugly-avatars.title": "Replace Ugly Avatars",
  568. "settings.extensions.more-by-pipecraft.title":
  569. "Find more useful userscripts",
  570. }
  571. var en_default = messages
  572. var messages2 = {
  573. "settings.title": "\u8BBE\u7F6E",
  574. "settings.otherExtensions": "\u5176\u4ED6\u6269\u5C55",
  575. "settings.displaySettingsButtonInSideMenu":
  576. "\u5728\u4FA7\u8FB9\u680F\u83DC\u5355\u4E2D\u663E\u793A\u8BBE\u7F6E\u6309\u94AE",
  577. "settings.menu.settings": "\u2699\uFE0F \u8BBE\u7F6E",
  578. "settings.extensions.utags.title":
  579. "\u{1F3F7}\uFE0F \u5C0F\u9C7C\u6807\u7B7E (UTags) - \u4E3A\u94FE\u63A5\u6DFB\u52A0\u7528\u6237\u6807\u7B7E",
  580. "settings.extensions.links-helper.title":
  581. "\u{1F517} \u94FE\u63A5\u52A9\u624B",
  582. "settings.extensions.v2ex.rep.title":
  583. "V2EX.REP - \u4E13\u6CE8\u63D0\u5347 V2EX \u4E3B\u9898\u56DE\u590D\u6D4F\u89C8\u4F53\u9A8C",
  584. "settings.extensions.v2ex.min.title":
  585. "v2ex.min - V2EX \u6781\u7B80\u98CE\u683C",
  586. "settings.extensions.replace-ugly-avatars.title":
  587. "\u8D50\u4F60\u4E2A\u5934\u50CF\u5427",
  588. "settings.extensions.more-by-pipecraft.title":
  589. "\u66F4\u591A\u6709\u8DA3\u7684\u811A\u672C",
  590. }
  591. var zh_cn_default = messages2
  592. var i = initI18n({
  593. "en,en-US": en_default,
  594. "zh,zh-CN": zh_cn_default,
  595. })
  596. var lang = navigator.language
  597. var locale
  598. if (lang === "zh-TW" || lang === "zh-HK") {
  599. locale = "zh-TW"
  600. } else if (lang.includes("zh")) {
  601. locale = "zh-CN"
  602. } else {
  603. locale = "en"
  604. }
  605. var relatedExtensions = [
  606. {
  607. id: "utags",
  608. title: i("settings.extensions.utags.title"),
  609. url: "https://greasyfork.org/".concat(
  610. locale,
  611. "/scripts/460718-utags-add-usertags-to-links"
  612. ),
  613. },
  614. {
  615. id: "links-helper",
  616. title: i("settings.extensions.links-helper.title"),
  617. description:
  618. "\u5728\u65B0\u6807\u7B7E\u9875\u4E2D\u6253\u5F00\u7B2C\u4E09\u65B9\u7F51\u7AD9\u94FE\u63A5\uFF0C\u56FE\u7247\u94FE\u63A5\u8F6C\u56FE\u7247\u6807\u7B7E\u7B49",
  619. url: "https://greasyfork.org/".concat(
  620. locale,
  621. "/scripts/464541-links-helper"
  622. ),
  623. },
  624. {
  625. id: "v2ex.rep",
  626. title: i("settings.extensions.v2ex.rep.title"),
  627. url: "https://greasyfork.org/".concat(
  628. locale,
  629. "/scripts/466589-v2ex-rep-%E4%B8%93%E6%B3%A8%E6%8F%90%E5%8D%87-v2ex-%E4%B8%BB%E9%A2%98%E5%9B%9E%E5%A4%8D%E6%B5%8F%E8%A7%88%E4%BD%93%E9%AA%8C"
  630. ),
  631. },
  632. {
  633. id: "v2ex.min",
  634. title: i("settings.extensions.v2ex.min.title"),
  635. url: "https://greasyfork.org/".concat(
  636. locale,
  637. "/scripts/463552-v2ex-min-v2ex-%E6%9E%81%E7%AE%80%E9%A3%8E%E6%A0%BC"
  638. ),
  639. },
  640. {
  641. id: "replace-ugly-avatars",
  642. title: i("settings.extensions.replace-ugly-avatars.title"),
  643. url: "https://greasyfork.org/".concat(
  644. locale,
  645. "/scripts/472616-replace-ugly-avatars"
  646. ),
  647. },
  648. {
  649. id: "more-by-pipecraft",
  650. title: i("settings.extensions.more-by-pipecraft.title"),
  651. url: "https://greasyfork.org/".concat(locale, "/users/1030884-pipecraft"),
  652. },
  653. ]
  654. var getInstalledExtesionList = () => {
  655. return $(".extension_list_container .installed_extension_list")
  656. }
  657. var getRelatedExtesionList = () => {
  658. return $(".extension_list_container .related_extension_list")
  659. }
  660. var isInstalledExtension = (id) => {
  661. const list = getInstalledExtesionList()
  662. if (!list) {
  663. return false
  664. }
  665. const installed = $('[data-extension-id="'.concat(id, '"]'), list)
  666. return Boolean(installed)
  667. }
  668. var addCurrentExtension = (extension) => {
  669. const list = getInstalledExtesionList()
  670. if (!list) {
  671. return
  672. }
  673. if (isInstalledExtension(extension.id)) {
  674. return
  675. }
  676. const element = createInstalledExtension(extension)
  677. list.append(element)
  678. const list2 = getRelatedExtesionList()
  679. if (list2) {
  680. updateRelatedExtensions(list2)
  681. }
  682. }
  683. var activeExtension = (id) => {
  684. const list = getInstalledExtesionList()
  685. if (!list) {
  686. return false
  687. }
  688. for (const element of $$(".active", list)) {
  689. removeClass(element, "active")
  690. }
  691. const installed = $('[data-extension-id="'.concat(id, '"]'), list)
  692. if (installed) {
  693. addClass(installed, "active")
  694. }
  695. }
  696. var activeExtensionList = () => {
  697. const extensionListContainer = $(".extension_list_container")
  698. if (extensionListContainer) {
  699. addClass(extensionListContainer, "bes_active")
  700. }
  701. }
  702. var deactiveExtensionList = () => {
  703. const extensionListContainer = $(".extension_list_container")
  704. if (extensionListContainer) {
  705. removeClass(extensionListContainer, "bes_active")
  706. }
  707. }
  708. var createInstalledExtension = (installedExtension) => {
  709. const div = createElement("div", {
  710. class: "installed_extension",
  711. "data-extension-id": installedExtension.id,
  712. })
  713. const a = addElement2(div, "a", {
  714. onclick: installedExtension.onclick,
  715. })
  716. addElement2(a, "span", {
  717. textContent: installedExtension.title,
  718. })
  719. const svg = addElement2(a, "svg")
  720. svg.outerHTML = createHTML(openButton)
  721. return div
  722. }
  723. var updateRelatedExtensions = (container) => {
  724. const relatedExtensionElements = $$("[data-extension-id]", container)
  725. if (relatedExtensionElements.length > 0) {
  726. for (const relatedExtensionElement of relatedExtensionElements) {
  727. if (
  728. isInstalledExtension(
  729. relatedExtensionElement.dataset.extensionId || "noid"
  730. )
  731. ) {
  732. relatedExtensionElement.remove()
  733. }
  734. }
  735. } else {
  736. container.innerHTML = createHTML("")
  737. }
  738. for (const relatedExtension of relatedExtensions) {
  739. if (
  740. isInstalledExtension(relatedExtension.id) ||
  741. $('[data-extension-id="'.concat(relatedExtension.id, '"]'), container)
  742. ) {
  743. continue
  744. }
  745. if ($$("[data-extension-id]", container).length >= 4) {
  746. return
  747. }
  748. const div4 = addElement2(container, "div", {
  749. class: "related_extension",
  750. "data-extension-id": relatedExtension.id,
  751. })
  752. const a = addElement2(div4, "a", {
  753. href: relatedExtension.url,
  754. target: "_blank",
  755. })
  756. addElement2(a, "span", {
  757. textContent: relatedExtension.title,
  758. })
  759. const svg = addElement2(a, "svg")
  760. svg.outerHTML = createHTML(openInNewTabButton)
  761. }
  762. }
  763. function createExtensionList(installedExtensions) {
  764. const div = createElement("div", {
  765. class: "extension_list_container thin_scrollbar",
  766. })
  767. addElement2(div, "h1", { textContent: i("settings.title") })
  768. const div2 = addElement2(div, "div", {
  769. class: "installed_extension_list",
  770. })
  771. for (const installedExtension of installedExtensions) {
  772. if (isInstalledExtension(installedExtension.id)) {
  773. continue
  774. }
  775. const element = createInstalledExtension(installedExtension)
  776. div2.append(element)
  777. }
  778. addElement2(div, "h2", { textContent: i("settings.otherExtensions") })
  779. const div3 = addElement2(div, "div", {
  780. class: "related_extension_list",
  781. })
  782. updateRelatedExtensions(div3)
  783. return div
  784. }
  785. var prefix = "browser_extension_settings_"
  786. var randomId = String(Math.round(Math.random() * 1e4))
  787. var settingsContainerId = prefix + "container_" + randomId
  788. var settingsElementId = prefix + "main_" + randomId
  789. var getSettingsElement = () => $("#" + settingsElementId)
  790. var getSettingsStyle = () =>
  791. style_default
  792. .replaceAll(/browser_extension_settings_container/gm, settingsContainerId)
  793. .replaceAll(/browser_extension_settings_main/gm, settingsElementId)
  794. var storageKey = "settings"
  795. var settingsOptions
  796. var settingsTable = {}
  797. var settings = {}
  798. async function getSettings() {
  799. var _a
  800. return (_a = await getValue(storageKey)) != null ? _a : {}
  801. }
  802. async function saveSettingsValue(key, value) {
  803. const settings2 = await getSettings()
  804. settings2[key] =
  805. settingsTable[key] && settingsTable[key].defaultValue === value
  806. ? void 0
  807. : value
  808. await setValue(storageKey, settings2)
  809. }
  810. function getSettingsValue(key) {
  811. var _a
  812. return Object.hasOwn(settings, key)
  813. ? settings[key]
  814. : (_a = settingsTable[key]) == null
  815. ? void 0
  816. : _a.defaultValue
  817. }
  818. var closeModal = () => {
  819. const settingsContainer = getSettingsContainer()
  820. if (settingsContainer) {
  821. settingsContainer.style.display = "none"
  822. }
  823. removeEventListener(document, "click", onDocumentClick, true)
  824. removeEventListener(document, "keydown", onDocumentKeyDown, true)
  825. }
  826. var onDocumentClick = (event) => {
  827. const target = event.target
  828. if (
  829. target == null ? void 0 : target.closest(".".concat(prefix, "container"))
  830. ) {
  831. return
  832. }
  833. closeModal()
  834. }
  835. var onDocumentKeyDown = (event) => {
  836. if (event.defaultPrevented) {
  837. return
  838. }
  839. if (event.key === "Escape") {
  840. closeModal()
  841. event.preventDefault()
  842. }
  843. }
  844. async function updateOptions() {
  845. if (!getSettingsElement()) {
  846. return
  847. }
  848. for (const key in settingsTable) {
  849. if (Object.hasOwn(settingsTable, key)) {
  850. const item = settingsTable[key]
  851. const type = item.type || "switch"
  852. switch (type) {
  853. case "switch": {
  854. const checkbox = $(
  855. "#"
  856. .concat(
  857. settingsElementId,
  858. ' .option_groups .switch_option[data-key="'
  859. )
  860. .concat(key, '"] input')
  861. )
  862. if (checkbox) {
  863. checkbox.checked = getSettingsValue(key)
  864. }
  865. break
  866. }
  867. case "select": {
  868. const options = $$(
  869. "#"
  870. .concat(
  871. settingsElementId,
  872. ' .option_groups .select_option[data-key="'
  873. )
  874. .concat(key, '"] .bes_select option')
  875. )
  876. for (const option of options) {
  877. option.selected = option.value === String(getSettingsValue(key))
  878. }
  879. break
  880. }
  881. case "textarea": {
  882. const textArea = $(
  883. "#"
  884. .concat(
  885. settingsElementId,
  886. ' .option_groups textarea[data-key="'
  887. )
  888. .concat(key, '"]')
  889. )
  890. if (textArea) {
  891. textArea.value = getSettingsValue(key)
  892. }
  893. break
  894. }
  895. default: {
  896. break
  897. }
  898. }
  899. }
  900. }
  901. if (typeof settingsOptions.onViewUpdate === "function") {
  902. const settingsMain = createSettingsElement()
  903. settingsOptions.onViewUpdate(settingsMain)
  904. }
  905. }
  906. function getSettingsContainer() {
  907. const container = $(".".concat(prefix, "container"))
  908. if (container) {
  909. const theVersion = parseInt10(container.dataset.besVersion, 0)
  910. if (theVersion < besVersion) {
  911. container.id = settingsContainerId
  912. container.dataset.besVersion = String(besVersion)
  913. }
  914. return container
  915. }
  916. return addElement2(doc.body, "div", {
  917. id: settingsContainerId,
  918. class: "".concat(prefix, "container"),
  919. "data-bes-version": besVersion,
  920. style: "display: none;",
  921. })
  922. }
  923. function getSettingsWrapper() {
  924. const container = getSettingsContainer()
  925. return (
  926. $(".".concat(prefix, "wrapper"), container) ||
  927. addElement2(container, "div", {
  928. class: "".concat(prefix, "wrapper"),
  929. })
  930. )
  931. }
  932. function initExtensionList() {
  933. const wrapper = getSettingsWrapper()
  934. if (!$(".extension_list_container", wrapper)) {
  935. const list = createExtensionList([])
  936. wrapper.append(list)
  937. }
  938. addCurrentExtension({
  939. id: settingsOptions.id,
  940. title: settingsOptions.title,
  941. onclick: showSettings,
  942. })
  943. }
  944. function createSettingsElement() {
  945. let settingsMain = getSettingsElement()
  946. if (!settingsMain) {
  947. const wrapper = getSettingsWrapper()
  948. for (const element of $$(".".concat(prefix, "main"))) {
  949. element.remove()
  950. }
  951. settingsMain = addElement2(wrapper, "div", {
  952. id: settingsElementId,
  953. class: "".concat(prefix, "main thin_scrollbar"),
  954. })
  955. addElement2(settingsMain, "a", {
  956. textContent: "Settings",
  957. class: "navigation_go_previous",
  958. onclick() {
  959. activeExtensionList()
  960. },
  961. })
  962. if (settingsOptions.title) {
  963. addElement2(settingsMain, "h2", { textContent: settingsOptions.title })
  964. }
  965. const optionGroups = []
  966. const getOptionGroup = (index) => {
  967. if (index > optionGroups.length) {
  968. for (let i3 = optionGroups.length; i3 < index; i3++) {
  969. optionGroups.push(
  970. addElement2(settingsMain, "div", {
  971. class: "option_groups",
  972. })
  973. )
  974. }
  975. }
  976. return optionGroups[index - 1]
  977. }
  978. for (const key in settingsTable) {
  979. if (Object.hasOwn(settingsTable, key)) {
  980. const item = settingsTable[key]
  981. const type = item.type || "switch"
  982. const group = item.group || 1
  983. const optionGroup = getOptionGroup(group)
  984. switch (type) {
  985. case "switch": {
  986. const switchOption = createSwitchOption(item.icon, item.title, {
  987. async onchange(event) {
  988. const checkbox = event.target
  989. if (checkbox) {
  990. let result = true
  991. if (typeof item.onConfirmChange === "function") {
  992. result = item.onConfirmChange(checkbox.checked)
  993. }
  994. if (result) {
  995. await saveSettingsValue(key, checkbox.checked)
  996. } else {
  997. checkbox.checked = !checkbox.checked
  998. }
  999. }
  1000. },
  1001. })
  1002. switchOption.dataset.key = key
  1003. addElement2(optionGroup, switchOption)
  1004. break
  1005. }
  1006. case "textarea": {
  1007. let timeoutId
  1008. const div = addElement2(optionGroup, "div", {
  1009. class: "bes_textarea",
  1010. })
  1011. addElement2(div, "textarea", {
  1012. "data-key": key,
  1013. placeholder: item.placeholder || "",
  1014. onkeyup(event) {
  1015. const textArea = event.target
  1016. if (timeoutId) {
  1017. clearTimeout(timeoutId)
  1018. timeoutId = void 0
  1019. }
  1020. timeoutId = setTimeout(async () => {
  1021. if (textArea) {
  1022. await saveSettingsValue(key, textArea.value.trim())
  1023. }
  1024. }, 100)
  1025. },
  1026. })
  1027. break
  1028. }
  1029. case "action": {
  1030. addElement2(optionGroup, "a", {
  1031. class: "action",
  1032. textContent: item.title,
  1033. onclick: item.onclick,
  1034. })
  1035. break
  1036. }
  1037. case "externalLink": {
  1038. const div4 = addElement2(optionGroup, "div", {
  1039. class: "bes_external_link",
  1040. })
  1041. addElement2(div4, "a", {
  1042. textContent: item.title,
  1043. href: item.url,
  1044. target: "_blank",
  1045. })
  1046. break
  1047. }
  1048. case "select": {
  1049. const div = addElement2(optionGroup, "div", {
  1050. class: "select_option bes_option",
  1051. "data-key": key,
  1052. })
  1053. if (item.icon) {
  1054. addElement2(div, "img", { src: item.icon, class: "bes_icon" })
  1055. }
  1056. addElement2(div, "span", {
  1057. textContent: item.title,
  1058. class: "bes_title",
  1059. })
  1060. const select = addElement2(div, "select", {
  1061. class: "bes_select",
  1062. async onchange() {
  1063. await saveSettingsValue(key, select.value)
  1064. },
  1065. })
  1066. for (const option of Object.entries(item.options)) {
  1067. addElement2(select, "option", {
  1068. textContent: option[0],
  1069. value: option[1],
  1070. })
  1071. }
  1072. break
  1073. }
  1074. case "tip": {
  1075. const tip = addElement2(optionGroup, "div", {
  1076. class: "bes_tip",
  1077. })
  1078. addElement2(tip, "a", {
  1079. class: "bes_tip_anchor",
  1080. textContent: item.title,
  1081. })
  1082. const tipContent = addElement2(tip, "div", {
  1083. class: "bes_tip_content",
  1084. innerHTML: createHTML(item.tipContent),
  1085. })
  1086. break
  1087. }
  1088. }
  1089. }
  1090. }
  1091. if (settingsOptions.footer) {
  1092. const footer = addElement2(settingsMain, "footer")
  1093. footer.innerHTML = createHTML(
  1094. typeof settingsOptions.footer === "string"
  1095. ? settingsOptions.footer
  1096. : '<p>Made with \u2764\uFE0F by\n <a href="https://www.pipecraft.net/" target="_blank">\n Pipecraft\n </a></p>'
  1097. )
  1098. }
  1099. }
  1100. return settingsMain
  1101. }
  1102. function addSideMenu() {
  1103. if (!getSettingsValue("displaySettingsButtonInSideMenu")) {
  1104. return
  1105. }
  1106. const menu =
  1107. $("#browser_extension_side_menu") ||
  1108. addElement2(doc.body, "div", {
  1109. id: "browser_extension_side_menu",
  1110. "data-bes-version": besVersion,
  1111. })
  1112. const button = $("button[data-bes-version]", menu)
  1113. if (button) {
  1114. const theVersion = parseInt10(button.dataset.besVersion, 0)
  1115. if (theVersion >= besVersion) {
  1116. return
  1117. }
  1118. button.remove()
  1119. }
  1120. addElement2(menu, "button", {
  1121. type: "button",
  1122. "data-bes-version": besVersion,
  1123. title: i("settings.menu.settings"),
  1124. onclick() {
  1125. setTimeout(showSettings, 1)
  1126. },
  1127. innerHTML: settingButton,
  1128. })
  1129. }
  1130. function addCommonSettings(settingsTable3) {
  1131. let maxGroup = 0
  1132. for (const key in settingsTable3) {
  1133. if (Object.hasOwn(settingsTable3, key)) {
  1134. const item = settingsTable3[key]
  1135. const group = item.group || 1
  1136. if (group > maxGroup) {
  1137. maxGroup = group
  1138. }
  1139. }
  1140. }
  1141. settingsTable3.displaySettingsButtonInSideMenu = {
  1142. title: i("settings.displaySettingsButtonInSideMenu"),
  1143. defaultValue: !(
  1144. typeof GM === "object" && typeof GM.registerMenuCommand === "function"
  1145. ),
  1146. group: maxGroup + 1,
  1147. }
  1148. }
  1149. function handleShowSettingsUrl() {
  1150. if (location.hash === "#bes-show-settings") {
  1151. setTimeout(showSettings, 100)
  1152. }
  1153. }
  1154. async function showSettings() {
  1155. const settingsContainer = getSettingsContainer()
  1156. const settingsMain = createSettingsElement()
  1157. await updateOptions()
  1158. settingsContainer.style.display = "block"
  1159. addEventListener(document, "click", onDocumentClick, true)
  1160. addEventListener(document, "keydown", onDocumentKeyDown, true)
  1161. activeExtension(settingsOptions.id)
  1162. deactiveExtensionList()
  1163. }
  1164. var initSettings = async (options) => {
  1165. settingsOptions = options
  1166. settingsTable = options.settingsTable || {}
  1167. addCommonSettings(settingsTable)
  1168. addValueChangeListener(storageKey, async () => {
  1169. settings = await getSettings()
  1170. await updateOptions()
  1171. addSideMenu()
  1172. if (typeof options.onValueChange === "function") {
  1173. options.onValueChange()
  1174. }
  1175. })
  1176. settings = await getSettings()
  1177. runWhenHeadExists(() => {
  1178. addStyle(getSettingsStyle())
  1179. })
  1180. runWhenDomReady(() => {
  1181. initExtensionList()
  1182. addSideMenu()
  1183. })
  1184. registerMenuCommand(i("settings.menu.settings"), showSettings, "o")
  1185. handleShowSettingsUrl()
  1186. }
  1187. var content_default =
  1188. '\uFEFF#TOFIX_uFEFF{display:block}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_key]{display:none !important}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity)[data-utags=off] .utags_ul{display:none !important}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul{box-sizing:border-box !important;display:inline-flex !important;flex-direction:row !important;flex-wrap:wrap !important;align-content:flex-start;justify-content:flex-start;overflow:visible;white-space:normal;list-style-type:none !important;margin:0 !important;padding:0 !important;vertical-align:text-bottom !important;line-height:normal !important;background-color:rgba(0,0,0,0);border:none !important;box-shadow:none !important;max-width:100% !important}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul>li{box-sizing:border-box !important;display:inline-flex !important;align-items:center !important;float:none !important;overflow:visible;width:unset !important;height:unset !important;border:none !important;padding:0 !important;margin:0 !important;vertical-align:top !important}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul>li:first-child .utags_text_tag{margin-left:3px !important}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul>li:last-child .utags_text_tag{margin-right:3px !important}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul>li::before,:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul>li::after{content:none}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul .utags_text_tag{box-sizing:border-box !important;display:block !important;border:var(--utags-text-tag-border-width) solid var(--utags-text-tag-border-color);color:var(--utags-text-tag-color) !important;border-radius:3px !important;padding:1px 3px !important;margin:0 1px !important;font-size:var(--utags-text-tag-font-size) !important;font-family:var(--utags-text-tag-font-family) !important;letter-spacing:0 !important;line-height:1 !important;height:unset !important;width:unset !important;font-weight:normal !important;text-decoration:none !important;text-align:center !important;text-shadow:none !important;min-width:unset !important;min-height:unset !important;max-width:unset !important;max-height:unset !important;background:unset !important;background-color:var(--utags-text-tag-background-color) !important;cursor:pointer;z-index:0;pointer-events:auto}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul .utags_text_tag:link{cursor:pointer}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul .utags_text_tag[data-utags_tag]::before{content:attr(data-utags_tag);display:block;font-size:var(--utags-text-tag-font-size);line-height:1;height:unset;width:unset;max-width:var(--utags-text-tag-max-width);white-space:var(--utags-text-tag-white-space);overflow:hidden;text-overflow:ellipsis;border-radius:unset;border:unset;background:unset;margin:unset;padding:unset}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul .utags_text_tag[data-utags_tag=":visited"]{height:var(--utags-visited-tag-size) !important;width:var(--utags-visited-tag-size) !important;border-radius:var(--utags-visited-tag-size) !important;--utags-text-tag-background-color: var( --utags-visited-tag-background-color );--utags-text-tag-border-color: var(--utags-visited-tag-background-color);--utags-text-tag-border-width: 0px;margin-left:2px !important}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul .utags_text_tag[data-utags_tag=":visited"]::before{display:none}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul .utags_emoji_tag{--utags-text-tag-background-color: var( --utags-emoji-tag-background-color );--utags-text-tag-font-size: var(--utags-emoji-tag-font-size);--utags-text-tag-font-family: var(--utags-emoji-tag-font-family);--utags-text-tag-border-width: var(--utags-emoji-tag-border-width);--utags-text-tag-border-color: var(--utags-emoji-tag-border-color)}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul .utags_captain_tag,:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul .utags_captain_tag2{width:var(--utags-captain-tag-size) !important;height:var(--utags-captain-tag-size) !important;padding:1px 0 0 1px !important;background:none !important;color:var(--utags-captain-tag-color) !important;border:none !important}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul .utags_captain_tag::before,:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul .utags_captain_tag2::before{content:none !important}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul .utags_captain_tag svg,:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul .utags_captain_tag2 svg{fill:currentColor !important;vertical-align:-3px}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul .utags_captain_tag *,:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul .utags_captain_tag2 *{color:inherit !important;fill:currentColor !important;width:unset;height:unset}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul .utags_captain_tag{opacity:1%;position:absolute;top:var(--utags-notag-captain-tag-top, 0);left:var(--utags-notag-captain-tag-left, 0);padding:0 !important;margin:0 !important;width:4px !important;height:4px !important;font-size:1px !important;background-color:var(--utags-captain-tag-background-color) !important;transition:all 0s .3s !important}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul .utags_captain_tag:hover,:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul .utags_captain_tag:focus,:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul .utags_captain_tag2:hover,:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul .utags_captain_tag2:focus{color:var(--utags-captain-tag-hover-color) !important}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul.utags_ul_0{margin:0 !important;display:var(--utags-notag-ul-disply, inline) !important;float:var(--utags-notag-ul-float, none);height:var(--utags-notag-ul-height, unset);width:var(--utags-notag-ul-width, unset) !important;position:var(--utags-notag-ul-position, unset);top:var(--utags-notag-ul-top, unset)}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul.utags_ul_0>li{position:relative !important;height:var(--utags-captain-tag-size) !important}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_captain_tag:focus,:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) *:hover+.utags_ul .utags_captain_tag,:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_fit_content]:hover .utags_ul .utags_captain_tag,:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_ul:hover .utags_captain_tag,:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_show_all .utags_captain_tag,:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) :not(a):not([data-utags_node_type=link])+.utags_ul .utags_captain_tag{opacity:100%;width:calc(var(--utags-captain-tag-size) + 8px) !important;height:calc(var(--utags-captain-tag-size) + 8px) !important;padding:5px 4px 4px 5px !important;transition:all 0s .1s !important;z-index:90}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_hide_all .utags_captain_tag,:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_show_all .utags_captain_tag{transition:unset !important}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_modal{position:fixed;top:0;left:0;height:0;width:0;z-index:200000}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_modal .utags_modal_wrapper{position:fixed;display:flex;align-items:flex-start;justify-content:center;width:100%;inset:0px;padding-top:5vh;background-color:rgba(255,255,255,.1);z-index:200000}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_modal .utags_modal_content{box-sizing:border-box;display:flex;flex-direction:column;max-width:94%;max-height:100%;overflow:hidden;overflow:auto;color:#000;background-color:#fff;border-radius:5px;padding:14px;margin:0 auto;-webkit-box-shadow:0px 10px 39px 10px rgba(62,66,66,.22);-moz-box-shadow:0px 10px 39px 10px rgba(62,66,66,.22);box-shadow:0px 10px 39px 10px rgba(62,66,66,.22)}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_modal .utags_title{display:block;color:#000;margin-bottom:10px;font-size:14px}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_modal .utags_buttons_wrapper{display:flex;flex-direction:row;justify-content:end;padding:10px 0 10px 0}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_modal .utags_buttons_wrapper button{font-size:14px;height:32px;min-width:80px;font-weight:600;padding:0 8px;border-radius:2px;color:var(--utags-button-text-color);border:1px solid var(--utags-button-border-color);background-color:var(--utags-button-bg-color);text-shadow:none;text-align:center;font-family:revert}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_modal .utags_buttons_wrapper button:hover{background-color:var(--utags-button-hover-bg-color);border-color:var(--utags-button-hover-border-color)}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_modal .utags_buttons_wrapper button:not(:first-child){margin-left:10px}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_modal .utags_buttons_wrapper button.utags_primary{--utags-button-text-color: var(--utags-action-button-text-color);--utags-button-bg-color: var(--utags-action-button-bg-color);--utags-button-border-color: var(--utags-action-button-border-color);--utags-button-hover-bg-color: var( --utags-action-button-hover-bg-color );--utags-button-hover-border-color: var( --utags-action-button-hover-border-color )}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_modal .utags_prompt input{-webkit-appearance:none;background-color:var(--utags-button-hover-bg-color);border:none;border-bottom:2px solid var(--utags-button-hover-bg-color);border-radius:4px;box-sizing:border-box;caret-color:var(--cr-input-focus-color);color:var(--cr-input-color);font-family:var(--utags-text-tag-font-family) !important;font-weight:inherit;line-height:inherit;min-height:var(--cr-input-min-height, auto);outline:0;padding-bottom:var(--cr-input-padding-bottom, 6px);padding-inline-end:var(--cr-input-padding-end, 8px);padding-inline-start:var(--cr-input-padding-start, 8px);padding-top:var(--cr-input-padding-top, 6px);text-align:left;text-overflow:ellipsis;width:100%;margin:0;font-size:12px}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_modal .utags_prompt input:focus,:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_modal .utags_prompt input:focus-visible{outline:0;border-bottom:2px solid var(--utags-action-button-hover-border-color)}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_modal .utags_prompt .utags_link_settings{font-size:12px;text-decoration:underline;cursor:pointer;color:#374151}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_current_tags_wrapper{display:flex;justify-content:space-between}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_current_tags_wrapper .utags_button_copy{cursor:pointer;font-size:10px;line-height:1;height:18px;padding:0 6px;border-radius:2px;color:var(--utags-action-button-text-color);background-color:var(--utags-action-button-bg-color);border:1px solid var(--utags-action-button-border-color);text-shadow:none;text-align:center;font-family:revert}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) ul.utags_current_tags{list-style-type:none;margin:0;padding:0 0 10px 0 !important;display:flex !important;flex-direction:row;flex-wrap:wrap}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) ul.utags_current_tags:empty,:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) ul.utags_current_tags:empty+button{display:none !important}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) ul.utags_current_tags li .utags_text_tag:hover{--utags-text-tag-color: #000;--utags-text-tag-border-color: #000;--utags-text-tag-background-color: unset;opacity:.5;text-decoration:line-through !important}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) ul.utags_current_tags li .utags_text_tag[data-utags_tag=":visited"]:hover{--utags-text-tag-background-color: var( --utags-visited-tag-background-color );--utags-text-tag-border-color: var(--utags-visited-tag-background-color);opacity:.3}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) .utags_list_wrapper{display:flex;justify-content:space-between;max-height:200px;overflow-y:auto}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) ul.utags_select_list{flex-grow:1;list-style-type:none;margin:0;padding:10px 0 10px 0}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) ul.utags_select_list:empty{display:none !important}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) ul.utags_select_list:not(:first-child){margin-left:4px}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) ul.utags_select_list::before{content:attr(data-utags_list_name);position:sticky;top:0;display:block;font-size:12px;font-weight:600;text-align:left;padding:0 2px 0 8px;cursor:default;background-color:#f8fafe}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) ul.utags_select_list li{box-sizing:border-box;cursor:pointer;font-size:12px;height:16px;display:flex;align-items:center;padding:0 2px 0 8px;margin:0;max-width:150px;overflow:hidden;text-overflow:ellipsis}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) ul.utags_select_list li.utags_active,:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) ul.utags_select_list li.utags_active2{background-color:#fef2f2}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) ul.utags_select_list li span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:var(--utags-text-tag-font-family) !important;font-size:12px;line-height:1}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) textarea[data-key=customStyleValue]{height:250px}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) textarea[data-key^=customStyleValue_]{height:250px}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",\u6807\u9898\u515A,"],:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",\u63A8\u5E7F,"],:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",\u65E0\u804A,"],:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",\u5FFD\u7565,"],:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",ignore,"],:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",clickbait,"],:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",promotion,"],:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",sb,"]{opacity:10%}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",\u5DF2\u9605,"],:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",\u5DF2\u8BFB,"],:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",\u65B0\u7528\u6237,"]{opacity:50%}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",hide,"],:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",\u9690\u85CF,"],:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",\u5C4F\u853D,"],:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",\u4E0D\u518D\u663E\u793A,"],:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",block,"]{opacity:5%;display:none}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",\u70ED\u95E8,"],:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",\u6536\u85CF,"],:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",\u91CD\u8981,"],:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",\u5173\u6CE8,"],:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",\u7A0D\u540E\u9605\u8BFB,"]{background-image:linear-gradient(to right, rgba(255, 255, 255, 0), #fefce8) !important;opacity:100% !important;display:var(--utags-list-node-display) !important}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",\u70ED\u95E8,"],:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",\u6536\u85CF,"],:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",\u91CD\u8981,"],:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node*=",\u5173\u6CE8,"]{background-image:linear-gradient(to right, rgba(255, 255, 255, 0), #fef2f2) !important}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_list_node]:hover{opacity:100% !important}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_other="1"]+ul.utags_ul .utags_captain_tag,:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) [data-utags_other="1"]+ul.utags_ul .utags_captain_tag2{color:#ff0 !important}[data-utags_display-effect-of-the-visited-content="4"] [data-utags_list_node*=",:visited,"] [data-utags_condition_node][data-utags_visited="1"]{color:var(--utags-visited-title-color)}[data-utags_display-effect-of-the-visited-content="2"] [data-utags_list_node*=",:visited,"]{opacity:var(--utags-visited-opacity)}[data-utags_display-effect-of-the-visited-content="3"] [data-utags_list_node*=",:visited,"]{opacity:5%;display:none}.utags_no_hide [data-utags_list_node*=","]{display:var(--utags-list-node-display) !important}.utags_no_opacity_effect [data-utags_list_node*=","]{opacity:100% !important}textarea[data-key=emojiTags]{font-family:var(--utags-text-tag-font-family)}:root{--utags-list-node-display: block;--utags-captain-tag-background-color: #ffffffb3;--utags-captain-tag-background-color-overlap: #ffffffdd;--utags-captain-tag-color: #ff6361;--utags-captain-tag-hover-color: #256cf1;--utags-captain-tag-size: 14px;--utags-text-tag-color: red;--utags-text-tag-border-color: red;--utags-text-tag-background-color: unset;--utags-text-tag-font-size: 10px;--utags-text-tag-border-width: 1px;--utags-text-tag-max-width: 90px;--utags-text-tag-white-space: nowrap;--utags-text-tag-font-family: "helvetica neue", "Helvetica", "microsoft yahei", "Arial", "sans-serif", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "noto color emoji", "android emoji", "emojisymbols", "emojione mozilla", "twemoji mozilla", "Segoe UI", "Noto Sans";--utags-emoji-tag-border-color: #fff0;--utags-emoji-tag-background-color: #fff0;--utags-emoji-tag-font-size: 12px;--utags-emoji-tag-border-width: 0;--utags-emoji-tag-font-family: "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "noto color emoji", "android emoji", "emojisymbols", "emojione mozilla", "twemoji mozilla", "Segoe UI", "Noto Sans";--utags-visited-tag-background-color: #bdbdbd;--utags-visited-tag-size: 11px;--utags-visited-title-color: #aaa;--utags-visited-opacity: 10%;--utags-button-text-color: #1a73e8;--utags-button-bg-color: #ffffff;--utags-button-border-color: #dadce0;--utags-button-hover-bg-color: #4285f40a;--utags-button-hover-border-color: #d2e3fc;--utags-action-button-text-color: #ffffff;--utags-action-button-bg-color: #1a73e8;--utags-action-button-border-color: #1a73e8;--utags-action-button-hover-bg-color: #1a73e8e6;--utags-action-button-hover-border-color: #1a73e8e6;--utags-notag-ul-disply-1: inline;--utags-notag-ul-float-1: none;--utags-notag-ul-height-1: unset;--utags-notag-ul-width-1: unset;--utags-notag-ul-position-1: unset;--utags-notag-ul-top-1: unset;--utags-notag-captain-tag-top-1: 0;--utags-notag-captain-tag-left-1: 0;--utags-notag-ul-disply-2: block;--utags-notag-ul-height-2: 0;--utags-notag-ul-width-2: 0;--utags-notag-ul-position-2: unset;--utags-notag-ul-top-2: unset;--utags-notag-captain-tag-top-2: -22px;--utags-notag-captain-tag-left-2: -4px;--utags-notag-ul-disply-3: block;--utags-notag-ul-height-3: 0;--utags-notag-ul-width-3: 0;--utags-notag-ul-position-3: absolute;--utags-notag-ul-top-3: 0;--utags-notag-captain-tag-top-3: 0;--utags-notag-captain-tag-left-3: -4px;--utags-notag-ul-disply-4: block;--utags-notag-ul-height-4: 0;--utags-notag-ul-width-4: 0;--utags-notag-ul-position-4: absolute;--utags-notag-ul-top-4: unset;--utags-notag-captain-tag-top-4: 0;--utags-notag-captain-tag-left-4: -4px;--utags-notag-ul-disply-5: block;--utags-notag-ul-height-5: 0;--utags-notag-ul-width-5: 0;--utags-notag-ul-position-5: absolute;--utags-notag-ul-top-5: -9999px;--utags-notag-captain-tag-top-5: 0;--utags-notag-captain-tag-left-5: -4px;--utags-notag-ul-disply: var(--utags-notag-ul-disply-1);--utags-notag-ul-float: var(--utags-notag-ul-float-1);--utags-notag-ul-height: var(--utags-notag-ul-height-1);--utags-notag-ul-width: var(--utags-notag-ul-width-1);--utags-notag-ul-position: var(--utags-notag-ul-position-1);--utags-notag-ul-top: var(--utags-notag-ul-top-1);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-1);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-1)}[data-utags_darkmode="1"]{--utags-visited-title-color: #666}'
  1189. function createTag(tagName, options) {
  1190. const a = createElement("a", {
  1191. title: tagName,
  1192. class: options.isEmoji
  1193. ? "utags_text_tag utags_emoji_tag"
  1194. : "utags_text_tag",
  1195. })
  1196. if (options.enableSelect) {
  1197. a.textContent = tagName
  1198. } else {
  1199. a.dataset.utags_tag = tagName
  1200. }
  1201. if (!options.noLink) {
  1202. a.setAttribute(
  1203. "href",
  1204. "https://utags.pipecraft.net/tags/#" + encodeURIComponent(tagName)
  1205. )
  1206. a.setAttribute("target", "_blank")
  1207. }
  1208. return a
  1209. }
  1210. var messages3 = {
  1211. "settings.enableCurrentSite": "Enable UTags on the current website",
  1212. "settings.showHidedItems": "Show hidden items (tags with 'block', 'hide')",
  1213. "settings.noOpacityEffect":
  1214. "No opacity mask effect (tags with 'ignore', 'clickbait', 'promotion')",
  1215. "settings.useVisitedFunction":
  1216. "Enable browsing content tagging on the current website",
  1217. "settings.displayEffectOfTheVisitedContent":
  1218. "The display effect of the browsed content",
  1219. "settings.displayEffectOfTheVisitedContent.recordingonly":
  1220. "Save records only, no mark display",
  1221. "settings.displayEffectOfTheVisitedContent.showtagonly":
  1222. "Only display marks",
  1223. "settings.displayEffectOfTheVisitedContent.changecolor":
  1224. "Change the title color",
  1225. "settings.displayEffectOfTheVisitedContent.translucent": "Translucent",
  1226. "settings.displayEffectOfTheVisitedContent.hide": "Hide",
  1227. "settings.pinnedTags": "Add the tags you want to pin, separated by commas.",
  1228. "settings.pinnedTagsDefaultValue":
  1229. "block, hide, ignore, clickbait, promotion",
  1230. "settings.pinnedTagsPlaceholder": "foo, bar",
  1231. "settings.emojiTags": "Add the emoji tags, separated by commas",
  1232. "settings.customStyle": "Enable custom style for all websites",
  1233. "settings.customStyleCurrentSite":
  1234. "Enable custom style for the current website",
  1235. "settings.customStyleDefaultValue":
  1236. "/* Custom style */\nbody {\n /* Tag text color */\n --utags-text-tag-color: white;\n /* Tag border color */\n --utags-text-tag-border-color: red;\n /* Tag background color */\n --utags-text-tag-background-color: red;\n}\n\n/* The tag style for the tag with the label 'TEST' */\n.utags_text_tag[data-utags_tag=\"TEST\"] {\n /* Tag text color */\n --utags-text-tag-color: white;\n /* Tag border color */\n --utags-text-tag-border-color: orange;\n /* Tag background color */\n --utags-text-tag-background-color: orange;\n}",
  1237. "settings.customStyleExamples": "Examples",
  1238. "settings.customStyleExamplesContent":
  1239. '<p>Custom style examples</p>\n <p>\n <pre>/* Custom style */\nbody {\n /* Tag text color */\n --utags-text-tag-color: white;\n /* Tag border color */\n --utags-text-tag-border-color: red;\n /* Tag background color */\n --utags-text-tag-background-color: red;\n}\n\n/* The tag style for the tag with the label \'TEST\' */\n.utags_text_tag[data-utags_tag="TEST"] {\n /* Tag text color */\n --utags-text-tag-color: white;\n /* Tag border color */\n --utags-text-tag-border-color: orange;\n /* Tag background color */\n --utags-text-tag-background-color: orange;\n}\n\ndata-utags_list_node*=",bar,"] {\n /* The background color of the entries\n in the list that contain the \'bar\' tag */\n background-color: aqua;\n}\n\nbody {\n /* The title color of viewed posts */\n --utags-visited-title-color: red;\n}\n\n/* Dark mode */\n[data-utags_darkmode="1"] body {\n /* The title color of viewed posts */\n --utags-visited-title-color: yellow;\n}\n</pre>\n </p>\n <p><a href="https://github.com/utags/utags/tree/main/custom-style-examples">More examples</a></p>\n ',
  1240. "settings.useSimplePrompt": "Use simple prompt method to add tags",
  1241. "settings.openTagsPage": "Open the tag list page",
  1242. "settings.openDataPage": "Open the import data/export data page",
  1243. "settings.title": "\u{1F3F7}\uFE0F UTags - Add usertags to links",
  1244. "settings.information":
  1245. "After changing the settings, reload the page to take effect",
  1246. "settings.report": "Report and Issue...",
  1247. "prompt.addTags":
  1248. "[UTags] Please enter tags, multiple tags are separated by commas",
  1249. "prompt.pinnedTags": "Pinned",
  1250. "prompt.mostUsedTags": "Recently commonly used",
  1251. "prompt.recentAddedTags": "Newly added",
  1252. "prompt.emojiTags": "Emoji",
  1253. "prompt.copy": "Copy",
  1254. "prompt.cancel": "Cancle",
  1255. "prompt.ok": "OK",
  1256. "prompt.settings": "Settings",
  1257. }
  1258. var en_default2 = messages3
  1259. var messages4 = {
  1260. "settings.enableCurrentSite":
  1261. "\u5728\u5F53\u524D\u7F51\u7AD9\u542F\u7528\u5C0F\u9C7C\u6807\u7B7E",
  1262. "settings.showHidedItems":
  1263. "\u663E\u793A\u88AB\u9690\u85CF\u7684\u5185\u5BB9 (\u6DFB\u52A0\u4E86 'block', 'hide', '\u9690\u85CF'\u7B49\u6807\u7B7E\u7684\u5185\u5BB9)",
  1264. "settings.noOpacityEffect":
  1265. "\u53BB\u9664\u534A\u900F\u660E\u6548\u679C (\u6DFB\u52A0\u4E86 'sb', '\u5FFD\u7565', '\u6807\u9898\u515A'\u7B49\u6807\u7B7E\u7684\u5185\u5BB9)",
  1266. "settings.useVisitedFunction":
  1267. "\u5728\u5F53\u524D\u7F51\u7AD9\u542F\u7528\u6D4F\u89C8\u5185\u5BB9\u6807\u8BB0\u529F\u80FD",
  1268. "settings.displayEffectOfTheVisitedContent":
  1269. "\u5F53\u524D\u7F51\u7AD9\u7684\u5DF2\u6D4F\u89C8\u5185\u5BB9\u7684\u5C55\u793A\u6548\u679C",
  1270. "settings.displayEffectOfTheVisitedContent.recordingonly":
  1271. "\u53EA\u4FDD\u5B58\u8BB0\u5F55\uFF0C\u4E0D\u663E\u793A\u6807\u8BB0",
  1272. "settings.displayEffectOfTheVisitedContent.showtagonly":
  1273. "\u53EA\u663E\u793A\u6807\u8BB0",
  1274. "settings.displayEffectOfTheVisitedContent.changecolor":
  1275. "\u66F4\u6539\u6807\u9898\u989C\u8272",
  1276. "settings.displayEffectOfTheVisitedContent.translucent":
  1277. "\u534A\u900F\u660E",
  1278. "settings.displayEffectOfTheVisitedContent.hide": "\u9690\u85CF",
  1279. "settings.pinnedTags":
  1280. "\u5728\u4E0B\u9762\u6DFB\u52A0\u8981\u7F6E\u9876\u7684\u6807\u7B7E\uFF0C\u4EE5\u9017\u53F7\u5206\u9694",
  1281. "settings.pinnedTagsDefaultValue":
  1282. "\u6536\u85CF, block, sb, \u5C4F\u853D, \u9690\u85CF, \u5DF2\u9605, \u5FFD\u7565, \u6807\u9898\u515A, \u63A8\u5E7F, \u5173\u6CE8",
  1283. "settings.pinnedTagsPlaceholder": "foo, bar",
  1284. "settings.emojiTags":
  1285. "\u5728\u4E0B\u9762\u6DFB\u52A0\u8868\u60C5\u7B26\u53F7\u6807\u7B7E\uFF0C\u4EE5\u9017\u53F7\u5206\u9694",
  1286. "settings.customStyle":
  1287. "\u542F\u7528\u5168\u5C40\u81EA\u5B9A\u4E49\u6837\u5F0F",
  1288. "settings.customStyleCurrentSite":
  1289. "\u542F\u7528\u5F53\u524D\u7F51\u7AD9\u7684\u81EA\u5B9A\u4E49\u6837\u5F0F",
  1290. "settings.customStyleDefaultValue":
  1291. "/* \u81EA\u5B9A\u4E49\u6837\u5F0F */\nbody {\n /* \u6807\u7B7E\u6587\u5B57\u989C\u8272 */\n --utags-text-tag-color: white;\n /* \u6807\u7B7E\u8FB9\u6846\u989C\u8272 */\n --utags-text-tag-border-color: red;\n /* \u6807\u7B7E\u80CC\u666F\u989C\u8272 */\n --utags-text-tag-background-color: red;\n}\n\n/* \u6807\u7B7E\u4E3A 'TEST' \u7684\u6807\u7B7E\u6837\u5F0F */\n.utags_text_tag[data-utags_tag=\"TEST\"] {\n /* \u6807\u7B7E\u6587\u5B57\u989C\u8272 */\n --utags-text-tag-color: white;\n /* \u6807\u7B7E\u8FB9\u6846\u989C\u8272 */\n --utags-text-tag-border-color: orange;\n /* \u6807\u7B7E\u80CC\u666F\u989C\u8272 */\n --utags-text-tag-background-color: orange;\n}",
  1292. "settings.customStyleExamples": "\u793A\u4F8B",
  1293. "settings.customStyleExamplesContent":
  1294. '<p>\u81EA\u5B9A\u4E49\u6837\u5F0F\u793A\u4F8B</p>\n <p>\n <pre>/* \u81EA\u5B9A\u4E49\u6837\u5F0F */\nbody {\n /* \u6807\u7B7E\u6587\u5B57\u989C\u8272 */\n --utags-text-tag-color: white;\n /* \u6807\u7B7E\u8FB9\u6846\u989C\u8272 */\n --utags-text-tag-border-color: red;\n /* \u6807\u7B7E\u80CC\u666F\u989C\u8272 */\n --utags-text-tag-background-color: red;\n}\n\n/* \u6807\u7B7E\u4E3A \'TEST\' \u7684\u6807\u7B7E\u6837\u5F0F */\n.utags_text_tag[data-utags_tag="TEST"] {\n /* \u6807\u7B7E\u6587\u5B57\u989C\u8272 */\n --utags-text-tag-color: white;\n /* \u6807\u7B7E\u8FB9\u6846\u989C\u8272 */\n --utags-text-tag-border-color: orange;\n /* \u6807\u7B7E\u80CC\u666F\u989C\u8272 */\n --utags-text-tag-background-color: orange;\n}\n\ndata-utags_list_node*=",bar,"] {\n /* \u5217\u8868\u4E2D\u542B\u6709 \'bar\' \u6807\u7B7E\u7684\u6761\u76EE\u7684\u80CC\u666F\u8272 */\n background-color: aqua;\n}\n\nbody {\n /* \u6D4F\u89C8\u8FC7\u7684\u5E16\u5B50\u7684\u6807\u9898\u989C\u8272 */\n --utags-visited-title-color: red;\n}\n\n/* \u6DF1\u8272\u6A21\u5F0F */\n[data-utags_darkmode="1"] body {\n /* \u6D4F\u89C8\u8FC7\u7684\u5E16\u5B50\u7684\u6807\u9898\u989C\u8272 */\n --utags-visited-title-color: yellow;\n}\n</pre>\n </p>\n <p><a href="https://github.com/utags/utags/tree/main/custom-style-examples">\u66F4\u591A\u793A\u4F8B</a></p>\n ',
  1295. "settings.useSimplePrompt":
  1296. "\u4F7F\u7528\u7B80\u5355\u65B9\u5F0F\u6DFB\u52A0\u6807\u7B7E",
  1297. "settings.openTagsPage": "\u6807\u7B7E\u5217\u8868",
  1298. "settings.openDataPage":
  1299. "\u5BFC\u51FA\u6570\u636E/\u5BFC\u5165\u6570\u636E",
  1300. "settings.title":
  1301. "\u{1F3F7}\uFE0F \u5C0F\u9C7C\u6807\u7B7E (UTags) - \u4E3A\u94FE\u63A5\u6DFB\u52A0\u7528\u6237\u6807\u7B7E",
  1302. "settings.information":
  1303. "\u66F4\u6539\u8BBE\u7F6E\u540E\uFF0C\u91CD\u65B0\u52A0\u8F7D\u9875\u9762\u5373\u53EF\u751F\u6548",
  1304. "settings.report": "\u53CD\u9988\u95EE\u9898",
  1305. "prompt.addTags":
  1306. "[UTags] \u8BF7\u8F93\u5165\u6807\u7B7E\uFF0C\u591A\u4E2A\u6807\u7B7E\u4EE5\u9017\u53F7\u5206\u9694",
  1307. "prompt.pinnedTags": "\u7F6E\u9876",
  1308. "prompt.mostUsedTags": "\u6700\u8FD1\u5E38\u7528",
  1309. "prompt.recentAddedTags": "\u6700\u65B0\u6DFB\u52A0",
  1310. "prompt.emojiTags": "\u7B26\u53F7",
  1311. "prompt.copy": "\u590D\u5236",
  1312. "prompt.cancel": "\u53D6\u6D88",
  1313. "prompt.ok": "\u786E\u8BA4",
  1314. "prompt.settings": "\u8BBE\u7F6E",
  1315. }
  1316. var zh_cn_default2 = messages4
  1317. var i2 = initI18n({
  1318. "en,en-US": en_default2,
  1319. "zh,zh-CN": zh_cn_default2,
  1320. })
  1321. function getFirstHeadElement(tagName = "h1") {
  1322. for (const element of $$(tagName)) {
  1323. if (element.closest(".browser_extension_settings_container")) {
  1324. continue
  1325. }
  1326. return element
  1327. }
  1328. return void 0
  1329. }
  1330. function trimTitle(title) {
  1331. return title ? title.replaceAll(/\s+/gm, " ").trim() : ""
  1332. }
  1333. function getTrimmedTitle(element) {
  1334. return trimTitle(element.textContent)
  1335. }
  1336. function splitTags(text) {
  1337. if (!text) {
  1338. return []
  1339. }
  1340. return text
  1341. .trim()
  1342. .replaceAll(/[\n\r\t]/gm, " ")
  1343. .split(/\s*[,,]\s*/)
  1344. }
  1345. function sortTags(tags, privilegedTags) {
  1346. return tags.sort((a, b) => {
  1347. const pA = privilegedTags.includes(a)
  1348. const pB = privilegedTags.includes(b)
  1349. if (pA && pB) {
  1350. return 0
  1351. }
  1352. if (pA) {
  1353. return -1
  1354. }
  1355. if (pB) {
  1356. return 1
  1357. }
  1358. return 0
  1359. })
  1360. }
  1361. function filterTags(tags, removed) {
  1362. if (typeof removed === "string") {
  1363. removed = [removed]
  1364. }
  1365. if (removed.length === 0) {
  1366. return tags
  1367. }
  1368. return tags.filter((value) => {
  1369. return !removed.includes(value)
  1370. })
  1371. }
  1372. async function copyText(data) {
  1373. const textArea = createElement("textarea", {
  1374. style: "position: absolute; left: -100%;",
  1375. contentEditable: "true",
  1376. })
  1377. textArea.value = data.replaceAll("\xA0", " ")
  1378. document.body.append(textArea)
  1379. textArea.select()
  1380. await navigator.clipboard.writeText(textArea.value)
  1381. textArea.remove()
  1382. }
  1383. function deleteUrlParameters(urlString, keys, excepts) {
  1384. const url = new URL(urlString)
  1385. if (keys === "*") {
  1386. if (excepts && excepts.length > 0) {
  1387. const parameters2 = new URLSearchParams(url.search)
  1388. keys = []
  1389. for (const key of parameters2.keys()) {
  1390. if (!excepts.includes(key)) {
  1391. keys.push(key)
  1392. }
  1393. }
  1394. } else {
  1395. url.search = ""
  1396. return url.toString()
  1397. }
  1398. }
  1399. if (typeof keys === "string") {
  1400. keys = [keys]
  1401. }
  1402. const parameters = new URLSearchParams(url.search)
  1403. for (const key of keys) {
  1404. parameters.delete(key)
  1405. }
  1406. url.search = parameters.size === 0 ? "" : "?" + parameters.toString()
  1407. return url.toString()
  1408. }
  1409. function getUrlParameters(urlString, keys, allowEmpty = false) {
  1410. const url = new URL(urlString)
  1411. if (typeof keys === "string") {
  1412. keys = [keys]
  1413. }
  1414. const result = {}
  1415. const parameters = new URLSearchParams(url.search)
  1416. for (const key of keys) {
  1417. if (key) {
  1418. const value = parameters.get(key)
  1419. if (
  1420. (allowEmpty && value !== void 0 && value !== null) ||
  1421. (!allowEmpty && value)
  1422. ) {
  1423. result[key] = value
  1424. }
  1425. }
  1426. }
  1427. return result
  1428. }
  1429. var extensionVersion = "0.8.0"
  1430. var databaseVersion = 2
  1431. var storageKey2 = "extension.utags.urlmap"
  1432. var storageKeyRecentTags = "extension.utags.recenttags"
  1433. var storageKeyMostUsedTags = "extension.utags.mostusedtags"
  1434. var storageKeyRecentAddedTags = "extension.utags.recentaddedtags"
  1435. var cachedUrlMap
  1436. async function getUrlMap() {
  1437. return (await getValue(storageKey2)) || {}
  1438. }
  1439. async function getUrlMapVesion1() {
  1440. return getValue("plugin.utags.tags.v1")
  1441. }
  1442. async function getCachedUrlMap() {
  1443. if (!cachedUrlMap) {
  1444. cachedUrlMap = await getUrlMap()
  1445. }
  1446. return cachedUrlMap
  1447. }
  1448. function getTags(key) {
  1449. return (cachedUrlMap && cachedUrlMap[key]) || { tags: [] }
  1450. }
  1451. async function saveTags(key, tags, meta) {
  1452. const urlMap = await getUrlMap()
  1453. urlMap.meta = Object.assign({}, urlMap.meta, {
  1454. extensionVersion,
  1455. databaseVersion,
  1456. })
  1457. const newTags = mergeTags(tags, [])
  1458. let oldTags = []
  1459. if (newTags.length === 0) {
  1460. delete urlMap[key]
  1461. } else {
  1462. const now = Date.now()
  1463. const data = urlMap[key] || {}
  1464. oldTags = data.tags
  1465. const newMeta = Object.assign({}, data.meta, meta, {
  1466. updated: now,
  1467. })
  1468. newMeta.created = newMeta.created || now
  1469. urlMap[key] = {
  1470. tags: newTags,
  1471. meta: newMeta,
  1472. }
  1473. }
  1474. await setValue(storageKey2, urlMap)
  1475. await addRecentTags(newTags, oldTags)
  1476. }
  1477. function getScore(weight = 1) {
  1478. return (Math.floor(Date.now() / 1e3) / 1e9) * weight
  1479. }
  1480. async function addRecentTags(newTags, oldTags) {
  1481. if (newTags.length === 0) {
  1482. return
  1483. }
  1484. newTags =
  1485. oldTags && oldTags.length > 0
  1486. ? newTags.filter((v) => !oldTags.includes(v))
  1487. : newTags
  1488. if (newTags.length > 0) {
  1489. const recentTags = (await getValue(storageKeyRecentTags)) || []
  1490. const score = getScore()
  1491. for (const tag of newTags) {
  1492. recentTags.push({
  1493. tag,
  1494. score,
  1495. })
  1496. }
  1497. if (recentTags.length > 1e3) {
  1498. recentTags.splice(0, 100)
  1499. }
  1500. await setValue(storageKeyRecentTags, recentTags)
  1501. await generateMostUsedAndRecentAddedTags(recentTags)
  1502. }
  1503. }
  1504. async function generateMostUsedAndRecentAddedTags(recentTags) {
  1505. const mostUsed = {}
  1506. for (const recentTag of recentTags) {
  1507. if (!recentTag.tag) {
  1508. continue
  1509. }
  1510. if (mostUsed[recentTag.tag]) {
  1511. mostUsed[recentTag.tag].score += recentTag.score
  1512. } else if (recentTag.tag) {
  1513. mostUsed[recentTag.tag] = {
  1514. tag: recentTag.tag,
  1515. score: recentTag.score,
  1516. }
  1517. }
  1518. }
  1519. const mostUsedTags2 = Object.values(mostUsed)
  1520. .filter((v) => v.score > getScore(1.5))
  1521. .sort((a, b) => {
  1522. return b.score - a.score
  1523. })
  1524. .map((v) => v.tag)
  1525. .slice(0, 200)
  1526. const uniqSet = /* @__PURE__ */ new Set()
  1527. const recentAddedTags2 = recentTags
  1528. .map((v) => v.tag)
  1529. .reverse()
  1530. .filter((v) => v && !uniqSet.has(v) && uniqSet.add(v))
  1531. .slice(0, 200)
  1532. await setValue(storageKeyMostUsedTags, mostUsedTags2)
  1533. await setValue(storageKeyRecentAddedTags, recentAddedTags2)
  1534. }
  1535. async function getMostUsedTags() {
  1536. return (await getValue(storageKeyMostUsedTags)) || []
  1537. }
  1538. async function getRecentAddedTags() {
  1539. return (await getValue(storageKeyRecentAddedTags)) || []
  1540. }
  1541. async function getPinnedTags() {
  1542. return splitTags(getSettingsValue("pinnedTags") || "")
  1543. }
  1544. async function getEmojiTags() {
  1545. return splitTags(getSettingsValue("emojiTags") || "")
  1546. }
  1547. function addTagsValueChangeListener(func) {
  1548. addValueChangeListener(storageKey2, func)
  1549. }
  1550. addTagsValueChangeListener(async () => {
  1551. cachedUrlMap = void 0
  1552. await checkVersion()
  1553. })
  1554. async function reload() {
  1555. console.log("Current extionsion is outdated, need reload page")
  1556. const urlMap = await getUrlMap()
  1557. urlMap.meta = urlMap.meta || {}
  1558. await setValue(storageKey2, urlMap)
  1559. location.reload()
  1560. }
  1561. async function checkVersion() {
  1562. cachedUrlMap = await getUrlMap()
  1563. const meta = cachedUrlMap.meta || {}
  1564. if (meta.extensionVersion !== extensionVersion) {
  1565. console.log(
  1566. "Previous extension version:",
  1567. meta.extensionVersion,
  1568. "current extension version:",
  1569. extensionVersion
  1570. )
  1571. if (meta.extensionVersion > extensionVersion) {
  1572. }
  1573. }
  1574. if (meta.databaseVersion !== databaseVersion) {
  1575. console.log(
  1576. "Previous database version:",
  1577. meta.databaseVersion,
  1578. "current database version:",
  1579. databaseVersion
  1580. )
  1581. if (meta.databaseVersion > databaseVersion) {
  1582. await reload()
  1583. return false
  1584. }
  1585. }
  1586. return true
  1587. }
  1588. function isValidKey(key) {
  1589. return isUrl(key)
  1590. }
  1591. function isValidTags(tags) {
  1592. return Array.isArray(tags)
  1593. }
  1594. function mergeTags(tags, tags2) {
  1595. tags = tags || []
  1596. tags2 = tags2 || []
  1597. return uniq(
  1598. tags
  1599. .concat(tags2)
  1600. .map((v) => (v ? String(v).trim() : v))
  1601. .filter(Boolean)
  1602. )
  1603. }
  1604. async function migrationData(urlMap) {
  1605. console.log("Before migration", JSON.stringify(urlMap))
  1606. const meta = urlMap.meta || {}
  1607. const now = Date.now()
  1608. const meta2 = { created: now, updated: now }
  1609. if (!meta.databaseVersion) {
  1610. meta.databaseVersion = 1
  1611. }
  1612. if (meta.databaseVersion === 1) {
  1613. for (const key in urlMap) {
  1614. if (!Object.hasOwn(urlMap, key)) {
  1615. continue
  1616. }
  1617. if (!isValidKey(key)) {
  1618. continue
  1619. }
  1620. const tags = urlMap[key]
  1621. if (!isValidTags(tags)) {
  1622. throw new Error("Invaid data format.")
  1623. }
  1624. const newTags = mergeTags(tags, [])
  1625. if (newTags.length > 0) {
  1626. urlMap[key] = { tags: newTags, meta: meta2 }
  1627. } else {
  1628. delete urlMap[key]
  1629. }
  1630. }
  1631. meta.databaseVersion = 2
  1632. }
  1633. if (meta.databaseVersion === 2) {
  1634. }
  1635. urlMap.meta = meta
  1636. console.log("After migration", JSON.stringify(urlMap))
  1637. return urlMap
  1638. }
  1639. async function mergeData(urlMapNew) {
  1640. if (typeof urlMapNew !== "object") {
  1641. throw new TypeError("Invalid data format")
  1642. }
  1643. let numberOfLinks = 0
  1644. let numberOfTags = 0
  1645. const urlMap = await getUrlMap()
  1646. if (
  1647. !urlMapNew.meta ||
  1648. urlMapNew.meta.databaseVersion !== urlMap.meta.databaseVersion
  1649. ) {
  1650. urlMapNew = await migrationData(urlMapNew)
  1651. }
  1652. if (urlMapNew.meta.databaseVersion !== urlMap.meta.databaseVersion) {
  1653. throw new Error("Invalid database version")
  1654. }
  1655. for (const key in urlMapNew) {
  1656. if (!Object.hasOwn(urlMapNew, key)) {
  1657. continue
  1658. }
  1659. if (!isValidKey(key)) {
  1660. continue
  1661. }
  1662. const tags = urlMapNew[key].tags || []
  1663. const meta = urlMapNew[key].meta || {}
  1664. if (!isValidTags(tags)) {
  1665. throw new Error("Invaid data format.")
  1666. }
  1667. const orgData = urlMap[key] || { tags: [] }
  1668. const orgTags = orgData.tags || []
  1669. const newTags = mergeTags(orgTags, tags)
  1670. const now = Date.now()
  1671. if (newTags.length > 0) {
  1672. const orgMeta = orgData.meta || {}
  1673. const created = Math.min(orgMeta.created || now, meta.created || now)
  1674. const updated = Math.max(
  1675. orgMeta.updated || 0,
  1676. meta.updated || 0,
  1677. created
  1678. )
  1679. const newMata = Object.assign({}, orgMeta, meta, { created, updated })
  1680. urlMap[key] = Object.assign({}, orgData, {
  1681. tags: newTags,
  1682. meta: newMata,
  1683. })
  1684. numberOfTags += Math.max(newTags.length - orgTags.length, 0)
  1685. if (orgTags.length === 0) {
  1686. numberOfLinks++
  1687. }
  1688. } else {
  1689. delete urlMap[key]
  1690. }
  1691. }
  1692. await setValue(storageKey2, urlMap)
  1693. console.log(
  1694. "\u6570\u636E\u5DF2\u6210\u529F\u5BFC\u5165\uFF0C\u65B0\u589E "
  1695. .concat(numberOfLinks, " \u6761\u94FE\u63A5\uFF0C\u65B0\u589E ")
  1696. .concat(numberOfTags, " \u6761\u6807\u7B7E\u3002")
  1697. )
  1698. return { numberOfLinks, numberOfTags }
  1699. }
  1700. async function migration() {
  1701. const result = await checkVersion()
  1702. if (!result) {
  1703. return
  1704. }
  1705. cachedUrlMap = await getUrlMap()
  1706. const meta = cachedUrlMap.meta || {}
  1707. if (meta.databaseVersion !== databaseVersion) {
  1708. meta.databaseVersion = meta.databaseVersion || 1
  1709. if (meta.databaseVersion < databaseVersion) {
  1710. console.log("Migration start")
  1711. await saveTags("any", [])
  1712. console.log("Migration done")
  1713. }
  1714. }
  1715. const urlMapVer1 = await getUrlMapVesion1()
  1716. if (urlMapVer1) {
  1717. console.log(
  1718. "Migration start: database version 1 to database version",
  1719. databaseVersion
  1720. )
  1721. const result2 = await mergeData(urlMapVer1)
  1722. if (result2) {
  1723. await setValue("plugin.utags.tags.v1", null)
  1724. }
  1725. }
  1726. }
  1727. async function outputData() {
  1728. if (
  1729. /^(utags\.pipecraft\.net|localhost|127\.0\.0\.1)$/.test(location.hostname)
  1730. ) {
  1731. const urlMap = await getUrlMap()
  1732. const textarea = createElement("textarea")
  1733. textarea.id = "utags_output"
  1734. textarea.setAttribute("style", "display:none")
  1735. textarea.value = JSON.stringify(urlMap)
  1736. doc.body.append(textarea)
  1737. textarea.addEventListener("click", async () => {
  1738. if (textarea.dataset.utags_type === "export") {
  1739. const urlMap2 = await getUrlMap()
  1740. textarea.value = JSON.stringify(urlMap2)
  1741. textarea.dataset.utags_type = "export_done"
  1742. textarea.click()
  1743. } else if (textarea.dataset.utags_type === "import") {
  1744. const data = textarea.value
  1745. try {
  1746. const result = await mergeData(JSON.parse(data))
  1747. textarea.value = JSON.stringify(result)
  1748. textarea.dataset.utags_type = "import_done"
  1749. textarea.click()
  1750. } catch (error) {
  1751. console.error(error)
  1752. textarea.value = JSON.stringify(error)
  1753. textarea.dataset.utags_type = "import_failed"
  1754. textarea.click()
  1755. }
  1756. }
  1757. })
  1758. }
  1759. }
  1760. function createModal(attributes) {
  1761. const div = addElement2(doc.body, "div", {
  1762. class: "utags_modal",
  1763. })
  1764. const wrapper = addElement2(div, "div", {
  1765. class: "utags_modal_wrapper",
  1766. })
  1767. const content = addElement2(wrapper, "div", attributes)
  1768. addClass(content, "utags_modal_content")
  1769. let removed = false
  1770. return {
  1771. remove() {
  1772. if (!removed) {
  1773. removed = true
  1774. div.remove()
  1775. }
  1776. },
  1777. getContentElement() {
  1778. return content
  1779. },
  1780. }
  1781. }
  1782. var pinnedTags
  1783. var mostUsedTags
  1784. var recentAddedTags
  1785. var emojiTags
  1786. var displayedTags = /* @__PURE__ */ new Set()
  1787. var currentTags = /* @__PURE__ */ new Set()
  1788. function onSelect(selected, input) {
  1789. if (selected) {
  1790. input.value = ""
  1791. const tags = splitTags(selected)
  1792. for (const tag of tags) {
  1793. if (tag.trim()) {
  1794. currentTags.add(tag.trim())
  1795. }
  1796. }
  1797. updateLists()
  1798. }
  1799. }
  1800. function removeTag(tag) {
  1801. if (tag) {
  1802. tag = tag.trim()
  1803. currentTags.delete(tag)
  1804. updateLists()
  1805. }
  1806. }
  1807. function updateLists() {
  1808. displayedTags = /* @__PURE__ */ new Set()
  1809. const ul1 = $(".utags_modal_content ul.utags_current_tags")
  1810. if (ul1) {
  1811. updateCurrentTagList(ul1)
  1812. }
  1813. const ul = $(".utags_modal_content ul.utags_select_list.utags_pined_list")
  1814. if (ul) {
  1815. updateCandidateTagList(ul, pinnedTags)
  1816. }
  1817. const ul4 = $(".utags_modal_content ul.utags_select_list.utags_emoji_list")
  1818. if (ul4) {
  1819. updateCandidateTagList(ul4, emojiTags)
  1820. }
  1821. const ul2 = $(".utags_modal_content ul.utags_select_list.utags_most_used")
  1822. if (ul2) {
  1823. updateCandidateTagList(ul2, mostUsedTags)
  1824. }
  1825. const ul3 = $(
  1826. ".utags_modal_content ul.utags_select_list.utags_recent_added"
  1827. )
  1828. if (ul3) {
  1829. updateCandidateTagList(ul3, recentAddedTags)
  1830. }
  1831. }
  1832. function updateCandidateTagList(ul, candidateTags) {
  1833. ul.textContent = ""
  1834. let index = 0
  1835. for (const text of candidateTags) {
  1836. if (displayedTags.has(text)) {
  1837. continue
  1838. }
  1839. displayedTags.add(text)
  1840. const li = addElement2(ul, "li", {})
  1841. addElement2(li, "span", {
  1842. textContent: text,
  1843. })
  1844. index++
  1845. if (index >= 50) {
  1846. break
  1847. }
  1848. }
  1849. }
  1850. function getNextList(parentElement) {
  1851. let parentNext = parentElement.nextElementSibling
  1852. while (parentNext && parentNext.children.length === 0) {
  1853. parentNext = parentNext.nextElementSibling
  1854. }
  1855. return parentNext
  1856. }
  1857. function getPreviousList(parentElement) {
  1858. let parentPrevious = parentElement.previousElementSibling
  1859. while (parentPrevious && parentPrevious.children.length === 0) {
  1860. parentPrevious = parentPrevious.previousElementSibling
  1861. }
  1862. return parentPrevious
  1863. }
  1864. function updateCurrentTagList(ul) {
  1865. ul.textContent = ""
  1866. const sortedTags = sortTags([...currentTags], emojiTags)
  1867. for (const tag of sortedTags) {
  1868. displayedTags.add(tag)
  1869. const li = addElement2(ul, "li")
  1870. const a = createTag(tag, {
  1871. isEmoji: emojiTags.includes(tag),
  1872. noLink: true,
  1873. })
  1874. li.append(a)
  1875. }
  1876. }
  1877. function removeAllActive(type) {
  1878. if (type !== 2) {
  1879. const selector = ".utags_modal_content ul.utags_select_list .utags_active"
  1880. for (const li of $$(selector)) {
  1881. removeClass(li, "utags_active")
  1882. }
  1883. }
  1884. if (type !== 1) {
  1885. const selector =
  1886. ".utags_modal_content ul.utags_select_list .utags_active2"
  1887. for (const li of $$(selector)) {
  1888. removeClass(li, "utags_active2")
  1889. }
  1890. }
  1891. }
  1892. async function copyCurrentTags(input) {
  1893. const value = sortTags([...currentTags], emojiTags).join(", ")
  1894. await copyText(value)
  1895. input.value = value
  1896. input.focus()
  1897. input.select()
  1898. }
  1899. function stopEventPropagation(event) {
  1900. event.preventDefault()
  1901. event.stopPropagation()
  1902. event.stopImmediatePropagation()
  1903. }
  1904. function createPromptView(message, value, resolve) {
  1905. const modal = createModal({ class: "utags_prompt" })
  1906. const content = modal.getContentElement()
  1907. value = value || ""
  1908. addElement2(content, "span", {
  1909. class: "utags_title",
  1910. textContent: message,
  1911. })
  1912. const currentTagsWrapper = addElement2(content, "div", {
  1913. class: "utags_current_tags_wrapper",
  1914. })
  1915. addElement2(currentTagsWrapper, "span", {
  1916. textContent: "",
  1917. style: "display: none;",
  1918. "data-utags": "",
  1919. })
  1920. addElement2(currentTagsWrapper, "ul", {
  1921. class: "utags_current_tags utags_ul",
  1922. })
  1923. const input = addElement2(content, "input", {
  1924. type: "text",
  1925. placeholder: "foo, bar",
  1926. onblur(event) {
  1927. if (event.relatedTarget) {
  1928. input.focus()
  1929. stopEventPropagation(event)
  1930. }
  1931. setTimeout(() => {
  1932. if (doc.activeElement === doc.body) {
  1933. closeModal2()
  1934. }
  1935. }, 1)
  1936. },
  1937. })
  1938. input.focus()
  1939. input.select()
  1940. addElement2(currentTagsWrapper, "button", {
  1941. type: "button",
  1942. class: "utags_button_copy",
  1943. textContent: i2("prompt.copy"),
  1944. async onclick() {
  1945. await copyCurrentTags(input)
  1946. },
  1947. })
  1948. const listWrapper = addElement2(content, "div", {
  1949. class: "utags_list_wrapper",
  1950. })
  1951. addElement2(listWrapper, "ul", {
  1952. class: "utags_select_list utags_pined_list",
  1953. "data-utags_list_name": i2("prompt.pinnedTags"),
  1954. })
  1955. addElement2(listWrapper, "ul", {
  1956. class: "utags_select_list utags_most_used",
  1957. "data-utags_list_name": i2("prompt.mostUsedTags"),
  1958. })
  1959. addElement2(listWrapper, "ul", {
  1960. class: "utags_select_list utags_recent_added",
  1961. "data-utags_list_name": i2("prompt.recentAddedTags"),
  1962. })
  1963. addElement2(listWrapper, "ul", {
  1964. class: "utags_select_list utags_emoji_list",
  1965. "data-utags_list_name": i2("prompt.emojiTags"),
  1966. })
  1967. updateLists()
  1968. const buttonWrapper = addElement2(content, "div", {
  1969. class: "utags_buttons_wrapper",
  1970. })
  1971. let closed = false
  1972. const closeModal2 = (value2) => {
  1973. if (closed) {
  1974. return
  1975. }
  1976. closed = true
  1977. removeEventListener(input, "keydown", keydonwHandler, true)
  1978. removeEventListener(doc, "keydown", keydonwHandler, true)
  1979. removeEventListener(doc, "mousedown", mousedownHandler, true)
  1980. removeEventListener(doc, "click", clickHandler, true)
  1981. removeEventListener(doc, "mouseover", mouseoverHandler, true)
  1982. setTimeout(() => {
  1983. modal.remove()
  1984. })
  1985. resolve(value2 == null ? null : value2)
  1986. }
  1987. const okHandler = () => {
  1988. closeModal2(Array.from(currentTags).join(","))
  1989. }
  1990. addElement2(buttonWrapper, "button", {
  1991. type: "button",
  1992. textContent: i2("prompt.cancel"),
  1993. onclick() {
  1994. closeModal2()
  1995. },
  1996. })
  1997. addElement2(buttonWrapper, "button", {
  1998. type: "button",
  1999. class: "utags_primary",
  2000. textContent: i2("prompt.ok"),
  2001. onclick() {
  2002. onSelect(input.value.trim(), input)
  2003. okHandler()
  2004. },
  2005. })
  2006. const keydonwHandler = (event) => {
  2007. if (event.defaultPrevented || !$(".utags_modal_content")) {
  2008. return
  2009. }
  2010. let current = $(".utags_modal_content ul.utags_select_list .utags_active")
  2011. switch (event.key) {
  2012. case "Escape": {
  2013. stopEventPropagation(event)
  2014. closeModal2()
  2015. break
  2016. }
  2017. case "Enter": {
  2018. stopEventPropagation(event)
  2019. input.focus()
  2020. if (current) {
  2021. onSelect(current.textContent, input)
  2022. } else if (input.value.trim()) {
  2023. onSelect(input.value.trim(), input)
  2024. } else {
  2025. okHandler()
  2026. }
  2027. break
  2028. }
  2029. case "Tab": {
  2030. stopEventPropagation(event)
  2031. input.focus()
  2032. break
  2033. }
  2034. case "ArrowDown": {
  2035. stopEventPropagation(event)
  2036. input.focus()
  2037. current = $(
  2038. ".utags_modal_content ul.utags_select_list .utags_active,.utags_modal_content ul.utags_select_list .utags_active2"
  2039. )
  2040. if (current) {
  2041. const next = current.nextElementSibling
  2042. if (next) {
  2043. next.scrollIntoView({ block: "end" })
  2044. removeAllActive()
  2045. addClass(next, "utags_active")
  2046. }
  2047. } else {
  2048. const next = $(".utags_modal_content ul.utags_select_list li")
  2049. if (next) {
  2050. next.scrollIntoView({ block: "end" })
  2051. removeAllActive()
  2052. addClass(next, "utags_active")
  2053. }
  2054. }
  2055. break
  2056. }
  2057. case "ArrowUp": {
  2058. stopEventPropagation(event)
  2059. input.focus()
  2060. current = $(
  2061. ".utags_modal_content ul.utags_select_list .utags_active,.utags_modal_content ul.utags_select_list .utags_active2"
  2062. )
  2063. if (current) {
  2064. const previous = current.previousElementSibling
  2065. if (previous) {
  2066. previous.scrollIntoView({ block: "end" })
  2067. removeAllActive()
  2068. addClass(previous, "utags_active")
  2069. }
  2070. }
  2071. break
  2072. }
  2073. case "ArrowLeft": {
  2074. stopEventPropagation(event)
  2075. input.focus()
  2076. current = $(
  2077. ".utags_modal_content ul.utags_select_list .utags_active,.utags_modal_content ul.utags_select_list .utags_active2"
  2078. )
  2079. if (current) {
  2080. const parentElement = current.parentElement
  2081. const index = Array.prototype.indexOf.call(
  2082. parentElement.children,
  2083. current
  2084. )
  2085. const parentPrevious = getPreviousList(parentElement)
  2086. if (parentPrevious) {
  2087. removeAllActive()
  2088. const newIndex = Math.min(
  2089. parentPrevious.children.length - 1,
  2090. index
  2091. )
  2092. const next = parentPrevious.children[newIndex]
  2093. next.scrollIntoView({ block: "end" })
  2094. addClass(next, "utags_active")
  2095. }
  2096. }
  2097. break
  2098. }
  2099. case "ArrowRight": {
  2100. stopEventPropagation(event)
  2101. input.focus()
  2102. current = $(
  2103. ".utags_modal_content ul.utags_select_list .utags_active,.utags_modal_content ul.utags_select_list .utags_active2"
  2104. )
  2105. if (current) {
  2106. const parentElement = current.parentElement
  2107. const index = Array.prototype.indexOf.call(
  2108. parentElement.children,
  2109. current
  2110. )
  2111. const parentNext = getNextList(parentElement)
  2112. if (parentNext) {
  2113. removeAllActive()
  2114. const newIndex = Math.min(parentNext.children.length - 1, index)
  2115. const next = parentNext.children[newIndex]
  2116. next.scrollIntoView({ block: "end" })
  2117. addClass(next, "utags_active")
  2118. }
  2119. }
  2120. break
  2121. }
  2122. default: {
  2123. removeAllActive()
  2124. break
  2125. }
  2126. }
  2127. }
  2128. addEventListener(input, "keydown", keydonwHandler, true)
  2129. addEventListener(doc, "keydown", keydonwHandler, true)
  2130. const mousedownHandler = (event) => {
  2131. if (event.defaultPrevented || !$(".utags_modal_content")) {
  2132. return
  2133. }
  2134. const target = event.target
  2135. if (!target) {
  2136. return
  2137. }
  2138. if (target.closest(".utags_modal_content")) {
  2139. if (target === input) {
  2140. return
  2141. }
  2142. event.preventDefault()
  2143. input.focus()
  2144. } else {
  2145. event.preventDefault()
  2146. input.focus()
  2147. }
  2148. }
  2149. addEventListener(doc, "mousedown", mousedownHandler, true)
  2150. const clickHandler = (event) => {
  2151. if (event.defaultPrevented || !$(".utags_modal_content")) {
  2152. return
  2153. }
  2154. const target = event.target
  2155. if (!target) {
  2156. return
  2157. }
  2158. if (
  2159. !target.closest(".utags_modal_content button") &&
  2160. !target.closest(".utags_modal_content .utags_footer a")
  2161. ) {
  2162. stopEventPropagation(event)
  2163. }
  2164. if (target.closest(".utags_modal_content")) {
  2165. input.focus()
  2166. if (target.closest(".utags_modal_content ul.utags_select_list li")) {
  2167. onSelect(target.textContent, input)
  2168. }
  2169. if (target.closest(".utags_modal_content ul.utags_current_tags li a")) {
  2170. removeTag(target.dataset.utags_tag)
  2171. }
  2172. } else {
  2173. closeModal2()
  2174. }
  2175. }
  2176. addEventListener(doc, "click", clickHandler, true)
  2177. const mouseoverHandler = (event) => {
  2178. const target = event.target
  2179. if (!(target == null ? void 0 : target.closest(".utags_modal_content"))) {
  2180. return
  2181. }
  2182. const li = target.closest("ul.utags_select_list li")
  2183. if (li) {
  2184. removeAllActive()
  2185. addClass(li, "utags_active2")
  2186. } else {
  2187. removeAllActive(2)
  2188. }
  2189. }
  2190. addEventListener(doc, "mousemove", mouseoverHandler, true)
  2191. const footer = addElement2(content, "div", {
  2192. class: "utags_footer",
  2193. })
  2194. addElement2(footer, "a", {
  2195. class: "utags_link_settings",
  2196. textContent: i2("prompt.settings"),
  2197. async onclick() {
  2198. closeModal2()
  2199. setTimeout(showSettings, 1)
  2200. },
  2201. })
  2202. }
  2203. async function advancedPrompt(message, value) {
  2204. pinnedTags = await getPinnedTags()
  2205. mostUsedTags = await getMostUsedTags()
  2206. recentAddedTags = await getRecentAddedTags()
  2207. emojiTags = await getEmojiTags()
  2208. currentTags = new Set(splitTags(value))
  2209. return new Promise((resolve) => {
  2210. createPromptView(message, value, resolve)
  2211. })
  2212. }
  2213. async function simplePrompt(message, value) {
  2214. return prompt(message, value)
  2215. }
  2216. var prefix2 = location.origin + "/"
  2217. var host = location.host
  2218. var useVisitedFunction = false
  2219. var displayMark = false
  2220. var isAvailable = false
  2221. var cache = {}
  2222. function setPrefix(newPrefix) {
  2223. prefix2 = newPrefix
  2224. }
  2225. function isAvailableOnCurrentSite() {
  2226. return isAvailable
  2227. }
  2228. function setVisitedAvailable(value) {
  2229. isAvailable = value
  2230. }
  2231. function onSettingsChange() {
  2232. useVisitedFunction = getSettingsValue("useVisitedFunction_".concat(host))
  2233. displayMark =
  2234. getSettingsValue("displayEffectOfTheVisitedContent_".concat(host)) !== "0"
  2235. }
  2236. function getVisitedLinks() {
  2237. if (!useVisitedFunction) {
  2238. return []
  2239. }
  2240. return JSON.parse(localStorage.getItem("utags_visited") || "[]") || []
  2241. }
  2242. function saveVisitedLinks(newVisitedLinks) {
  2243. if (useVisitedFunction) {
  2244. localStorage.setItem("utags_visited", JSON.stringify(newVisitedLinks))
  2245. }
  2246. }
  2247. function convertKey(url) {
  2248. if (url.includes(prefix2)) {
  2249. return url.slice(prefix2.length)
  2250. }
  2251. return url
  2252. }
  2253. var TAG_VISITED = ":visited"
  2254. function addVisited(key) {
  2255. if (key && !cache[key]) {
  2256. cache[key] = 1
  2257. } else {
  2258. return
  2259. }
  2260. key = convertKey(key)
  2261. const visitedLinks = getVisitedLinks()
  2262. if (!visitedLinks.includes(key)) {
  2263. visitedLinks.push(key)
  2264. saveVisitedLinks(visitedLinks)
  2265. }
  2266. }
  2267. function removeVisited(key) {
  2268. key = convertKey(key)
  2269. const visitedLinks = getVisitedLinks()
  2270. if (visitedLinks.includes(key)) {
  2271. const newVisitedLinks = visitedLinks.filter((value) => {
  2272. return value !== key
  2273. })
  2274. saveVisitedLinks(newVisitedLinks)
  2275. }
  2276. }
  2277. function isVisited(key) {
  2278. if (!displayMark) {
  2279. return false
  2280. }
  2281. key = convertKey(key)
  2282. const visitedLinks = getVisitedLinks()
  2283. return visitedLinks.includes(key)
  2284. }
  2285. function markElementWhetherVisited(key, element) {
  2286. if (isVisited(key)) {
  2287. element.dataset.utags_visited = "1"
  2288. } else if (element.dataset.utags_visited === "1") {
  2289. delete element.dataset.utags_visited
  2290. }
  2291. }
  2292. var numberLimitOfShowAllUtagsInArea = 10
  2293. var lastShownArea
  2294. var isPromptShown = false
  2295. function hideAllUtagsInArea(target) {
  2296. const element = $(".utags_show_all")
  2297. if (!element) {
  2298. return
  2299. }
  2300. if (element === target || element.contains(target)) {
  2301. return
  2302. }
  2303. if (!target) {
  2304. lastShownArea = void 0
  2305. }
  2306. for (const element2 of $$(".utags_show_all")) {
  2307. addClass(element2, "utags_hide_all")
  2308. removeClass(element2, "utags_show_all")
  2309. setTimeout(() => {
  2310. removeClass(element2, "utags_hide_all")
  2311. })
  2312. }
  2313. }
  2314. function showAllUtagsInArea(element) {
  2315. if (!element) {
  2316. return false
  2317. }
  2318. const utags = $$(".utags_ul", element)
  2319. if (utags.length > 0 && utags.length <= numberLimitOfShowAllUtagsInArea) {
  2320. addClass(element, "utags_show_all")
  2321. return true
  2322. }
  2323. return false
  2324. }
  2325. function findElementToShowAllUtags(target) {
  2326. hideAllUtagsInArea(target)
  2327. if (!target) {
  2328. return
  2329. }
  2330. const targets = []
  2331. let width
  2332. let height
  2333. do {
  2334. targets.push(target)
  2335. const tagName = target.tagName
  2336. const style = getComputedStyle(target)
  2337. if (
  2338. style.position === "fixed" ||
  2339. style.position === "sticky" ||
  2340. /^(BODY|TABLE|UL|NAV|ARTICLE|SECTION|ASIDE)$/.test(tagName)
  2341. ) {
  2342. break
  2343. }
  2344. target = target.parentElement
  2345. if (target) {
  2346. width = target.offsetWidth || target.clientWidth
  2347. height = target.offsetHeight || target.clientHeight
  2348. } else {
  2349. width = 0
  2350. height = 0
  2351. }
  2352. } while (targets.length < 8 && target && width > 20 && height > 10)
  2353. while (targets.length > 0) {
  2354. const area = targets.pop()
  2355. if (showAllUtagsInArea(area)) {
  2356. if (lastShownArea === area) {
  2357. hideAllUtagsInArea()
  2358. return
  2359. }
  2360. lastShownArea = area
  2361. return
  2362. }
  2363. }
  2364. hideAllUtagsInArea()
  2365. lastShownArea = void 0
  2366. }
  2367. function bindDocumentEvents() {
  2368. const eventType = isTouchScreen() ? "touchstart" : "click"
  2369. addEventListener(
  2370. doc,
  2371. eventType,
  2372. (event) => {
  2373. const target = event.target
  2374. if (!target) {
  2375. return
  2376. }
  2377. if (target.closest(".utags_prompt")) {
  2378. return
  2379. }
  2380. if (target.closest(".utags_ul")) {
  2381. const captainTag = target.closest(
  2382. ".utags_captain_tag,.utags_captain_tag2"
  2383. )
  2384. const textTag = target.closest(".utags_text_tag")
  2385. if (captainTag) {
  2386. event.preventDefault()
  2387. event.stopPropagation()
  2388. event.stopImmediatePropagation()
  2389. if (!captainTag.dataset.utags_key || isPromptShown) {
  2390. return
  2391. }
  2392. isPromptShown = true
  2393. setTimeout(async () => {
  2394. const key = captainTag.dataset.utags_key
  2395. const tags = captainTag.dataset.utags_tags || ""
  2396. const meta = captainTag.dataset.utags_meta
  2397. ? JSON.parse(captainTag.dataset.utags_meta)
  2398. : void 0
  2399. const myPrompt = getSettingsValue("useSimplePrompt")
  2400. ? simplePrompt
  2401. : advancedPrompt
  2402. const newTags = await myPrompt(i2("prompt.addTags"), tags)
  2403. isPromptShown = false
  2404. captainTag.focus()
  2405. if (key && newTags != void 0) {
  2406. const emojiTags3 = await getEmojiTags()
  2407. const newTagsArray = sortTags(
  2408. filterTags(splitTags(newTags), TAG_VISITED),
  2409. emojiTags3
  2410. )
  2411. if (
  2412. tags.includes(TAG_VISITED) &&
  2413. !newTags.includes(TAG_VISITED)
  2414. ) {
  2415. removeVisited(key)
  2416. } else if (
  2417. !tags.includes(TAG_VISITED) &&
  2418. newTags.includes(TAG_VISITED)
  2419. ) {
  2420. addVisited(key)
  2421. }
  2422. await saveTags(key, newTagsArray, meta)
  2423. }
  2424. })
  2425. } else if (textTag) {
  2426. event.stopPropagation()
  2427. event.stopImmediatePropagation()
  2428. }
  2429. return
  2430. }
  2431. setTimeout(() => {
  2432. findElementToShowAllUtags(target)
  2433. }, 100)
  2434. },
  2435. true
  2436. )
  2437. addEventListener(
  2438. doc,
  2439. "keydown",
  2440. (event) => {
  2441. if (event.defaultPrevented) {
  2442. return
  2443. }
  2444. if (event.key === "Escape" && $(".utags_show_all")) {
  2445. hideAllUtagsInArea()
  2446. event.preventDefault()
  2447. }
  2448. },
  2449. true
  2450. )
  2451. addEventListener(
  2452. doc,
  2453. "mousedown",
  2454. (event) => {
  2455. const target = event.target
  2456. if (target == null ? void 0 : target.closest(".utags_ul")) {
  2457. event.preventDefault()
  2458. event.stopPropagation()
  2459. event.stopImmediatePropagation()
  2460. }
  2461. },
  2462. true
  2463. )
  2464. addEventListener(
  2465. doc,
  2466. "mouseup",
  2467. (event) => {
  2468. const target = event.target
  2469. if (target == null ? void 0 : target.closest(".utags_ul")) {
  2470. event.preventDefault()
  2471. event.stopPropagation()
  2472. event.stopImmediatePropagation()
  2473. }
  2474. },
  2475. true
  2476. )
  2477. }
  2478. function extendHistoryApi2() {
  2479. let url = location.href
  2480. setInterval(() => {
  2481. const url2 = location.href
  2482. if (url !== url2) {
  2483. url = url2
  2484. window.dispatchEvent(new Event("locationchange"))
  2485. }
  2486. }, 100)
  2487. }
  2488. function bindWindowEvents() {
  2489. extendHistoryApi()
  2490. extendHistoryApi2()
  2491. addEventListener(window, "locationchange", function () {
  2492. hideAllUtagsInArea()
  2493. })
  2494. }
  2495. var default_default =
  2496. ":not(#a):not(#b):not(#c) a+.utags_ul_0{object-position:100% 50%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-5);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-5);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) a+.utags_ul_1{object-position:0% 200%}"
  2497. var default_default2 = (() => {
  2498. return {
  2499. matches: /.*/,
  2500. matchedNodesSelectors: ["a[href]:not(.utags_text_tag)"],
  2501. validate(element) {
  2502. return true
  2503. },
  2504. excludeSelectors: [],
  2505. getCanonicalUrl: (url) =>
  2506. deleteUrlParameters(url, ["utm_campaign", "utm_source", "utm_medium"]),
  2507. getStyle: () => default_default,
  2508. }
  2509. })()
  2510. var v2ex_default =
  2511. ':not(#a):not(#b):not(#c) .header h1+.utags_ul_0{object-position:0% 200%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: 10px;--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-5)}:not(#a):not(#b):not(#c) .header h1+.utags_ul_0+.votes{margin-left:24px}:not(#a):not(#b):not(#c) .title .node-breadcrumb[data-utags_fit_content="1"]{display:inline-block !important;max-width:fit-content !important}:not(#a):not(#b):not(#c) .title .node-breadcrumb+.utags_ul_0{object-position:200% 50%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-5);--utags-notag-captain-tag-left: 2px;--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) .title .node-breadcrumb+.utags_ul_1{object-position:200% 50%;position:absolute;top:-9999px}:not(#a):not(#b):not(#c) .box .header>span[data-utags_flag=tag_page]+.utags_ul_0{object-position:200% 50%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-5);--utags-notag-captain-tag-left: 2px;--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) .box .header>span[data-utags_flag=tag_page]+.utags_ul_1{object-position:200% 50%;position:absolute;top:-9999px}'
  2512. var v2ex_default2 = (() => {
  2513. function getCanonicalUrl2(url) {
  2514. if (url.startsWith("https://links.pipecraft")) {
  2515. url = url.replace("https://links.pipecraft.net/", "https://")
  2516. }
  2517. if (url.includes("v2ex.com")) {
  2518. return url
  2519. .replace(/[?#].*/, "")
  2520. .replace(/(\w+\.)?v2ex.com/, "www.v2ex.com")
  2521. }
  2522. if (url.includes("v2ex.co")) {
  2523. return url
  2524. .replace(/[?#].*/, "")
  2525. .replace(/(\w+\.)?v2ex.co/, "www.v2ex.com")
  2526. }
  2527. return url
  2528. }
  2529. function cloneWithoutCitedReplies(element) {
  2530. const newElement = element.cloneNode(true)
  2531. for (const cell of $$(".cell", newElement)) {
  2532. cell.remove()
  2533. }
  2534. return newElement
  2535. }
  2536. return {
  2537. matches: /v2ex\.com|v2hot\.|v2ex\.co/,
  2538. preProcess() {
  2539. setVisitedAvailable(true)
  2540. setPrefix("https://www.v2ex.com/")
  2541. },
  2542. listNodesSelectors: [".box .cell", ".my-box .comment"],
  2543. conditionNodesSelectors: [
  2544. ".box .cell .topic-link",
  2545. ".item_hot_topic_title a",
  2546. '.box .cell .topic_info strong:first-of-type a[href*="/member/"]',
  2547. ".box .cell .topic_info .node",
  2548. '.box .cell strong a.dark[href*="/member/"]',
  2549. ".box .cell .ago a",
  2550. ".box .cell .fade.small a",
  2551. ".comment .username",
  2552. ".comment .ago",
  2553. ],
  2554. matchedNodesSelectors: [
  2555. 'a[href*="/t/"]',
  2556. 'a[href*="/member/"]',
  2557. 'a[href*="/go/"]',
  2558. 'a[href^="https://"]:not([href*="v2ex.com"])',
  2559. 'a[href^="http://"]:not([href*="v2ex.com"])',
  2560. ".box .cell .fr .tag",
  2561. ".box .inner .tag",
  2562. ],
  2563. excludeSelectors: [
  2564. ...default_default2.excludeSelectors,
  2565. ".site-nav a",
  2566. ".cell_tabs a",
  2567. ".tab-alt-container a",
  2568. "#SecondaryTabs a",
  2569. "a.page_normal,a.page_current",
  2570. "a.count_livid",
  2571. ".post-item a.post-content",
  2572. ],
  2573. addExtraMatchedNodes(matchedNodesSet) {
  2574. if (location.pathname.includes("/member/")) {
  2575. const profile = $(".content h1")
  2576. if (profile) {
  2577. const username = profile.textContent
  2578. if (username) {
  2579. const key = "https://www.v2ex.com/member/".concat(username)
  2580. const meta = { title: username, type: "user" }
  2581. profile.utags = { key, meta }
  2582. matchedNodesSet.add(profile)
  2583. }
  2584. }
  2585. }
  2586. if (location.pathname.includes("/t/")) {
  2587. const header = $(".header h1")
  2588. if (header) {
  2589. const key = getCanonicalUrl2(
  2590. "https://www.v2ex.com" + location.pathname
  2591. )
  2592. const title = $("h1").textContent
  2593. const meta = { title, type: "topic" }
  2594. header.utags = { key, meta }
  2595. matchedNodesSet.add(header)
  2596. addVisited(key)
  2597. markElementWhetherVisited(key, header)
  2598. }
  2599. const main2 = $("#Main") || $(".content")
  2600. const replyElements = $$(
  2601. '.box .cell[id^="r_"],.box .cell[id^="related_r_"]',
  2602. main2
  2603. )
  2604. for (const reply of replyElements) {
  2605. const replyId = reply.id.replace("related_", "")
  2606. const floorNoElement = $(".no", reply)
  2607. const replyContentElement = $(".reply_content", reply)
  2608. const agoElement = $(".ago,.fade.small", reply)
  2609. if (
  2610. replyId &&
  2611. floorNoElement &&
  2612. replyContentElement &&
  2613. agoElement
  2614. ) {
  2615. let newAgoElement = $("a", agoElement)
  2616. if (!newAgoElement) {
  2617. newAgoElement = createElement("a", {
  2618. textContent: agoElement.textContent,
  2619. href: "#" + replyId,
  2620. })
  2621. agoElement.textContent = ""
  2622. agoElement.append(newAgoElement)
  2623. }
  2624. const floorNo = parseInt10(floorNoElement.textContent, 1)
  2625. const pageNo = Math.floor((floorNo - 1) / 100) + 1
  2626. const key =
  2627. getCanonicalUrl2("https://www.v2ex.com" + location.pathname) +
  2628. "?p=" +
  2629. String(pageNo) +
  2630. "#" +
  2631. replyId
  2632. const title =
  2633. cloneWithoutCitedReplies(replyContentElement).textContent
  2634. const meta = { title, type: "reply" }
  2635. newAgoElement.utags = { key, meta }
  2636. matchedNodesSet.add(newAgoElement)
  2637. }
  2638. }
  2639. }
  2640. if (location.pathname.includes("/go/")) {
  2641. const header = $(".title .node-breadcrumb")
  2642. if (header) {
  2643. const key = getCanonicalUrl2(
  2644. "https://www.v2ex.com" + location.pathname
  2645. )
  2646. const title = header.textContent.replaceAll(/\s+/g, " ").trim()
  2647. const meta = { title, type: "node" }
  2648. header.utags = { key, meta }
  2649. matchedNodesSet.add(header)
  2650. }
  2651. }
  2652. if (location.pathname.includes("/tag/")) {
  2653. const header = $(".box .header > span")
  2654. if (header) {
  2655. const key = getCanonicalUrl2(
  2656. "https://www.v2ex.com" + location.pathname
  2657. )
  2658. const title = header.textContent.replaceAll(/\s+/g, " ").trim()
  2659. const meta = { title, type: "tag" }
  2660. header.utags = { key, meta }
  2661. header.dataset.utags_flag = "tag_page"
  2662. matchedNodesSet.add(header)
  2663. }
  2664. }
  2665. },
  2666. getStyle: () => v2ex_default,
  2667. getCanonicalUrl: getCanonicalUrl2,
  2668. postProcess() {
  2669. for (const element of $$('a[href*="/t/"]')) {
  2670. const key = getCanonicalUrl2(element.href)
  2671. markElementWhetherVisited(key, element)
  2672. }
  2673. },
  2674. }
  2675. })()
  2676. var greasyfork_org_default =
  2677. ":not(#a):not(#b):not(#c) .discussion-title+.utags_ul_0{display:block !important;height:0}:not(#a):not(#b):not(#c) .discussion-title+.utags_ul_0 .utags_captain_tag{top:-26px;background-color:rgba(255,255,255,.8666666667) !important}:not(#a):not(#b):not(#c) .discussion-title+.utags_ul_1{display:block !important;margin-top:-12px !important;margin-bottom:8px !important}:not(#a):not(#b):not(#c) .discussion-meta .script-link+.utags_ul_0{display:block !important;height:0}:not(#a):not(#b):not(#c) .discussion-meta .script-link+.utags_ul_0 .utags_captain_tag{top:-22px;background-color:rgba(255,255,255,.8666666667) !important}"
  2678. var greasyfork_org_default2 = (() => {
  2679. function getScriptUrl(url) {
  2680. return getCanonicalUrl2(url.replace(/(scripts\/\d+)(.*)/, "$1"))
  2681. }
  2682. function getCanonicalUrl2(url) {
  2683. if (/(greasyfork|sleazyfork)\.org/.test(url)) {
  2684. url = url.replace(
  2685. /((greasyfork|sleazyfork)\.org\/)(\w{2}(-\w{2})?)(\/|$)/,
  2686. "$1"
  2687. )
  2688. if (url.includes("/scripts/")) {
  2689. return url.replace(/(scripts\/\d+)([^/]*)/, "$1")
  2690. }
  2691. if (url.includes("/users/")) {
  2692. return url.replace(/(users\/\d+)(.*)/, "$1")
  2693. }
  2694. }
  2695. return url
  2696. }
  2697. return {
  2698. matches: /(greasyfork|sleazyfork)\.org/,
  2699. listNodesSelectors: [".script-list > li", ".discussion-list-container"],
  2700. conditionNodesSelectors: [
  2701. ".script-list li .script-link",
  2702. ".script-list li .script-list-author a",
  2703. ".discussion-list-container .script-link",
  2704. ".discussion-list-container .discussion-title",
  2705. ".discussion-list-container .discussion-meta-item:nth-child(2) > a",
  2706. ],
  2707. excludeSelectors: [
  2708. ...default_default2.excludeSelectors,
  2709. ".sidebar",
  2710. ".pagination",
  2711. ".sign-out-link,.sign-in-link",
  2712. ".with-submenu",
  2713. "#script-links.tabs",
  2714. "#install-area",
  2715. ".history_versions .version-number",
  2716. 'a[href*="show_all_versions"]',
  2717. 'a[href*="/reports/new"]',
  2718. 'a[href*="/conversations/new"]',
  2719. 'a[href*="/discussions/mark_all_read"]',
  2720. 'a[href*="/discussions/new"]',
  2721. "div.sidebarred-main-content > p:nth-child(3) > a",
  2722. ],
  2723. addExtraMatchedNodes(matchedNodesSet) {
  2724. if (location.pathname.includes("/scripts/")) {
  2725. const element = $("#script-info header h2")
  2726. if (element) {
  2727. const title = element.textContent
  2728. if (title) {
  2729. const key = getScriptUrl(location.href)
  2730. const meta = { title }
  2731. element.utags = { key, meta }
  2732. matchedNodesSet.add(element)
  2733. }
  2734. }
  2735. } else if (location.pathname.includes("/users/")) {
  2736. const element = $("#about-user h2")
  2737. if (element) {
  2738. const title = element.textContent
  2739. if (title) {
  2740. const key = getCanonicalUrl2(location.href)
  2741. const meta = { title }
  2742. element.utags = { key, meta }
  2743. matchedNodesSet.add(element)
  2744. }
  2745. }
  2746. }
  2747. },
  2748. getCanonicalUrl: getCanonicalUrl2,
  2749. getStyle: () => greasyfork_org_default,
  2750. }
  2751. })()
  2752. var news_ycombinator_com_default = (() => {
  2753. function cloneComment(element) {
  2754. const newElement = element.cloneNode(true)
  2755. for (const node of $$(".reply", newElement)) {
  2756. node.remove()
  2757. }
  2758. return newElement
  2759. }
  2760. return {
  2761. matches: /news\.ycombinator\.com/,
  2762. listNodesSelectors: [".script-list li", ".discussion-list-container"],
  2763. conditionNodesSelectors: [],
  2764. excludeSelectors: [
  2765. ...default_default2.excludeSelectors,
  2766. ".pagetop",
  2767. ".morelink",
  2768. ".hnpast",
  2769. ".clicky",
  2770. ".navs > a",
  2771. 'a[href^="login"]',
  2772. 'a[href^="logout"]',
  2773. 'a[href^="forgot"]',
  2774. 'a[href^="vote"]',
  2775. 'a[href^="submit"]',
  2776. 'a[href^="hide"]',
  2777. 'a[href^="fave"]',
  2778. 'a[href^="reply"]',
  2779. 'a[href^="context"]',
  2780. 'a[href^="newcomments"]',
  2781. 'a[href^="#"]',
  2782. '.subline > a[href^="item"]',
  2783. ],
  2784. addExtraMatchedNodes(matchedNodesSet) {
  2785. if (location.pathname === "/item") {
  2786. const comments = $$(".comment-tree .comtr[id]")
  2787. for (const comment of comments) {
  2788. const commentText = $(".commtext", comment)
  2789. const target = $(".age a", comment)
  2790. if (commentText && target) {
  2791. const key = target.href
  2792. const title = cloneComment(commentText).textContent
  2793. if (key && title) {
  2794. const meta = { title, type: "comment" }
  2795. target.utags = { key, meta }
  2796. matchedNodesSet.add(target)
  2797. }
  2798. }
  2799. }
  2800. const fatitem = $(".fatitem")
  2801. if (fatitem) {
  2802. const titleElement = $(".titleline a", fatitem)
  2803. const commentText = titleElement || $(".commtext", fatitem)
  2804. const type = titleElement ? "topic" : "comment"
  2805. const target = $(".age a", fatitem)
  2806. if (commentText && target) {
  2807. const key = target.href
  2808. const title = cloneComment(commentText).textContent
  2809. if (key && title) {
  2810. const meta = { title, type }
  2811. target.utags = { key, meta }
  2812. matchedNodesSet.add(target)
  2813. }
  2814. }
  2815. }
  2816. } else if (location.pathname === "/newcomments") {
  2817. const comments = $$(".athing[id]")
  2818. for (const comment of comments) {
  2819. const commentText = $(".commtext", comment)
  2820. const target = $(".age a", comment)
  2821. if (commentText && target) {
  2822. const key = target.href
  2823. const title = cloneComment(commentText).textContent
  2824. if (key && title) {
  2825. const meta = { title, type: "comment" }
  2826. target.utags = { key, meta }
  2827. matchedNodesSet.add(target)
  2828. }
  2829. }
  2830. }
  2831. } else {
  2832. const topics = $$(".athing[id]")
  2833. for (const topic of topics) {
  2834. const titleElement = $(".titleline a", topic)
  2835. const subtext = topic.nextElementSibling
  2836. if (subtext) {
  2837. const target = $(".age a", subtext)
  2838. if (titleElement && target) {
  2839. const key = target.href
  2840. const title = titleElement.textContent
  2841. if (key && title) {
  2842. const meta = { title, type: "topic" }
  2843. target.utags = { key, meta }
  2844. matchedNodesSet.add(target)
  2845. }
  2846. }
  2847. }
  2848. }
  2849. }
  2850. },
  2851. }
  2852. })()
  2853. var lobste_rs_default = (() => {
  2854. return {
  2855. matches:
  2856. /lobste\.rs|dto\.pipecraft\.net|tilde\.news|journalduhacker\.net/,
  2857. listNodesSelectors: [],
  2858. conditionNodesSelectors: [],
  2859. excludeSelectors: [
  2860. ...default_default2.excludeSelectors,
  2861. "#nav",
  2862. "#header",
  2863. "#subnav",
  2864. ".mobile_comments",
  2865. ".description_present",
  2866. ".morelink",
  2867. ".user_tree",
  2868. ".dropdown_parent",
  2869. 'a[href^="/login"]',
  2870. 'a[href^="/logout"]',
  2871. 'a[href^="/u#"]',
  2872. 'a[href$="/save"]',
  2873. 'a[href$="/hide"]',
  2874. 'a[href$="/suggest"]',
  2875. ],
  2876. }
  2877. })()
  2878. var github_com_default =
  2879. ':not(#a):not(#b):not(#c) .search-title .utags_ul_0,:not(#a):not(#b):not(#c) .d-flex.flex-justify-between a[href^="/topics/"]+.utags_ul_0,:not(#a):not(#b):not(#c) .d-md-flex.flex-justify-between a[href^="/topics/"].d-flex+.utags_ul_0,:not(#a):not(#b):not(#c) [id=user-starred-repos] a[href^="/topics/"].flex-items-center+.utags_ul_0,:not(#a):not(#b):not(#c) ul.f4 a[href^="/topics/"].d-flex+.utags_ul_0{--utags-notag-ul-disply: var(--utags-notag-ul-disply-4);--utags-notag-ul-height: var(--utags-notag-ul-height-4);--utags-notag-ul-position: var(--utags-notag-ul-position-4);--utags-notag-ul-top: var(--utags-notag-ul-top-4);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-4);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-4);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) .search-title .utags_ul_0{--utags-notag-captain-tag-top: -10px}:not(#a):not(#b):not(#c) .d-flex.flex-justify-between a[href^="/topics/"]+.utags_ul_0{--utags-notag-captain-tag-top: 6px;--utags-notag-captain-tag-left: 76px}:not(#a):not(#b):not(#c) .d-md-flex.flex-justify-between a[href^="/topics/"].d-flex+.utags_ul_0{--utags-notag-captain-tag-top: 20px;--utags-notag-captain-tag-left: 76px}:not(#a):not(#b):not(#c) ul.f4 a[href^="/topics/"].d-flex+.utags_ul_0{--utags-notag-captain-tag-top: -24px;--utags-notag-captain-tag-left: -2px}:not(#a):not(#b):not(#c) div[id=repo-title-component] strong[itemprop=name] a+.utags_ul_0{--utags-notag-ul-disply: var(--utags-notag-ul-disply-4);--utags-notag-ul-height: var(--utags-notag-ul-height-4);--utags-notag-ul-position: var(--utags-notag-ul-position-4);--utags-notag-ul-top: var(--utags-notag-ul-top-4);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-4);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-4)}'
  2880. var github_com_default2 = (() => {
  2881. const noneUsers = /* @__PURE__ */ new Set([
  2882. "about",
  2883. "pricing",
  2884. "security",
  2885. "login",
  2886. "logout",
  2887. "signup",
  2888. "explore",
  2889. "topics",
  2890. "trending",
  2891. "collections",
  2892. "events",
  2893. "sponsors",
  2894. "features",
  2895. "enterprise",
  2896. "team",
  2897. "customer-stories",
  2898. "readme",
  2899. "premium-support",
  2900. "sitemap",
  2901. "git-guides",
  2902. "open-source",
  2903. "marketplace",
  2904. "codespaces",
  2905. "issues",
  2906. "pulls",
  2907. "discussions",
  2908. "dashboard",
  2909. "account",
  2910. "new",
  2911. "notifications",
  2912. "settings",
  2913. "feedback",
  2914. "organizations",
  2915. "github-copilot",
  2916. "search",
  2917. ])
  2918. const prefix3 = "https://github.com/"
  2919. function getUserProfileUrl(href) {
  2920. if (href.startsWith(prefix3)) {
  2921. const href2 = href.slice(19)
  2922. let username = ""
  2923. if (/^[\w-]+$/.test(href2)) {
  2924. username = /^([\w-]+)$/.exec(href2)[1]
  2925. }
  2926. if (/(author%3A|author=)[\w-]+/.test(href2)) {
  2927. username = /(author%3A|author=)([\w-]+)/.exec(href2)[2]
  2928. }
  2929. if (username && !noneUsers.has(username)) {
  2930. return prefix3 + username
  2931. }
  2932. }
  2933. return void 0
  2934. }
  2935. function getRepoUrl(href) {
  2936. if (href.startsWith(prefix3)) {
  2937. const href2 = href.slice(19)
  2938. if (/^[\w-]+\/[\w-.]+(\?.*)?$/.test(href2)) {
  2939. const username = /^([\w-]+)/.exec(href2)[1]
  2940. if (username && !noneUsers.has(username)) {
  2941. return prefix3 + href2.replace(/(^[\w-]+\/[\w-.]+).*/, "$1")
  2942. }
  2943. }
  2944. }
  2945. return void 0
  2946. }
  2947. function getTopicsUrl(href) {
  2948. if (href.startsWith(prefix3)) {
  2949. const href2 = href.slice(19)
  2950. if (/^topics\/[\w-.]+(\?.*)?$/.test(href2)) {
  2951. return prefix3 + href2.replace(/(^topics\/[\w-.]+).*/, "$1")
  2952. }
  2953. }
  2954. return void 0
  2955. }
  2956. function getIssuesUrl(href) {
  2957. if (href.startsWith(prefix3)) {
  2958. const href2 = href.slice(19)
  2959. if (
  2960. /^[\w-]+\/[\w-.]+\/(issues|pull|discussions)\/\d+(\?.*)?$/.test(href2)
  2961. ) {
  2962. const username = /^([\w-]+)/.exec(href2)[1]
  2963. if (username && !noneUsers.has(username)) {
  2964. return (
  2965. prefix3 +
  2966. href2.replace(
  2967. /(^[\w-]+\/[\w-.]+\/(issues|pull|discussions)\/\d+).*/,
  2968. "$1"
  2969. )
  2970. )
  2971. }
  2972. }
  2973. }
  2974. return void 0
  2975. }
  2976. return {
  2977. matches: /github\.com/,
  2978. listNodesSelectors: [],
  2979. conditionNodesSelectors: [],
  2980. validate(element) {
  2981. const href = element.href
  2982. if (href.startsWith(prefix3)) {
  2983. if (/since|until/.test(href)) {
  2984. return false
  2985. }
  2986. let key = getUserProfileUrl(href)
  2987. if (key) {
  2988. const username = /^https:\/\/github\.com\/([\w-]+)$/.exec(key)[1]
  2989. const title = username
  2990. const meta = { title, type: "user" }
  2991. element.utags = { key, meta }
  2992. return true
  2993. }
  2994. key = getRepoUrl(href)
  2995. if (key) {
  2996. const title = key.replace(prefix3, "")
  2997. const meta = { title, type: "repo" }
  2998. element.utags = { key, meta }
  2999. return true
  3000. }
  3001. key = getTopicsUrl(href)
  3002. if (key) {
  3003. const text = element.textContent.trim()
  3004. if (text === "#") {
  3005. return false
  3006. }
  3007. const title = "#" + key.replace(prefix3 + "topics/", "")
  3008. const meta = { title, type: "topic" }
  3009. element.utags = { key, meta }
  3010. return true
  3011. }
  3012. key = getIssuesUrl(href)
  3013. if (key) {
  3014. const meta = { type: "issue" }
  3015. element.utags = { key, meta }
  3016. return true
  3017. }
  3018. return false
  3019. }
  3020. return true
  3021. },
  3022. excludeSelectors: [
  3023. ...default_default2.excludeSelectors,
  3024. 'section[aria-label~="User"] .Link--secondary',
  3025. ".Popover-message .Link--secondary",
  3026. ".IssueLabel",
  3027. ".subnav-links",
  3028. ".btn",
  3029. ".filter-item",
  3030. ".js-github-dev-shortcut",
  3031. ".js-github-dev-new-tab-shortcut",
  3032. ".js-skip-to-content",
  3033. ],
  3034. validMediaSelectors: ["svg.octicon-repo"],
  3035. getStyle: () => github_com_default,
  3036. }
  3037. })()
  3038. var reddit_com_default =
  3039. '\uFEFF#TOFIX_uFEFF{display:block}:not(#a):not(#b):not(#c) a+.utags_ul_0{object-position:200% 50%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-5);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-5);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) a+.utags_ul_1{object-position:0% 200%}:not(#a):not(#b):not(#c) shreddit-comment [slot=commentMeta]{position:relative}:not(#a):not(#b):not(#c) [data-testid=user-hover-card]{position:relative}:not(#a):not(#b):not(#c) div[slot=content]{position:relative}:not(#a):not(#b):not(#c) div[slot=comment]{position:relative}:not(#a):not(#b):not(#c) article:hover a[slot=title]+.utags_ul .utags_captain_tag,:not(#a):not(#b):not(#c) [slot=post-media-container]:hover a+.utags_ul .utags_captain_tag{opacity:100%;width:calc(var(--utags-captain-tag-size) + 8px) !important;height:calc(var(--utags-captain-tag-size) + 8px) !important;padding:5px 4px 4px 5px !important;transition:all 0s .1s !important;z-index:0}:not(#a):not(#b):not(#c) article a[slot=title][data-utags_fit_content="1"],:not(#a):not(#b):not(#c) recent-posts a[data-utags_fit_content="1"]{min-width:unset !important;width:fit-content !important}:not(#a):not(#b):not(#c) article a[slot=title][data-utags_fit_content="1"] *:not(svg),:not(#a):not(#b):not(#c) recent-posts a[data-utags_fit_content="1"] *:not(svg){width:fit-content !important}:not(#a):not(#b):not(#c) article a[slot=title]+.utags_ul_0,:not(#a):not(#b):not(#c) recent-posts a+.utags_ul_0{object-position:100% 50%}:not(#a):not(#b):not(#c) article a[slot=title]+.utags_ul_1,:not(#a):not(#b):not(#c) recent-posts a+.utags_ul_1{object-position:0% 200%;position:absolute;top:-9999px;margin-top:-4px !important;margin-left:0px !important}:not(#a):not(#b):not(#c) h1[slot=title][data-utags_fit_content="1"]{min-width:unset !important;width:fit-content !important}:not(#a):not(#b):not(#c) h1[slot=title][data-utags_fit_content="1"] *:not(svg){width:fit-content !important}:not(#a):not(#b):not(#c) h1[slot=title]+.utags_ul_0{object-position:200% 50%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-5);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-5);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) h1[slot=title]+.utags_ul_1{object-position:0% 200%;position:absolute;top:-9999px;margin-top:0px !important;margin-left:0px !important}:not(#a):not(#b):not(#c) [data-utags_list_node*=",hide,"],:not(#a):not(#b):not(#c) [data-utags_list_node*=",\u9690\u85CF,"],:not(#a):not(#b):not(#c) [data-utags_list_node*=",\u5C4F\u853D,"],:not(#a):not(#b):not(#c) [data-utags_list_node*=",\u4E0D\u518D\u663E\u793A,"],:not(#a):not(#b):not(#c) [data-utags_list_node*=",block,"]{opacity:1%;display:block !important}'
  3040. var reddit_com_default2 = (() => {
  3041. const prefix3 = "https://www.reddit.com/"
  3042. function getCanonicalUrl2(url) {
  3043. if (url.startsWith(prefix3)) {
  3044. let href2 = getUserProfileUrl(url, true)
  3045. if (href2) {
  3046. return href2
  3047. }
  3048. href2 = getCommunityUrl(url, true)
  3049. if (href2) {
  3050. return href2
  3051. }
  3052. href2 = getCommentsUrl(url, true)
  3053. if (href2) {
  3054. return href2
  3055. }
  3056. }
  3057. return url
  3058. }
  3059. function getUserProfileUrl(url, exact = false) {
  3060. if (url.startsWith(prefix3)) {
  3061. const href2 = url.slice(prefix3.length)
  3062. if (exact) {
  3063. if (/^(user|u)\/[\w-]+\/?([?#].*)?$/.test(href2)) {
  3064. return (
  3065. prefix3 +
  3066. "user/" +
  3067. href2.replace(/^(user|u)\/([\w-]+).*/, "$2") +
  3068. "/"
  3069. )
  3070. }
  3071. } else if (/^(user|u)\/[\w-]+/.test(href2)) {
  3072. return (
  3073. prefix3 +
  3074. "user/" +
  3075. href2.replace(/^(user|u)\/([\w-]+).*/, "$2") +
  3076. "/"
  3077. )
  3078. }
  3079. }
  3080. return void 0
  3081. }
  3082. function getCommunityUrl(url, exact = false) {
  3083. if (url.startsWith(prefix3)) {
  3084. const href2 = url.slice(prefix3.length)
  3085. if (exact) {
  3086. if (/^r\/\w+\/?(#.*)?$/.test(href2)) {
  3087. return prefix3 + href2.replace(/^(r\/\w+).*/, "$1") + "/"
  3088. }
  3089. } else if (/^r\/\w+/.test(href2)) {
  3090. return prefix3 + href2.replace(/^(r\/\w+).*/, "$1") + "/"
  3091. }
  3092. }
  3093. return void 0
  3094. }
  3095. function getCommentsUrl(url, exact = false) {
  3096. if (url.startsWith(prefix3)) {
  3097. const href2 = url.slice(prefix3.length)
  3098. if (exact) {
  3099. if (/^(r\/\w+\/comments\/\w+(\/([^/]*\/?)?)?)$/.test(href2)) {
  3100. return (
  3101. prefix3 +
  3102. href2.replace(/^(r\/\w+\/comments\/\w+(\/([^/]*)?)?).*/, "$1") +
  3103. "/"
  3104. )
  3105. }
  3106. } else if (/^(r\/\w+\/comments\/\w+(\/([^/]*)?)?).*/.test(href2)) {
  3107. return (
  3108. prefix3 +
  3109. href2.replace(/^(r\/\w+\/comments\/\w+(\/([^/]*)?)?).*/, "$1") +
  3110. "/"
  3111. )
  3112. }
  3113. }
  3114. return void 0
  3115. }
  3116. return {
  3117. matches: /reddit\.com/,
  3118. listNodesSelectors: [
  3119. "shreddit-feed article",
  3120. "shreddit-feed shreddit-ad-post",
  3121. "shreddit-comment",
  3122. ],
  3123. conditionNodesSelectors: [
  3124. 'shreddit-feed article a[data-testid="subreddit-name"]',
  3125. 'shreddit-feed article a[slot="title"]',
  3126. 'shreddit-feed article [slot="authorName"] a',
  3127. "shreddit-feed shreddit-ad-post a",
  3128. "shreddit-comment faceplate-hovercard a",
  3129. ],
  3130. validate(element) {
  3131. const href = element.href
  3132. if (!href.startsWith(prefix3)) {
  3133. return true
  3134. }
  3135. if ($("time,faceplate-number", element)) {
  3136. return false
  3137. }
  3138. let key = getUserProfileUrl(href, true)
  3139. if (key) {
  3140. const title = element.textContent.trim()
  3141. if (!title) {
  3142. return false
  3143. }
  3144. const meta = { type: "user", title }
  3145. element.utags = { key, meta }
  3146. element.dataset.utags = element.dataset.utags || ""
  3147. return true
  3148. }
  3149. key = getCommunityUrl(href, true)
  3150. if (key) {
  3151. const title = element.textContent.trim()
  3152. if (!title) {
  3153. return false
  3154. }
  3155. const meta = { type: "community", title }
  3156. element.utags = { key, meta }
  3157. element.dataset.utags = element.dataset.utags || ""
  3158. return true
  3159. }
  3160. key = getCommentsUrl(href, true)
  3161. if (key) {
  3162. const title = element.textContent.trim()
  3163. if (!title) {
  3164. return false
  3165. }
  3166. const meta = { type: "comments", title }
  3167. element.utags = { key, meta }
  3168. element.dataset.utags = element.dataset.utags || ""
  3169. return true
  3170. }
  3171. return true
  3172. },
  3173. excludeSelectors: [
  3174. ...default_default2.excludeSelectors,
  3175. 'a[data-testid="comment_author_icon"]',
  3176. "#shreddit-skip-link",
  3177. 'a[slot="text-body"]',
  3178. 'a[slot="full-post-link"]',
  3179. '[slot="post-media-container"] a.inset-0',
  3180. '[bundlename="shreddit_sort_dropdown"]',
  3181. '[slot="tabs"]',
  3182. ],
  3183. addExtraMatchedNodes(matchedNodesSet) {
  3184. let element = $('[data-testid="profile-main"] .w-full p')
  3185. if (element) {
  3186. const title = element.textContent.trim()
  3187. const key = getUserProfileUrl(location.href)
  3188. if (title && key) {
  3189. const meta = { title, type: "user" }
  3190. element.utags = { key, meta }
  3191. matchedNodesSet.add(element)
  3192. }
  3193. }
  3194. element = $(".w-full h1")
  3195. if (element) {
  3196. const title = element.textContent.trim()
  3197. const key = getCommunityUrl(location.href)
  3198. if (title && key) {
  3199. const meta = { title, type: "community" }
  3200. element.utags = { key, meta }
  3201. matchedNodesSet.add(element)
  3202. }
  3203. }
  3204. element = $('h1[slot="title"]')
  3205. if (element) {
  3206. const title = element.textContent.trim()
  3207. const key = getCommentsUrl(location.href, true)
  3208. if (title && key) {
  3209. const meta = { title, type: "comments" }
  3210. element.utags = { key, meta }
  3211. matchedNodesSet.add(element)
  3212. }
  3213. }
  3214. },
  3215. getStyle: () => reddit_com_default,
  3216. postProcess() {
  3217. setTimeout(() => {
  3218. for (const element of $$(
  3219. '[data-utags_list_node*=",hide,"],\n [data-utags_list_node*=",\u9690\u85CF,"],\n [data-utags_list_node*=",\u5C4F\u853D,"],\n [data-utags_list_node*=",\u4E0D\u518D\u663E\u793A,"],\n [data-utags_list_node*=",block,"]'
  3220. )) {
  3221. element.setAttribute("collapsed", "")
  3222. }
  3223. }, 1e3)
  3224. },
  3225. getCanonicalUrl: getCanonicalUrl2,
  3226. }
  3227. })()
  3228. var twitter_com_default =
  3229. ":not(#a):not(#b):not(#c) a+.utags_ul_0{object-position:200% 50%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-5);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-5);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) .css-175oi2r.r-xoduu5:hover{z-index:2 !important}:not(#a):not(#b):not(#c) [data-testid=User-Name]:hover .utags_ul .utags_captain_tag,:not(#a):not(#b):not(#c) [data-testid=HoverCard]:hover .utags_ul .utags_captain_tag,:not(#a):not(#b):not(#c) [data-testid=UserCell]:hover .utags_ul .utags_captain_tag{opacity:100%;width:calc(var(--utags-captain-tag-size) + 8px) !important;height:calc(var(--utags-captain-tag-size) + 8px) !important;padding:5px 4px 4px 5px !important;transition:all 0s .1s !important;z-index:0}"
  3230. var twitter_com_default2 = (() => {
  3231. const prefix3 = "https://x.com/"
  3232. const prefix22 = "https://twitter.com/"
  3233. return {
  3234. matches: /x\.com|twitter\.com/,
  3235. listNodesSelectors: ['[data-testid="cellInnerDiv"]'],
  3236. conditionNodesSelectors: [
  3237. '[data-testid="cellInnerDiv"] [data-testid="User-Name"] a',
  3238. ],
  3239. validate(element) {
  3240. const href = element.href
  3241. if (href.startsWith(prefix3) || href.startsWith(prefix22)) {
  3242. const href2 = href.startsWith(prefix22)
  3243. ? href.slice(20)
  3244. : href.slice(14)
  3245. if (/^\w+$/.test(href2)) {
  3246. if (
  3247. /^(home|explore|notifications|messages|tos|privacy)$/.test(href2)
  3248. ) {
  3249. return false
  3250. }
  3251. const textContent = element.textContent || ""
  3252. if (!textContent.startsWith("@")) {
  3253. return false
  3254. }
  3255. const parent = element.parentElement
  3256. setStyle(parent, { zIndex: "1" })
  3257. const meta = { type: "user" }
  3258. element.utags = { meta }
  3259. return true
  3260. }
  3261. }
  3262. return false
  3263. },
  3264. addExtraMatchedNodes(matchedNodesSet) {
  3265. const elements = $$('[data-testid="UserName"] span')
  3266. for (const element of elements) {
  3267. const title = element.textContent.trim()
  3268. if (!title || !title.startsWith("@")) {
  3269. continue
  3270. }
  3271. const key = prefix3 + title.slice(1)
  3272. const meta = { title, type: "user" }
  3273. element.utags = { key, meta }
  3274. matchedNodesSet.add(element)
  3275. }
  3276. },
  3277. getStyle: () => twitter_com_default,
  3278. }
  3279. })()
  3280. var mp_weixin_qq_com_default = (() => {
  3281. function getCanonicalUrl2(url) {
  3282. if (url.startsWith("http://mp.weixin.qq.com")) {
  3283. url = url.replace(/^http:/, "https:")
  3284. }
  3285. if (url.startsWith("https://mp.weixin.qq.com/s/")) {
  3286. url = url.replace(/(\/s\/[\w-]+).*/, "$1")
  3287. }
  3288. if (url.startsWith("https://mp.weixin.qq.com/") && url.includes("#")) {
  3289. url = url.replace(/#.*/, "")
  3290. }
  3291. return url
  3292. }
  3293. return {
  3294. matches: /mp\.weixin\.qq\.com/,
  3295. addExtraMatchedNodes(matchedNodesSet) {
  3296. const element = $("h1.rich_media_title")
  3297. if (element) {
  3298. const title = element.textContent.trim()
  3299. if (title) {
  3300. const key = getCanonicalUrl2(location.href)
  3301. const meta = { title }
  3302. element.utags = { key, meta }
  3303. matchedNodesSet.add(element)
  3304. }
  3305. }
  3306. },
  3307. getCanonicalUrl: getCanonicalUrl2,
  3308. }
  3309. })()
  3310. var instagram_com_default =
  3311. ":not(#a):not(#b):not(#c) [data-utags_node_type=notag_relative]+.utags_ul_0 .utags_captain_tag{position:relative !important;width:14px !important;height:14px !important;padding:1px 0 0 1px !important}"
  3312. var instagram_com_default2 = (() => {
  3313. return {
  3314. matches: /instagram\.com/,
  3315. validate(element) {
  3316. const href = element.href
  3317. if (href.startsWith("https://www.instagram.com/")) {
  3318. const href2 = href.slice(26)
  3319. if (/^[\w.]+\/$/.test(href2)) {
  3320. if (/^(explore|reels)\/$/.test(href2)) {
  3321. return false
  3322. }
  3323. if ($("div span", element)) {
  3324. element.dataset.utags_node_type = "notag_relative"
  3325. }
  3326. const meta = { type: "user" }
  3327. element.utags = { meta }
  3328. return true
  3329. }
  3330. }
  3331. return false
  3332. },
  3333. excludeSelectors: [...default_default2.excludeSelectors],
  3334. getStyle: () => instagram_com_default,
  3335. }
  3336. })()
  3337. var threads_net_default =
  3338. ':not(#a):not(#b):not(#c) a[href^="/@"][data-utags]+.utags_ul_0{--utags-notag-ul-disply: var(--utags-notag-ul-disply-4);--utags-notag-ul-height: var(--utags-notag-ul-height-4);--utags-notag-ul-position: var(--utags-notag-ul-position-4);--utags-notag-ul-top: var(--utags-notag-ul-top-4);--utags-notag-captain-tag-top: -22px;--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-4)}'
  3339. var threads_net_default2 = (() => {
  3340. function getUserProfileUrl(url) {
  3341. if (url.startsWith("https://www.threads.net/")) {
  3342. const href2 = url.slice(24)
  3343. if (/^@[\w.]+/.test(href2)) {
  3344. return (
  3345. "https://www.threads.net/" +
  3346. href2.replace(/(^@[\w.]+).*/, "$1").toLowerCase()
  3347. )
  3348. }
  3349. }
  3350. return void 0
  3351. }
  3352. return {
  3353. matches: /threads\.net/,
  3354. validate(element) {
  3355. const href = element.href
  3356. if (href.startsWith("https://www.threads.net/")) {
  3357. const href2 = href.slice(24)
  3358. if (/^@[\w.]+$/.test(href2)) {
  3359. const meta = { type: "user" }
  3360. element.utags = { meta }
  3361. return true
  3362. }
  3363. }
  3364. return false
  3365. },
  3366. excludeSelectors: [
  3367. ...default_default2.excludeSelectors,
  3368. '[role="tablist"]',
  3369. ],
  3370. addExtraMatchedNodes(matchedNodesSet) {
  3371. const element = $("h1+div>div>span,h2+div>div>span")
  3372. if (element) {
  3373. const title = element.textContent.trim()
  3374. const key = getUserProfileUrl(location.href)
  3375. if (title && key && key === "https://www.threads.net/@" + title) {
  3376. const meta = { title, type: "user" }
  3377. element.utags = { key, meta }
  3378. matchedNodesSet.add(element)
  3379. }
  3380. }
  3381. },
  3382. getStyle: () => threads_net_default,
  3383. }
  3384. })()
  3385. var facebook_com_default =
  3386. ":not(#a):not(#b):not(#c) a[data-utags_flag=username_with_avatar]+.utags_ul_0{object-position:0% 100%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: -2px;--utags-notag-captain-tag-left: 0px;--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) h1+ul.utags_ul{margin-bottom:16px !important;display:inline-flex !important}"
  3387. var facebook_com_default2 = (() => {
  3388. const prefix3 = location.origin + "/"
  3389. function getUserProfileUrl(href, exact = false) {
  3390. if (href.startsWith(prefix3)) {
  3391. const href2 = href.slice(prefix3.length).toLowerCase()
  3392. if (href2.startsWith("profile.php")) {
  3393. const parameters = getUrlParameters(href, ["id", "sk"])
  3394. if (parameters.id && !parameters.sk) {
  3395. return "https://www.facebook.com/profile.php?id=" + parameters.id
  3396. }
  3397. } else if (/^\d+\/?([?#].*)?$/.test(href2)) {
  3398. return (
  3399. "https://www.facebook.com/profile.php?id=" +
  3400. href2.replace(/^(\d+).*/, "$1")
  3401. )
  3402. } else if (/^messages\/t\/\d+\/?([?#].*)?$/.test(href2)) {
  3403. return (
  3404. "https://www.facebook.com/profile.php?id=" +
  3405. href2.replace(/^messages\/t\/(\d+).*/, "$1")
  3406. )
  3407. } else if (
  3408. href2.startsWith("friends/requests/?profile_id=") ||
  3409. href2.startsWith("friends/suggestions/?profile_id=")
  3410. ) {
  3411. const parameters = getUrlParameters(href, ["profile_id"])
  3412. if (parameters.profile_id) {
  3413. return (
  3414. "https://www.facebook.com/profile.php?id=" + parameters.profile_id
  3415. )
  3416. }
  3417. } else if (
  3418. ((exact && /^[\w.]+([?#].*)?$/.test(href2)) ||
  3419. (!exact && /^[\w.]+/.test(href2))) &&
  3420. !/^(policies|events|ads|business|privacy|help|friends|messages|profile\.php|permalink\.php|photo\.php|\w+\.php)\b/.test(
  3421. href2
  3422. )
  3423. ) {
  3424. return (
  3425. "https://www.facebook.com/" + href2.replace(/(^[\w.]+).*/, "$1")
  3426. )
  3427. }
  3428. }
  3429. return void 0
  3430. }
  3431. return {
  3432. matches: /^(www|m)\.facebook\.com$/,
  3433. validate(element) {
  3434. const href = element.href
  3435. if (
  3436. !href.startsWith("https://www.facebook.com/") &&
  3437. !href.startsWith("https://m.facebook.com/") &&
  3438. !href.startsWith("https://l.facebook.com/")
  3439. ) {
  3440. return true
  3441. }
  3442. const key = getUserProfileUrl(href, true)
  3443. if (key) {
  3444. const title = element.textContent.trim()
  3445. if (!title) {
  3446. return false
  3447. }
  3448. if ($("svg,img", element)) {
  3449. element.dataset.utags_flag = "username_with_avatar"
  3450. }
  3451. const meta = { type: "user", title }
  3452. element.utags = { key, meta }
  3453. element.dataset.utags = element.dataset.utags || ""
  3454. return true
  3455. }
  3456. return false
  3457. },
  3458. excludeSelectors: [
  3459. ...default_default2.excludeSelectors,
  3460. 'div[data-pagelet="ProfileTabs"]',
  3461. ],
  3462. addExtraMatchedNodes(matchedNodesSet) {
  3463. const element = getFirstHeadElement('div[role="main"] h1')
  3464. if (element) {
  3465. const title = element.textContent.trim()
  3466. const key = getUserProfileUrl(location.href)
  3467. if (title && key) {
  3468. const meta = { title, type: "user" }
  3469. element.utags = { key, meta }
  3470. matchedNodesSet.add(element)
  3471. }
  3472. }
  3473. },
  3474. getStyle: () => facebook_com_default,
  3475. }
  3476. })()
  3477. var youtube_com_default =
  3478. ":not(#a):not(#b):not(#c) ytd-rich-item-renderer h3.ytd-rich-grid-media .utags_ul_0{--utags-notag-ul-disply: var(--utags-notag-ul-disply-2);--utags-notag-ul-height: var(--utags-notag-ul-height-2);--utags-notag-ul-position: var(--utags-notag-ul-position-2);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-2);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-2);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) ytd-rich-item-renderer yt-formatted-string[ellipsis-truncate-styling] .utags_ul_0 .utags_captain_tag{left:-20px}:not(#a):not(#b):not(#c) ytd-video-renderer.ytd-item-section-renderer h3 .utags_ul_0,:not(#a):not(#b):not(#c) ytd-video-renderer.ytd-vertical-list-renderer h3 .utags_ul_0{--utags-notag-ul-disply: var(--utags-notag-ul-disply-2);--utags-notag-ul-height: var(--utags-notag-ul-height-2);--utags-notag-ul-position: var(--utags-notag-ul-position-2);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-2);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-2);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) ytd-video-renderer.ytd-item-section-renderer yt-formatted-string.ytd-channel-name .utags_ul_0 .utags_captain_tag,:not(#a):not(#b):not(#c) ytd-video-renderer.ytd-vertical-list-renderer yt-formatted-string.ytd-channel-name .utags_ul_0 .utags_captain_tag{left:-20px}:not(#a):not(#b):not(#c) .watch-active-metadata ytd-channel-name yt-formatted-string .utags_ul_0,:not(#a):not(#b):not(#c) ytd-comment-thread-renderer h3.ytd-comment-renderer .utags_ul_0{--utags-notag-ul-disply: var(--utags-notag-ul-disply-2);--utags-notag-ul-height: var(--utags-notag-ul-height-2);--utags-notag-ul-position: var(--utags-notag-ul-position-2);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-2);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-2);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) .ytd-shorts ytd-reel-video-renderer ytd-channel-name yt-formatted-string .utags_ul_0 .utags_captain_tag{left:-24px}:not(#a):not(#b):not(#c) [hidden]+.utags_ul{display:none !important}"
  3479. var youtube_com_default2 = (() => {
  3480. const prefix3 = "https://www.youtube.com/"
  3481. const prefix22 = "https://m.youtube.com/"
  3482. function getUserProfileUrl(href) {
  3483. if (href.startsWith(prefix3) || href.startsWith(prefix22)) {
  3484. const href2 = href.startsWith(prefix22)
  3485. ? href.slice(22)
  3486. : href.slice(24)
  3487. if (/^@[\w-]+/.test(href2)) {
  3488. return prefix3 + href2.replace(/(^@[\w-]+).*/, "$1")
  3489. }
  3490. if (/^channel\/[\w-]+/.test(href2)) {
  3491. return prefix3 + href2.replace(/(^channel\/[\w-]+).*/, "$1")
  3492. }
  3493. }
  3494. return void 0
  3495. }
  3496. function getVideoUrl(href) {
  3497. if (href.startsWith(prefix3) || href.startsWith(prefix22)) {
  3498. const href2 = href.startsWith(prefix22)
  3499. ? href.slice(22)
  3500. : href.slice(24)
  3501. if (href2.includes("&lc=")) {
  3502. return void 0
  3503. }
  3504. if (/^watch\?v=[\w-]+/.test(href2)) {
  3505. return prefix3 + href2.replace(/(watch\?v=[\w-]+).*/, "$1")
  3506. }
  3507. if (/^shorts\/[\w-]+/.test(href2)) {
  3508. return prefix3 + href2.replace(/(^shorts\/[\w-]+).*/, "$1")
  3509. }
  3510. }
  3511. return void 0
  3512. }
  3513. return {
  3514. matches: /youtube\.com/,
  3515. validate(element) {
  3516. const hrefAttr = getAttribute(element, "href")
  3517. if (!hrefAttr || hrefAttr === "null" || hrefAttr === "#") {
  3518. return false
  3519. }
  3520. const href = element.href
  3521. if (href.startsWith(prefix3) || href.startsWith(prefix22)) {
  3522. const pathname = element.pathname
  3523. if (/^\/@[\w-]+$/.test(pathname)) {
  3524. const key2 = prefix3 + pathname.slice(1)
  3525. const meta = { type: "user" }
  3526. element.utags = { key: key2, meta }
  3527. return true
  3528. }
  3529. if (/^\/channel\/[\w-]+$/.test(pathname)) {
  3530. const key2 = prefix3 + pathname.slice(1)
  3531. const meta = { type: "channel" }
  3532. element.utags = { key: key2, meta }
  3533. return true
  3534. }
  3535. const key = getVideoUrl(href)
  3536. if (key) {
  3537. let title
  3538. const titleElement = $("#video-title", element)
  3539. if (titleElement) {
  3540. title = titleElement.textContent
  3541. }
  3542. const meta = title ? { title, type: "video" } : { type: "video" }
  3543. element.utags = { key, meta }
  3544. return true
  3545. }
  3546. }
  3547. return false
  3548. },
  3549. excludeSelectors: [...default_default2.excludeSelectors],
  3550. addExtraMatchedNodes(matchedNodesSet) {
  3551. let key = getUserProfileUrl(location.href)
  3552. if (key) {
  3553. const element = $(
  3554. "#inner-header-container #container.ytd-channel-name #text"
  3555. )
  3556. if (element) {
  3557. const title = element.textContent.trim()
  3558. if (title) {
  3559. const meta = { title }
  3560. element.utags = { key, meta }
  3561. matchedNodesSet.add(element)
  3562. }
  3563. }
  3564. }
  3565. key = getVideoUrl(location.href)
  3566. if (key) {
  3567. const element = $(
  3568. "#title h1.ytd-watch-metadata,ytd-reel-video-renderer[is-active] h2.title"
  3569. )
  3570. if (element) {
  3571. const title = element.textContent.trim()
  3572. if (title) {
  3573. const meta = { title, type: "video" }
  3574. element.utags = { key, meta }
  3575. matchedNodesSet.add(element)
  3576. }
  3577. }
  3578. }
  3579. },
  3580. getStyle: () => youtube_com_default,
  3581. }
  3582. })()
  3583. var bilibili_com_default =
  3584. ':not(#a):not(#b):not(#c) .bili-video-card__info--right a[href*="/video/"]+.utags_ul_0,:not(#a):not(#b):not(#c) .bili-video-card__info--right h3.bili-video-card__info--tit+.utags_ul_0,:not(#a):not(#b):not(#c) .video-page-card-small a[href*="/video/"]+.utags_ul_0,:not(#a):not(#b):not(#c) .video-page-card-small h3.bili-video-card__info--tit+.utags_ul_0,:not(#a):not(#b):not(#c) .video-page-operator-card-small a[href*="/video/"]+.utags_ul_0,:not(#a):not(#b):not(#c) .video-page-operator-card-small h3.bili-video-card__info--tit+.utags_ul_0{display:block !important;height:0}:not(#a):not(#b):not(#c) .bili-video-card__info--right a[href*="/video/"]+.utags_ul_0 .utags_captain_tag,:not(#a):not(#b):not(#c) .bili-video-card__info--right h3.bili-video-card__info--tit+.utags_ul_0 .utags_captain_tag,:not(#a):not(#b):not(#c) .video-page-card-small a[href*="/video/"]+.utags_ul_0 .utags_captain_tag,:not(#a):not(#b):not(#c) .video-page-card-small h3.bili-video-card__info--tit+.utags_ul_0 .utags_captain_tag,:not(#a):not(#b):not(#c) .video-page-operator-card-small a[href*="/video/"]+.utags_ul_0 .utags_captain_tag,:not(#a):not(#b):not(#c) .video-page-operator-card-small h3.bili-video-card__info--tit+.utags_ul_0 .utags_captain_tag{top:-22px;background-color:rgba(255,255,255,.8666666667) !important}'
  3585. var bilibili_com_default2 = (() => {
  3586. const prefix3 = "https://www.bilibili.com/"
  3587. const prefix22 = "https://space.bilibili.com/"
  3588. const prefix32 = "https://m.bilibili.com/"
  3589. function getUserProfileUrl(href) {
  3590. if (href.startsWith(prefix22)) {
  3591. const href2 = href.slice(27)
  3592. if (/^\d+/.test(href2)) {
  3593. return prefix22 + href2.replace(/(^\d+).*/, "$1")
  3594. }
  3595. }
  3596. if (href.startsWith(prefix32 + "space/")) {
  3597. const href2 = href.slice(29)
  3598. if (/^\d+/.test(href2)) {
  3599. return prefix22 + href2.replace(/(^\d+).*/, "$1")
  3600. }
  3601. }
  3602. return void 0
  3603. }
  3604. function getVideoUrl(href) {
  3605. if (
  3606. href.startsWith(prefix3 + "video/") ||
  3607. href.startsWith(prefix32 + "video/")
  3608. ) {
  3609. const href2 = href.startsWith(prefix32)
  3610. ? href.slice(23)
  3611. : href.slice(25)
  3612. if (/^video\/\w+/.test(href2)) {
  3613. return prefix3 + href2.replace(/^(video\/\w+).*/, "$1")
  3614. }
  3615. }
  3616. return void 0
  3617. }
  3618. return {
  3619. matches: /bilibili\.com|biligame\.com/,
  3620. excludeSelectors: ["*"],
  3621. addExtraMatchedNodes(matchedNodesSet) {
  3622. if (location.href.startsWith(prefix3 + "video/")) {
  3623. if ($(".bpx-state-loading")) {
  3624. return
  3625. }
  3626. const img = $(".bpx-player-follow-face")
  3627. const img2 = $("img.video-capture-img")
  3628. if (
  3629. !(img == null ? void 0 : img.src) ||
  3630. !(img2 == null ? void 0 : img2.src)
  3631. ) {
  3632. return
  3633. }
  3634. }
  3635. const elements = $$(
  3636. ".user-name[data-user-id],.sub-user-name[data-user-id],.jump-link.user[data-user-id]"
  3637. )
  3638. for (const element2 of elements) {
  3639. const userId = element2.dataset.userId
  3640. if (!userId) {
  3641. return false
  3642. }
  3643. const title = element2.textContent.trim()
  3644. const key = prefix22 + userId
  3645. const meta = { title, type: "user" }
  3646. element2.utags = { key, meta }
  3647. element2.dataset.utags_node_type = "link"
  3648. matchedNodesSet.add(element2)
  3649. }
  3650. const elements2 = $$(".upname a,a.bili-video-card__info--owner")
  3651. for (const element2 of elements2) {
  3652. const href = element2.href
  3653. if (href.startsWith(prefix22)) {
  3654. const key = getUserProfileUrl(href)
  3655. if (key) {
  3656. const nameElement = $(
  3657. ".name,.bili-video-card__info--author",
  3658. element2
  3659. )
  3660. if (nameElement) {
  3661. const title = nameElement.textContent
  3662. const meta = { title, type: "user" }
  3663. nameElement.utags = { key, meta }
  3664. nameElement.dataset.utags_node_type = "link"
  3665. matchedNodesSet.add(nameElement)
  3666. }
  3667. }
  3668. }
  3669. }
  3670. const elements3 = $$(
  3671. [
  3672. "a.up-name",
  3673. "a.card-user-name",
  3674. ".usercard-wrap .user .name",
  3675. ".comment-list .user .name",
  3676. ".user-card .user .name",
  3677. "a[data-usercard-mid]",
  3678. "a.user-name",
  3679. ".user-name a",
  3680. 'a[href^="https://space.bilibili.com/"]',
  3681. "a.staff-name",
  3682. ].join(",")
  3683. )
  3684. for (const element2 of elements3) {
  3685. const href = element2.href
  3686. if (href.startsWith(prefix22)) {
  3687. const key = getUserProfileUrl(href)
  3688. if (key) {
  3689. let title = element2.textContent.trim()
  3690. if (title) {
  3691. title = title.replace(/^@/, "")
  3692. const meta = { title, type: "user" }
  3693. element2.utags = { key, meta }
  3694. matchedNodesSet.add(element2)
  3695. }
  3696. }
  3697. }
  3698. }
  3699. if (
  3700. location.href.startsWith(prefix22) ||
  3701. location.href.startsWith(prefix32 + "space/")
  3702. ) {
  3703. const element2 = $("#h-name,.m-space-info .name")
  3704. if (element2) {
  3705. const title = element2.textContent.trim()
  3706. const key = getUserProfileUrl(location.href)
  3707. if (title && key) {
  3708. const meta = { title, type: "user" }
  3709. element2.utags = { key, meta }
  3710. matchedNodesSet.add(element2)
  3711. }
  3712. }
  3713. }
  3714. const element = $("h1.video-title,h1.title-text")
  3715. if (element) {
  3716. const title = element.textContent.trim()
  3717. const key = getVideoUrl(location.href)
  3718. if (title && key) {
  3719. const meta = { title, type: "video" }
  3720. element.utags = { key, meta }
  3721. matchedNodesSet.add(element)
  3722. }
  3723. }
  3724. const elements4 = $$(
  3725. ".bili-video-card__info--right a,.video-page-card-small .info a,.video-page-operator-card-small .info a"
  3726. )
  3727. for (const element2 of elements4) {
  3728. const key = getVideoUrl(element2.href)
  3729. if (key) {
  3730. const title = element2.textContent.trim()
  3731. const target =
  3732. element2.parentElement.tagName === "H3"
  3733. ? element2.parentElement
  3734. : element2
  3735. if (title) {
  3736. const meta = { title, type: "video" }
  3737. target.utags = { key, meta }
  3738. target.dataset.utags_node_type = "link"
  3739. matchedNodesSet.add(target)
  3740. }
  3741. }
  3742. }
  3743. },
  3744. getStyle: () => bilibili_com_default,
  3745. }
  3746. })()
  3747. var tiktok_com_default =
  3748. ':not(#a):not(#b):not(#c) a+.utags_ul_0{object-position:200% 50%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-5);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-5);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) a+.utags_ul_1{object-position:0% 200%}:not(#a):not(#b):not(#c) .css-e2j6y6-StyledLink+.utags_ul_0{object-position:0% 200%;--utags-notag-captain-tag-top: -4px;--utags-notag-captain-tag-left: -4px}:not(#a):not(#b):not(#c) .css-e2j6y6-StyledLink+.utags_ul_1{position:absolute;top:-9999px;margin-top:0px !important;margin-left:0px !important}:not(#a):not(#b):not(#c) .css-1gstnae-DivCommentItemWrapper{--utags-list-node-display: flex}:not(#a):not(#b):not(#c) .css-1gstnae-DivCommentItemWrapper a[href^="/@"] p{display:inline}:not(#a):not(#b):not(#c) .css-ulyotp-DivCommentContentContainer{--utags-list-node-display: flex}:not(#a):not(#b):not(#c) .css-1asahzr-DivBroadcastTitleWrapper a[data-utags_fit_content="1"]{display:inline-block !important;width:fit-content !important}:not(#a):not(#b):not(#c) .css-1asahzr-DivBroadcastTitleWrapper a[data-utags_fit_content="1"] *:not(svg){width:fit-content !important}:not(#a):not(#b):not(#c) .css-1asahzr-DivBroadcastTitleWrapper a+.utags_ul_1{object-position:200% 50%;position:absolute;top:-9999px;margin-top:0px !important;margin-left:0px !important}:not(#a):not(#b):not(#c) .css-c5ejjw-DivProfileContainer[data-e2e=user-profile-card] a[data-utags_fit_content="1"]{display:inline-block !important;width:fit-content !important}:not(#a):not(#b):not(#c) .css-c5ejjw-DivProfileContainer[data-e2e=user-profile-card] a[data-utags_fit_content="1"] *:not(svg){width:fit-content !important}:not(#a):not(#b):not(#c) .css-8c0sl4-AName[data-utags_fit_content="1"]{display:inline-block !important;width:fit-content !important;height:fit-content !important}:not(#a):not(#b):not(#c) .css-8c0sl4-AName[data-utags_fit_content="1"] *:not(svg){width:fit-content !important;height:fit-content !important}:not(#a):not(#b):not(#c) .css-8c0sl4-AName+.utags_ul_0{object-position:0% 200%;--utags-notag-captain-tag-top: -4px;--utags-notag-captain-tag-left: -4px}:not(#a):not(#b):not(#c) .css-8c0sl4-AName+.utags_ul_1{position:absolute;top:-9999px;margin-top:0px !important;margin-left:0px !important}:not(#a):not(#b):not(#c) [data-e2e=recommend-card] a+.utags_ul_0{object-position:0% 200%;--utags-notag-captain-tag-top: -2px;--utags-notag-captain-tag-left: -4px}:not(#a):not(#b):not(#c) [data-e2e=recommend-card] a+.utags_ul_1{position:absolute;top:-9999px;margin-top:2px !important;margin-left:0px !important}'
  3749. var tiktok_com_default2 = (() => {
  3750. const prefix3 = "https://www.tiktok.com/"
  3751. function getUserProfileUrl(url, exact = false) {
  3752. if (url.startsWith(prefix3)) {
  3753. const href2 = url.slice(23)
  3754. if (exact) {
  3755. if (/^@[\w.-]+([?#].*)?$/.test(href2)) {
  3756. return prefix3 + href2.replace(/(^@[\w.-]+).*/, "$1")
  3757. }
  3758. } else if (/^@[\w.-]+/.test(href2)) {
  3759. return prefix3 + href2.replace(/(^@[\w.-]+).*/, "$1")
  3760. }
  3761. }
  3762. return void 0
  3763. }
  3764. return {
  3765. matches: /tiktok\.com/,
  3766. listNodesSelectors: [
  3767. ".css-ulyotp-DivCommentContentContainer",
  3768. ".css-1gstnae-DivCommentItemWrapper",
  3769. ".css-x6y88p-DivItemContainerV2",
  3770. ],
  3771. conditionNodesSelectors: [
  3772. '.css-ulyotp-DivCommentContentContainer a[href^="/@"]',
  3773. '.css-1gstnae-DivCommentItemWrapper a[href^="/@"]',
  3774. '.css-x6y88p-DivItemContainerV2 a[href^="/@"]',
  3775. ],
  3776. validate(element) {
  3777. const href = element.href
  3778. if (!href.startsWith(prefix3)) {
  3779. return true
  3780. }
  3781. const key = getUserProfileUrl(href, true)
  3782. if (key) {
  3783. const titleElement = $('h3,[data-e2e="browse-username"]', element)
  3784. const title = titleElement
  3785. ? titleElement.textContent.trim()
  3786. : element.textContent.trim()
  3787. if (!title) {
  3788. return false
  3789. }
  3790. const meta = { type: "user", title }
  3791. element.utags = { key, meta }
  3792. return true
  3793. }
  3794. return false
  3795. },
  3796. excludeSelectors: [
  3797. ...default_default2.excludeSelectors,
  3798. ".avatar-anchor",
  3799. '[data-e2e*="avatar"]',
  3800. '[data-e2e="user-card-nickname"]',
  3801. ],
  3802. validMediaSelectors: [
  3803. '[data-e2e="browse-bluev"]',
  3804. '[data-e2e="recommend-card"]',
  3805. ],
  3806. addExtraMatchedNodes(matchedNodesSet) {
  3807. const element = $('h1[data-e2e="user-title"]')
  3808. if (element) {
  3809. const title = element.textContent.trim()
  3810. const key = getUserProfileUrl(location.href)
  3811. if (title && key) {
  3812. const meta = { title, type: "user" }
  3813. element.utags = { key, meta }
  3814. matchedNodesSet.add(element)
  3815. }
  3816. }
  3817. },
  3818. getStyle: () => tiktok_com_default,
  3819. }
  3820. })()
  3821. var pojie_cn_default =
  3822. ".fl cite,.tl cite{white-space:break-spaces}.favatar .pi .authi a{line-height:16px}.favatar .pi{height:auto}"
  3823. var pojie_cn_default2 = (() => {
  3824. return {
  3825. matches: /52pojie\.cn/,
  3826. matchedNodesSelectors: [
  3827. 'a[href*="home.php?mod=space&uid="]',
  3828. 'a[href*="home.php?mod=space&username="]',
  3829. ],
  3830. excludeSelectors: [
  3831. ...default_default2.excludeSelectors,
  3832. "#hd",
  3833. "#pt",
  3834. "#pgt",
  3835. "#jz52top",
  3836. ],
  3837. getStyle: () => pojie_cn_default,
  3838. }
  3839. })()
  3840. var juejin_cn_default = (() => {
  3841. const prefix3 = "https://juejin.cn/"
  3842. function getUserProfileUrl(url) {
  3843. if (url.startsWith(prefix3)) {
  3844. const href2 = url.slice(18)
  3845. if (/^user\/\d+/.test(href2)) {
  3846. return prefix3 + href2.replace(/^(user\/\d+).*/, "$1")
  3847. }
  3848. }
  3849. return void 0
  3850. }
  3851. return {
  3852. matches: /juejin\.cn/,
  3853. validate(element) {
  3854. if ($(".avatar", element)) {
  3855. return false
  3856. }
  3857. const href = element.href
  3858. if (href.startsWith(prefix3)) {
  3859. const key = getUserProfileUrl(href)
  3860. if (key) {
  3861. const titleElement = $(".name", element)
  3862. let title
  3863. if (titleElement) {
  3864. title = titleElement.textContent
  3865. }
  3866. const meta = { type: "user" }
  3867. if (title) {
  3868. meta.title = title
  3869. }
  3870. element.utags = { key, meta }
  3871. element.dataset.utags = element.dataset.utags || ""
  3872. return true
  3873. }
  3874. }
  3875. return false
  3876. },
  3877. excludeSelectors: [
  3878. ...default_default2.excludeSelectors,
  3879. ".list-header",
  3880. ".sub-header",
  3881. ".next-page",
  3882. ".follow-item",
  3883. ".more-item",
  3884. ],
  3885. addExtraMatchedNodes(matchedNodesSet) {
  3886. const key = getUserProfileUrl(location.href)
  3887. if (key) {
  3888. const element2 = $("h1.username")
  3889. if (element2) {
  3890. const title = element2.textContent.trim()
  3891. if (title) {
  3892. const meta = { title, type: "user" }
  3893. element2.utags = { key, meta }
  3894. matchedNodesSet.add(element2)
  3895. }
  3896. }
  3897. }
  3898. const element = $(".sidebar-block.author-block a .username")
  3899. if (element) {
  3900. const anchor = element.closest("a")
  3901. if (anchor) {
  3902. const key2 = getUserProfileUrl(anchor.href)
  3903. if (key2) {
  3904. const titleElement = $(".name", element)
  3905. const title = titleElement
  3906. ? titleElement.textContent
  3907. : element.textContent
  3908. if (title) {
  3909. const meta = { title, type: "user" }
  3910. element.utags = { key: key2, meta }
  3911. matchedNodesSet.add(element)
  3912. }
  3913. }
  3914. }
  3915. }
  3916. },
  3917. }
  3918. })()
  3919. var zhihu_com_default = (() => {
  3920. const prefix3 = "https://www.zhihu.com/"
  3921. function getUserProfileUrl(url, exact = false) {
  3922. if (url.startsWith(prefix3)) {
  3923. const href2 = url.slice(22)
  3924. if (exact) {
  3925. if (/^people\/[\w-]+(\?.*)?$/.test(href2)) {
  3926. return prefix3 + href2.replace(/^(people\/[\w-]+).*/, "$1")
  3927. }
  3928. } else if (/^people\/[\w-]+/.test(href2)) {
  3929. return prefix3 + href2.replace(/^(people\/[\w-]+).*/, "$1")
  3930. }
  3931. }
  3932. return void 0
  3933. }
  3934. return {
  3935. matches: /zhihu\.com/,
  3936. validate(element) {
  3937. if ($(".avatar", element)) {
  3938. return false
  3939. }
  3940. const href = element.href
  3941. if (!href.includes("zhihu.com")) {
  3942. return true
  3943. }
  3944. if (href.startsWith(prefix3 + "people/")) {
  3945. const key = getUserProfileUrl(href, true)
  3946. if (key) {
  3947. const titleElement = $(".name", element)
  3948. let title
  3949. if (titleElement) {
  3950. title = titleElement.textContent
  3951. }
  3952. const meta = { type: "user" }
  3953. if (title) {
  3954. meta.title = title
  3955. }
  3956. element.utags = { key, meta }
  3957. return true
  3958. }
  3959. }
  3960. return false
  3961. },
  3962. excludeSelectors: [
  3963. ...default_default2.excludeSelectors,
  3964. ".NumberBoard",
  3965. ".ProfileMain-tabs",
  3966. ".Profile-lightList",
  3967. ],
  3968. addExtraMatchedNodes(matchedNodesSet) {
  3969. const key = getUserProfileUrl(location.href)
  3970. if (key) {
  3971. const element = $("h1.ProfileHeader-title .ProfileHeader-name")
  3972. if (element) {
  3973. const title = element.textContent.trim()
  3974. if (title) {
  3975. const meta = { title, type: "user" }
  3976. element.utags = { key, meta }
  3977. matchedNodesSet.add(element)
  3978. }
  3979. }
  3980. }
  3981. },
  3982. }
  3983. })()
  3984. var xiaohongshu_com_default =
  3985. ":not(#a):not(#b):not(#c) a+.utags_ul_0{object-position:0% 100%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-5);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-5);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) a+.utags_ul_1{object-position:0% 100%;background-color:var(--utags-captain-tag-background-color) !important;border-radius:3px !important}:not(#a):not(#b):not(#c) .author-container .author-wrapper .name+.utags_ul_0{--utags-notag-captain-tag-top: 6px;--utags-notag-captain-tag-left: 8px}:not(#a):not(#b):not(#c) .author-container .author-wrapper .name+.utags_ul_1{position:absolute;top:-9999px;margin-top:4px !important;margin-left:8px !important}:not(#a):not(#b):not(#c) .note-text{position:relative}:not(#a):not(#b):not(#c) .note-text .utags_ul_0{--utags-notag-ul-disply: var(--utags-notag-ul-disply-1);--utags-notag-ul-height: var(--utags-notag-ul-height-1);--utags-notag-ul-position: var(--utags-notag-ul-position-1);--utags-notag-ul-top: var(--utags-notag-ul-top-1);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-1);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-1);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) .comments-container .author-wrapper .author{align-items:flex-start;flex-direction:column}:not(#a):not(#b):not(#c) .comments-container .author-wrapper .author .name+.utags_ul_0{object-position:200% 50%}:not(#a):not(#b):not(#c) .note-content-user+.utags_ul_0{--utags-notag-captain-tag-top: 0px;--utags-notag-captain-tag-left: 20px}:not(#a):not(#b):not(#c) .tooltip-content .user-content .avatar-info+.utags_ul_0{--utags-notag-captain-tag-top: 6px;--utags-notag-captain-tag-left: 46px}:not(#a):not(#b):not(#c) .tooltip-content .user-content .avatar-info+.utags_ul_1{position:absolute;top:-9999px;margin-top:6px !important;margin-left:46px !important}:not(#a):not(#b):not(#c) .note-item .cover+.utags_ul_0{--utags-notag-captain-tag-top: 18px;--utags-notag-captain-tag-left: -8px}:not(#a):not(#b):not(#c) .note-item .cover+.utags_ul_1{position:absolute;top:-9999px;margin-top:14px !important;margin-left:-4px !important}:not(#a):not(#b):not(#c) .note-item .author-wrapper .author+.utags_ul_0{--utags-notag-captain-tag-top: 16px;--utags-notag-captain-tag-left: 20px}:not(#a):not(#b):not(#c) .note-item .author-wrapper .author+.utags_ul_1{position:absolute;top:-9999px;margin-top:12px !important;margin-left:22px !important}:not(#a):not(#b):not(#c) #userPageContainer .user-info .user-nickname{align-items:flex-start;flex-direction:column}:not(#a):not(#b):not(#c) #userPageContainer .user-info .user-nickname .user-name+.utags_ul_0{object-position:0% 200%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: 0px;--utags-notag-captain-tag-left: 0px}"
  3986. var xiaohongshu_com_default2 = (() => {
  3987. const prefix3 = "https://www.xiaohongshu.com/"
  3988. function getCanonicalUrl2(url) {
  3989. if (url.startsWith(prefix3)) {
  3990. const href2 = url.slice(prefix3.length)
  3991. if (href2.startsWith("search_result") && href2.includes("keyword")) {
  3992. return (
  3993. prefix3 +
  3994. "search_result/?" +
  3995. href2.replace(/.*?(keyword=[^&]*).*/, "$1") +
  3996. "&type=54"
  3997. )
  3998. }
  3999. }
  4000. return url
  4001. }
  4002. function getUserProfileUrl(url, exact = false) {
  4003. if (url.startsWith(prefix3)) {
  4004. const href2 = url.slice(28)
  4005. if (exact) {
  4006. if (/^user\/profile\/\w+(\?.*)?$/.test(href2)) {
  4007. return prefix3 + href2.replace(/^(user\/profile\/\w+).*/, "$1")
  4008. }
  4009. } else if (/^user\/profile\/\w+/.test(href2)) {
  4010. return prefix3 + href2.replace(/^(user\/profile\/\w+).*/, "$1")
  4011. }
  4012. }
  4013. return void 0
  4014. }
  4015. function getPostUrl(url) {
  4016. if (url.startsWith(prefix3)) {
  4017. const href2 = url.slice(28)
  4018. if (/^explore\/\w+/.test(href2)) {
  4019. return prefix3 + href2.replace(/^(explore\/\w+).*/, "$1")
  4020. }
  4021. if (/^user\/profile\/\w+\/\w+/.test(href2)) {
  4022. return (
  4023. prefix3 +
  4024. "explore/" +
  4025. href2.replace(/^user\/profile\/\w+\/(\w+).*/, "$1")
  4026. )
  4027. }
  4028. if (/^search_result\/\w+/.test(href2)) {
  4029. return (
  4030. prefix3 +
  4031. "explore/" +
  4032. href2.replace(/^search_result\/(\w+).*/, "$1")
  4033. )
  4034. }
  4035. }
  4036. return void 0
  4037. }
  4038. return {
  4039. matches: /www\.xiaohongshu\.com/,
  4040. listNodesSelectors: [".feeds-container section", ".comment-item"],
  4041. conditionNodesSelectors: [
  4042. ".feeds-container section .author-wrapper .author",
  4043. ".feeds-container section .cover",
  4044. ".comment-item .author-wrapper .author a",
  4045. ],
  4046. validate(element) {
  4047. const href = element.href
  4048. if (!href.startsWith(prefix3)) {
  4049. return true
  4050. }
  4051. let key = getUserProfileUrl(href, true)
  4052. if (key) {
  4053. const titleElement =
  4054. (hasClass(element, "name") ? element : $(".name", element)) ||
  4055. element
  4056. let title
  4057. if (titleElement) {
  4058. title = titleElement.textContent.trim()
  4059. }
  4060. if (!title) {
  4061. return false
  4062. }
  4063. const meta = { type: "user", title }
  4064. element.utags = { key, meta }
  4065. element.dataset.utags = element.dataset.utags || ""
  4066. return true
  4067. }
  4068. key = getPostUrl(href)
  4069. if (key) {
  4070. const meta = { type: "post" }
  4071. if (hasClass(element, "cover")) {
  4072. const sibling = element.nextElementSibling
  4073. if (sibling && hasClass(sibling, "footer")) {
  4074. const titleElement = $(".title span", sibling)
  4075. if (titleElement) {
  4076. const title = titleElement.textContent.trim()
  4077. if (title) {
  4078. meta.title = title
  4079. }
  4080. }
  4081. element.dataset.utags = element.dataset.utags || ""
  4082. }
  4083. }
  4084. element.utags = { key, meta }
  4085. return true
  4086. }
  4087. return true
  4088. },
  4089. excludeSelectors: [
  4090. ...default_default2.excludeSelectors,
  4091. ".side-bar",
  4092. ".dropdown-nav",
  4093. ".dropdown-container",
  4094. ".interaction-info",
  4095. ],
  4096. addExtraMatchedNodes(matchedNodesSet) {
  4097. let key = getUserProfileUrl(location.href)
  4098. if (key) {
  4099. const element = $(".user-info .user-name")
  4100. if (element) {
  4101. const title = element.textContent.trim()
  4102. if (title) {
  4103. const meta = { title, type: "user" }
  4104. element.utags = { key, meta }
  4105. element.dataset.utags_node_type = "link"
  4106. matchedNodesSet.add(element)
  4107. }
  4108. }
  4109. }
  4110. key = getPostUrl(location.href)
  4111. if (key) {
  4112. const element = $(".note-content .title")
  4113. if (element) {
  4114. const title = element.textContent.trim()
  4115. if (title) {
  4116. const meta = { title, type: "post" }
  4117. element.utags = { key, meta }
  4118. matchedNodesSet.add(element)
  4119. }
  4120. }
  4121. }
  4122. },
  4123. getCanonicalUrl: getCanonicalUrl2,
  4124. getStyle: () => xiaohongshu_com_default,
  4125. }
  4126. })()
  4127. var weibo_com_default = (() => {
  4128. const prefix3 = "https://weibo.com/"
  4129. const prefix22 = "https://m.weibo.cn/"
  4130. function getCanonicalUrl2(url) {
  4131. if (url.startsWith(prefix3) || url.startsWith(prefix22)) {
  4132. const href2 = getUserProfileUrl(url, true)
  4133. if (href2) {
  4134. return href2
  4135. }
  4136. }
  4137. return url
  4138. }
  4139. function getUserProfileUrl(url, exact = false) {
  4140. if (url.startsWith(prefix3) || url.startsWith(prefix22)) {
  4141. const href2 = url.startsWith(prefix22) ? url.slice(19) : url.slice(18)
  4142. if (exact) {
  4143. if (/^u\/\d+(\?.*)?$/.test(href2)) {
  4144. return prefix3 + href2.replace(/^(u\/\d+).*/, "$1")
  4145. }
  4146. if (/^profile\/\d+(\?.*)?$/.test(href2)) {
  4147. return prefix3 + "u/" + href2.replace(/^profile\/(\d+).*/, "$1")
  4148. }
  4149. if (/^\d+(\?.*)?$/.test(href2)) {
  4150. return prefix3 + "u/" + href2.replace(/^(\d+).*/, "$1")
  4151. }
  4152. } else {
  4153. if (/^u\/\d+/.test(href2)) {
  4154. return prefix3 + href2.replace(/^(u\/\d+).*/, "$1")
  4155. }
  4156. if (/^profile\/\d+/.test(href2)) {
  4157. return prefix3 + "u/" + href2.replace(/^profile\/(\d+).*/, "$1")
  4158. }
  4159. if (/^\d+/.test(href2)) {
  4160. return prefix3 + "u/" + href2.replace(/^(\d+).*/, "$1")
  4161. }
  4162. }
  4163. }
  4164. return void 0
  4165. }
  4166. return {
  4167. matches: /weibo\.com|weibo\.cn/,
  4168. validate(element) {
  4169. const href = element.href
  4170. if (!href.includes("weibo.com") && !href.includes("weibo.cn")) {
  4171. return true
  4172. }
  4173. const key = getUserProfileUrl(href, true)
  4174. if (key) {
  4175. const meta = { type: "user" }
  4176. element.utags = { key, meta }
  4177. if ($(".m-icon.vipicon", element)) {
  4178. element.dataset.utags = element.dataset.utags || ""
  4179. }
  4180. return true
  4181. }
  4182. return true
  4183. },
  4184. excludeSelectors: [
  4185. ...default_default2.excludeSelectors,
  4186. '[class^="Frame_side_"]',
  4187. 'a[href*="promote.biz.weibo.cn"]',
  4188. ],
  4189. addExtraMatchedNodes(matchedNodesSet) {
  4190. const key = getUserProfileUrl(location.href)
  4191. if (key) {
  4192. const element = $(
  4193. '[class^="ProfileHeader_name_"],.profile-cover .mod-fil-name .txt-shadow'
  4194. )
  4195. if (element) {
  4196. const title = element.textContent.trim()
  4197. if (title) {
  4198. const meta = { title, type: "user" }
  4199. element.utags = { key, meta }
  4200. matchedNodesSet.add(element)
  4201. }
  4202. }
  4203. }
  4204. },
  4205. getCanonicalUrl: getCanonicalUrl2,
  4206. }
  4207. })()
  4208. var sspai_com_default =
  4209. ":not(#a):not(#b):not(#c) #article-title+.utags_ul{display:block !important;margin-top:-30px !important;margin-bottom:20px !important}:not(#a):not(#b):not(#c) .user__info__card__center .utags_ul{display:block !important;margin-bottom:5px !important}:not(#a):not(#b):not(#c) .pai_title .utags_ul{float:left}"
  4210. var sspai_com_default2 = (() => {
  4211. const prefix3 = "https://sspai.com/"
  4212. const excludeLinks = [
  4213. "https://sspai.com/prime",
  4214. "https://sspai.com/matrix",
  4215. "https://sspai.com/page/about-us",
  4216. "https://sspai.com/page/agreement",
  4217. "https://sspai.com/page/bussiness",
  4218. "https://sspai.com/post/37793",
  4219. "https://sspai.com/page/client",
  4220. "https://sspai.com/s/J71e",
  4221. "https://sspai.com/mall",
  4222. ]
  4223. function getCanonicalUrl2(url) {
  4224. if (url.startsWith(prefix3)) {
  4225. const href = url.slice(18)
  4226. if (href.startsWith("u/")) {
  4227. return prefix3 + href.replace(/^(u\/\w+).*/, "$1")
  4228. }
  4229. }
  4230. return url
  4231. }
  4232. function getUserProfileUrl(url) {
  4233. if (url.startsWith(prefix3)) {
  4234. const href2 = url.slice(18)
  4235. if (/^u\/\w+/.test(href2)) {
  4236. return prefix3 + href2.replace(/^(u\/\w+).*/, "$1")
  4237. }
  4238. }
  4239. return void 0
  4240. }
  4241. function getPostUrl(url) {
  4242. if (url.startsWith(prefix3)) {
  4243. const href2 = url.slice(18)
  4244. if (/^post\/\d+/.test(href2)) {
  4245. return prefix3 + href2.replace(/^(post\/\d+).*/, "$1")
  4246. }
  4247. }
  4248. return void 0
  4249. }
  4250. return {
  4251. matches: /sspai\.com/,
  4252. validate(element) {
  4253. const href = element.href
  4254. for (const link of excludeLinks) {
  4255. if (href.includes(link)) {
  4256. return false
  4257. }
  4258. }
  4259. if (
  4260. hasClass(element, "ss__user__nickname__wrapper") ||
  4261. element.closest('.card_bottom > a[href^="/u/"]')
  4262. ) {
  4263. element.dataset.utags = element.dataset.utags || ""
  4264. return true
  4265. }
  4266. return true
  4267. },
  4268. excludeSelectors: [
  4269. ...default_default2.excludeSelectors,
  4270. "header",
  4271. "footer",
  4272. ".pai_abstract",
  4273. ".pai_title .link",
  4274. ],
  4275. addExtraMatchedNodes(matchedNodesSet) {
  4276. let key = getPostUrl(location.href)
  4277. if (key) {
  4278. const element = $(".article-header .title")
  4279. if (element && !element.closest(".pai_title")) {
  4280. const title = element.textContent.trim()
  4281. if (title) {
  4282. const meta = { title, type: "post" }
  4283. element.utags = { key, meta }
  4284. matchedNodesSet.add(element)
  4285. }
  4286. }
  4287. }
  4288. key = getUserProfileUrl(location.href)
  4289. if (key) {
  4290. const element = $(
  4291. ".user_content .user__info__card .ss__user__card__nickname"
  4292. )
  4293. if (element) {
  4294. const title = element.textContent.trim()
  4295. if (title) {
  4296. const meta = { title, type: "user" }
  4297. element.utags = { key, meta }
  4298. matchedNodesSet.add(element)
  4299. }
  4300. }
  4301. }
  4302. },
  4303. getCanonicalUrl: getCanonicalUrl2,
  4304. getStyle: () => sspai_com_default,
  4305. }
  4306. })()
  4307. var douyin_com_default =
  4308. ':not(#a):not(#b):not(#c) [data-e2e=comment-item] .utags_ul_0 .utags_captain_tag{left:-26px}:not(#a):not(#b):not(#c) [data-e2e=detail-video-info] .utags_ul[data-utags_key*="/video/"]{display:block !important;margin-top:0px !important;margin-bottom:2px !important}:not(#a):not(#b):not(#c) [data-e2e=detail-video-info] .utags_ul[data-utags_key*="/video/"].utags_ul_0{height:0}:not(#a):not(#b):not(#c) [data-e2e=detail-video-info] .utags_ul[data-utags_key*="/video/"].utags_ul_0 .utags_captain_tag{top:-26px;background-color:rgba(255,255,255,.8666666667) !important}:not(#a):not(#b):not(#c) [data-e2e=related-video] .utags_ul_0[data-utags_key*="/video/"]{display:block !important;height:0}:not(#a):not(#b):not(#c) [data-e2e=related-video] .utags_ul_0[data-utags_key*="/video/"] .utags_captain_tag{top:-26px;background-color:rgba(255,255,255,.8666666667) !important}:not(#a):not(#b):not(#c) [data-e2e=related-video] .utags_ul_0[data-utags_key*="/user/"]{display:block !important;height:0px;width:0px}:not(#a):not(#b):not(#c) [data-e2e=related-video] .utags_ul_0[data-utags_key*="/user/"] .utags_captain_tag{top:-22px;background-color:rgba(255,255,255,.8666666667) !important}:not(#a):not(#b):not(#c) [data-e2e=user-info] a+.utags_ul_0[data-utags_key*="/user/"]{display:block !important;height:0px;width:0px}:not(#a):not(#b):not(#c) [data-e2e=user-info] a+.utags_ul_0[data-utags_key*="/user/"] .utags_captain_tag{top:-22px;background-color:rgba(255,255,255,.8666666667) !important}'
  4309. var douyin_com_default2 = (() => {
  4310. const prefix3 = "https://www.douyin.com/"
  4311. function getUserProfileUrl(url, exact = false) {
  4312. if (url.startsWith(prefix3)) {
  4313. const href2 = url.slice(23)
  4314. if (exact) {
  4315. if (/^user\/[\w-]+(\?.*)?$/.test(href2)) {
  4316. return prefix3 + href2.replace(/^(user\/[\w-]+).*/, "$1")
  4317. }
  4318. } else if (/^user\/[\w-]+/.test(href2)) {
  4319. return prefix3 + href2.replace(/^(user\/[\w-]+).*/, "$1")
  4320. }
  4321. }
  4322. return void 0
  4323. }
  4324. function getVideoUrl(url) {
  4325. if (url.startsWith(prefix3)) {
  4326. const href2 = url.slice(23)
  4327. if (/^video\/\w+/.test(href2)) {
  4328. return prefix3 + href2.replace(/^(video\/\w+).*/, "$1")
  4329. }
  4330. }
  4331. return void 0
  4332. }
  4333. function getNoteUrl(url) {
  4334. if (url.startsWith(prefix3)) {
  4335. const href2 = url.slice(23)
  4336. if (/^note\/\w+/.test(href2)) {
  4337. return prefix3 + href2.replace(/^(note\/\w+).*/, "$1")
  4338. }
  4339. }
  4340. return void 0
  4341. }
  4342. return {
  4343. matches: /www\.douyin\.com/,
  4344. validate(element) {
  4345. const href = element.href
  4346. if (!href.includes("www.douyin.com")) {
  4347. return true
  4348. }
  4349. let key = getUserProfileUrl(href, true)
  4350. if (key) {
  4351. const meta = { type: "user" }
  4352. element.utags = { key, meta }
  4353. return true
  4354. }
  4355. key = getVideoUrl(href)
  4356. if (key) {
  4357. const meta = { type: "video" }
  4358. element.utags = { key, meta }
  4359. return true
  4360. }
  4361. key = getNoteUrl(href)
  4362. if (key) {
  4363. const meta = { type: "post" }
  4364. element.utags = { key, meta }
  4365. return true
  4366. }
  4367. return true
  4368. },
  4369. excludeSelectors: [
  4370. ...default_default2.excludeSelectors,
  4371. '[data-e2e="douyin-navigation"]',
  4372. ],
  4373. validMediaSelectors: ['img[src*="twemoji"]'],
  4374. addExtraMatchedNodes(matchedNodesSet) {
  4375. let key = getUserProfileUrl(location.href)
  4376. if (key) {
  4377. const element = getFirstHeadElement("h1")
  4378. if (element) {
  4379. const title = element.textContent.trim()
  4380. if (title) {
  4381. const meta = { title, type: "user" }
  4382. element.utags = { key, meta }
  4383. matchedNodesSet.add(element)
  4384. }
  4385. }
  4386. }
  4387. key = getVideoUrl(location.href)
  4388. if (key) {
  4389. const element = getFirstHeadElement("h1")
  4390. if (element) {
  4391. const title = element.textContent.trim()
  4392. const target = element.parentElement.parentElement
  4393. if (title) {
  4394. const meta = { title, type: "video" }
  4395. target.utags = { key, meta }
  4396. target.dataset.utags_node_type = "link"
  4397. matchedNodesSet.add(target)
  4398. }
  4399. }
  4400. }
  4401. key = getNoteUrl(location.href)
  4402. if (key) {
  4403. const element = getFirstHeadElement("h1")
  4404. if (element) {
  4405. const title = element.textContent.trim()
  4406. if (title) {
  4407. const meta = { title, type: "post" }
  4408. element.utags = { key, meta }
  4409. matchedNodesSet.add(element)
  4410. }
  4411. }
  4412. }
  4413. },
  4414. getStyle: () => douyin_com_default,
  4415. }
  4416. })()
  4417. var podcasts_google_com_default = ""
  4418. var podcasts_google_com_default2 = (() => {
  4419. const prefix3 = "https://podcasts.google.com/"
  4420. function getEpisodeUrl(url, exact = false) {
  4421. if (url.startsWith(prefix3)) {
  4422. const href2 = url.slice(28)
  4423. if (exact) {
  4424. if (/^feed\/\w+\/episode\/\w+(\?.*)?$/.test(href2)) {
  4425. return prefix3 + href2.replace(/^(feed\/\w+\/episode\/\w+).*/, "$1")
  4426. }
  4427. } else if (/^feed\/\w+\/episode\/\w+/.test(href2)) {
  4428. return prefix3 + href2.replace(/^(feed\/\w+\/episode\/\w+).*/, "$1")
  4429. }
  4430. }
  4431. return void 0
  4432. }
  4433. function getFeedUrl(url) {
  4434. if (url.startsWith(prefix3)) {
  4435. const href2 = url.slice(28)
  4436. if (/^feed\/\w+(\?.*)?$/.test(href2)) {
  4437. return prefix3 + href2.replace(/^(feed\/\w+).*/, "$1")
  4438. }
  4439. }
  4440. return void 0
  4441. }
  4442. function getCanonicalUrl2(url) {
  4443. if (url.startsWith(prefix3)) {
  4444. let url2 = getFeedUrl(url)
  4445. if (url2) {
  4446. return url2
  4447. }
  4448. url2 = getEpisodeUrl(url)
  4449. if (url2) {
  4450. return url2
  4451. }
  4452. }
  4453. return url
  4454. }
  4455. return {
  4456. matches: /podcasts\.google\.com/,
  4457. excludeSelectors: [
  4458. ...default_default2.excludeSelectors,
  4459. "header",
  4460. "gm-coplanar-drawer",
  4461. ],
  4462. addExtraMatchedNodes(matchedNodesSet) {
  4463. let key = getEpisodeUrl(location.href)
  4464. if (key) {
  4465. const element = $("h5")
  4466. if (element) {
  4467. const title = element.textContent.trim()
  4468. if (title) {
  4469. const meta = { title, type: "episode" }
  4470. element.utags = { key, meta }
  4471. matchedNodesSet.add(element)
  4472. }
  4473. }
  4474. }
  4475. key = getFeedUrl(location.href)
  4476. if (key) {
  4477. for (const container of $$("[data-encoded-feed]")) {
  4478. if (isVisible(container)) {
  4479. const element = $(
  4480. "div:first-child > div:first-child > div:first-child > div:first-child",
  4481. container
  4482. )
  4483. if (element) {
  4484. const title = element.textContent.trim()
  4485. if (title) {
  4486. const meta = { title, type: "feed" }
  4487. element.utags = { key, meta }
  4488. matchedNodesSet.add(element)
  4489. }
  4490. }
  4491. }
  4492. }
  4493. }
  4494. for (const element of $$('a[role="listitem"]')) {
  4495. const key2 = getEpisodeUrl(element.href)
  4496. const titleElement = $(
  4497. 'div[role="navigation"] div div[role="presentation"]',
  4498. element
  4499. )
  4500. if (key2 && titleElement) {
  4501. const title = titleElement.textContent
  4502. const meta = { title, type: "episode" }
  4503. titleElement.utags = { key: key2, meta }
  4504. titleElement.dataset.utags_node_type = "link"
  4505. matchedNodesSet.add(titleElement)
  4506. }
  4507. }
  4508. for (const element of $$(
  4509. 'a[href^="./feed/"]:not(a[href*="/episode/"])'
  4510. )) {
  4511. if (!isVisible(element)) {
  4512. continue
  4513. }
  4514. const key2 = getFeedUrl(element.href)
  4515. const titleElement = $("div > div", element)
  4516. if (titleElement) {
  4517. const title = titleElement.textContent
  4518. const meta = { title, type: "feed" }
  4519. titleElement.utags = { key: key2, meta }
  4520. titleElement.dataset.utags_node_type = "link"
  4521. matchedNodesSet.add(titleElement)
  4522. }
  4523. }
  4524. },
  4525. getCanonicalUrl: getCanonicalUrl2,
  4526. getStyle: () => podcasts_google_com_default,
  4527. }
  4528. })()
  4529. var rebang_today_default =
  4530. ":not(#a):not(#b):not(#c) .w-screen ul{--utags-list-node-display: flex}:not(#a):not(#b):not(#c) .w-screen ul .flex-1:not(.relative)>.utags_ul_0,:not(#a):not(#b):not(#c) .w-screen ul .flex.flex-col.relative .flex-1 .utags_ul_0,:not(#a):not(#b):not(#c) .w-screen ul .relative>.utags_ul_0{--utags-notag-ul-disply: var(--utags-notag-ul-disply-3);--utags-notag-ul-height: var(--utags-notag-ul-height-3);--utags-notag-ul-position: var(--utags-notag-ul-position-3);--utags-notag-ul-top: var(--utags-notag-ul-top-3);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-3);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-3);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) .w-screen ul .flex.flex-col.relative .flex-1 .utags_ul_0,:not(#a):not(#b):not(#c) .w-screen ul .flex-1:not(.relative)>.utags_ul_0{--utags-notag-captain-tag-top: 18px}:not(#a):not(#b):not(#c) .w-screen ul .text-base .block+.utags_ul_0,:not(#a):not(#b):not(#c) .w-screen ul h1 .utags_ul_0,:not(#a):not(#b):not(#c) .w-screen ul li>div.overflow-hidden:nth-of-type(2):not(.relative)>a+.utags_ul_0,:not(#a):not(#b):not(#c) .w-screen ul li>a+.utags_ul_0{--utags-notag-ul-disply: var(--utags-notag-ul-disply-2);--utags-notag-ul-height: var(--utags-notag-ul-height-2);--utags-notag-ul-position: var(--utags-notag-ul-position-2);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-2);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-2);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) .w-screen ul .text-base .block+.utags_ul_0{--utags-notag-captain-tag-top: -24px}:not(#a):not(#b):not(#c) .w-screen ul h1 .utags_ul_0{--utags-notag-captain-tag-top: -28px}:not(#a):not(#b):not(#c) .w-screen ul li>a+.utags_ul_0{--utags-notag-captain-tag-left: 26px}:not(#a):not(#b):not(#c) .w-screen ul .flex.flex-col .text-base+.utags_ul_0,:not(#a):not(#b):not(#c) .w-screen ul li>a.text-base+.utags_ul_0{--utags-notag-ul-disply: var(--utags-notag-ul-disply-4);--utags-notag-ul-height: var(--utags-notag-ul-height-4);--utags-notag-ul-position: var(--utags-notag-ul-position-4);--utags-notag-ul-top: var(--utags-notag-ul-top-4);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-4);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-4);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) .w-screen ul li>a.text-base+.utags_ul_0{--utags-notag-captain-tag-top: -10px;--utags-notag-captain-tag-left: 14px}:not(#a):not(#b):not(#c) .w-screen ul .truncate .utags_ul_0{--utags-notag-captain-tag-left: -22px}:not(#a):not(#b):not(#c) aside{--utags-list-node-display: flex}:not(#a):not(#b):not(#c) aside .select-none .utags_ul_0{--utags-notag-captain-tag-left: -22px}:not(#a):not(#b):not(#c) aside .select-none .arco-tag .utags_ul_0{--utags-notag-captain-tag-left: -6px}:not(#a):not(#b):not(#c) #markdown-body.markdown-body a+.utags_ul_0{--utags-notag-ul-disply: var(--utags-notag-ul-disply-1);--utags-notag-ul-height: var(--utags-notag-ul-height-1);--utags-notag-ul-width: var(--utags-notag-ul-width-1);--utags-notag-ul-position: var(--utags-notag-ul-position-1);--utags-notag-ul-top: var(--utags-notag-ul-top-1);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-1);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-1)}"
  4531. var rebang_today_default2 = (() => {
  4532. const nodeNameMap = {
  4533. 知乎: "zhihu",
  4534. 微博: "weibo",
  4535. IT之家: "ithome",
  4536. 虎扑: "hupu",
  4537. 豆瓣社区: "douban-community",
  4538. 虎嗅: "huxiu",
  4539. 少数派: "sspai",
  4540. 网易新闻: "ne-news",
  4541. 澎湃新闻: "thepaper",
  4542. 小红书: "xiaohongshu",
  4543. "36\u6C2A": "36kr",
  4544. 今日头条: "toutiao",
  4545. 爱范儿: "ifanr",
  4546. 豆瓣书影音: "douban-media",
  4547. 什么值得买: "smzdm",
  4548. 百度: "baidu",
  4549. 百度贴吧: "baidu-tieba",
  4550. 吾爱破解: "52pojie",
  4551. 观风闻: "guancha-user",
  4552. 雪球: "xueqiu",
  4553. 东方财富: "eastmoney",
  4554. 新浪财经: "sina-fin",
  4555. 蓝点网: "landian",
  4556. 小众软件: "appinn",
  4557. 反斗限免: "apprcn",
  4558. NGA社区: "nga",
  4559. 游民星空: "gamersky",
  4560. 喷嚏网: "penti",
  4561. 沙雕新闻: "shadiao-news",
  4562. 抖音: "douyin",
  4563. 哔哩哔哩: "bilibili",
  4564. 直播吧: "zhibo8",
  4565. 掘金: "juejin",
  4566. 技术期刊: "journal-tech",
  4567. 开发者头条: "toutiaoio",
  4568. GitHub: "github",
  4569. AcFun: "acfun",
  4570. 宽带山: "kds",
  4571. V2EX: "v2ex",
  4572. 格隆汇: "gelonghui",
  4573. 第一财经: "diyicaijing",
  4574. InfoQ: "infoq",
  4575. CSDN: "csdn",
  4576. }
  4577. return {
  4578. matches: /rebang\.today/,
  4579. preProcess() {
  4580. const nodes = $$(":not(a) > .arco-tag-content")
  4581. for (const node of nodes) {
  4582. const name = node.textContent
  4583. if (name && !node.closest("a")) {
  4584. const nodeId = nodeNameMap[name]
  4585. if (nodeId) {
  4586. const a = createElement("a", {
  4587. href: "https://rebang.today/home?tab=" + nodeId,
  4588. })
  4589. node.after(a)
  4590. a.append(node)
  4591. }
  4592. }
  4593. }
  4594. },
  4595. listNodesSelectors: [
  4596. ".w-screen ul:not(.utags_ul) > li",
  4597. "aside .w-full .select-none",
  4598. ],
  4599. conditionNodesSelectors: [
  4600. '[data-utags_list_node] [data-utags]:not([href^="https://www.v2ex.com/member/"])',
  4601. '[data-utags_list_node] a[href^="https://www.v2ex.com/member/"][data-utags].hidden',
  4602. ],
  4603. excludeSelectors: [
  4604. ...default_default2.excludeSelectors,
  4605. "header",
  4606. ".absolute.rounded-xl",
  4607. "ul li h1 + p a",
  4608. ],
  4609. validMediaSelectors: [
  4610. ".text-text-100",
  4611. ".items-center .rounded-full",
  4612. 'a[href^="https://github.com/"] svg',
  4613. 'a[href^="https://space.bilibili.com/"] img',
  4614. 'a[href^="https://toutiao.io/subjects/"] img',
  4615. "svg.arco-icon",
  4616. ],
  4617. getStyle: () => rebang_today_default,
  4618. }
  4619. })()
  4620. var myanimelist_net_default =
  4621. ":not(#a):not(#b):not(#c) tbody.list-item td.title{--utags-notag-captain-tag-top: -6px;--utags-notag-captain-tag-left: -24px}"
  4622. var myanimelist_net_default2 = (() => {
  4623. return {
  4624. matches: /myanimelist\.net/,
  4625. listNodesSelectors: [],
  4626. conditionNodesSelectors: [],
  4627. excludeSelectors: [
  4628. ...default_default2.excludeSelectors,
  4629. "#headerSmall",
  4630. "#menu",
  4631. "#nav",
  4632. ".header",
  4633. "#status-menu",
  4634. 'a[href^="/sns/register/"]',
  4635. 'a[href^="/logout"]',
  4636. 'a[href*="/membership?"]',
  4637. 'a[href*="/login.php"]',
  4638. 'a[href*="/register.php"]',
  4639. 'a[href*="/dbchanges.php"]',
  4640. 'a[href*="/editprofile.php"]',
  4641. 'a[href*="go=write"]',
  4642. 'a[href^="/ownlist/anime/add?"]',
  4643. '[class*="btn-"]',
  4644. '[class*="icon-"]',
  4645. '[rel*="sponsored"]',
  4646. ],
  4647. getStyle: () => myanimelist_net_default,
  4648. }
  4649. })()
  4650. var douban_com_default = (() => {
  4651. function getCanonicalUrl2(url) {
  4652. if (url.includes("douban.com")) {
  4653. return deleteUrlParameters(url, [
  4654. "ref",
  4655. "dcs",
  4656. "dcm",
  4657. "from",
  4658. "from_",
  4659. "dt_time_source",
  4660. "target_user_id",
  4661. "_dtcc",
  4662. "_i",
  4663. ])
  4664. }
  4665. return url
  4666. }
  4667. return {
  4668. matches: /douban\.com/,
  4669. listNodesSelectors: [],
  4670. conditionNodesSelectors: [],
  4671. excludeSelectors: [
  4672. ...default_default2.excludeSelectors,
  4673. ".tabs",
  4674. 'a[href*="/accounts/login?"]',
  4675. 'a[href*="/passport/login?"]',
  4676. 'a[href*="/register?"]',
  4677. ],
  4678. getCanonicalUrl: getCanonicalUrl2,
  4679. }
  4680. })()
  4681. var pixiv_net_default = ""
  4682. var pixiv_net_default2 = (() => {
  4683. const prefix3 = "https://www.pixiv.net/"
  4684. function getUserProfileUrl(url, exact = false) {
  4685. if (url.startsWith(prefix3)) {
  4686. let href2 = url.slice(22)
  4687. if (href2.startsWith("en/")) {
  4688. href2 = href2.slice(3)
  4689. }
  4690. if (exact) {
  4691. if (/^users\/\d+([?#].*)?$/.test(href2)) {
  4692. return prefix3 + href2.replace(/^(users\/\d+).*/, "$1")
  4693. }
  4694. } else if (/^users\/\d+/.test(href2)) {
  4695. return prefix3 + href2.replace(/^(users\/\d+).*/, "$1")
  4696. }
  4697. }
  4698. return void 0
  4699. }
  4700. return {
  4701. matches: /pixiv\.net/,
  4702. validate(element) {
  4703. const href = element.href
  4704. if (!href.includes("www.pixiv.net")) {
  4705. return true
  4706. }
  4707. const key = getUserProfileUrl(href, true)
  4708. if (key) {
  4709. const title = element.textContent
  4710. if (
  4711. !title ||
  4712. /プロフィールを見る|View Profile|프로필 보기|查看个人资料|查看個人資料|ホーム|Home|홈|主页|首頁/.test(
  4713. title
  4714. )
  4715. ) {
  4716. return false
  4717. }
  4718. const meta = { type: "user", title }
  4719. element.utags = { key, meta }
  4720. element.dataset.utags = element.dataset.utags || ""
  4721. return true
  4722. }
  4723. return false
  4724. },
  4725. addExtraMatchedNodes(matchedNodesSet) {
  4726. const key = getUserProfileUrl(location.href)
  4727. if (key) {
  4728. const element = $("h1")
  4729. if (element) {
  4730. const title = element.textContent.trim()
  4731. if (title) {
  4732. const meta = { title, type: "user" }
  4733. element.utags = { key, meta }
  4734. matchedNodesSet.add(element)
  4735. }
  4736. }
  4737. }
  4738. },
  4739. getStyle: () => pixiv_net_default,
  4740. }
  4741. })()
  4742. var discourse_default =
  4743. ':not(#a):not(#b):not(#c) *+.utags_ul_0{object-position:200% 50%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-5);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-5);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) *+.utags_ul_1{object-position:0% 200%}:not(#a):not(#b):not(#c) .topic-list{--utags-list-node-display: table-row}:not(#a):not(#b):not(#c) .topic-list .main-link a.title+.utags_ul_1{margin-bottom:4px !important}:not(#a):not(#b):not(#c) .topic-list .discourse-tag+.utags_ul_0{--utags-notag-captain-tag-top: 1px}:not(#a):not(#b):not(#c) .topic-list .discourse-tag+.utags_ul_1{margin-top:3px !important}:not(#a):not(#b):not(#c) .topic-list .posters a:first-of-type+.utags_ul_0{object-position:0% 200%;--utags-notag-captain-tag-left: -6px}:not(#a):not(#b):not(#c) .topic-list .posters a:first-of-type+.utags_ul_1{position:absolute;top:-9999px;margin-top:4px !important;margin-left:-2px !important}:not(#a):not(#b):not(#c) header .header-title a.topic-link+.utags_ul_1{object-position:100% 200%;position:absolute;top:-9999px;margin-bottom:4px !important}:not(#a):not(#b):not(#c) header .header-title a.topic-link[data-utags_flag=inline]+.utags_ul_1{position:unset;margin-bottom:4px !important}:not(#a):not(#b):not(#c) header .badge-category__wrapper+.utags_ul_1{margin-top:2px !important}:not(#a):not(#b):not(#c) #topic-title a.fancy-title+.utags_ul_1{margin-bottom:8px !important}:not(#a):not(#b):not(#c) #topic-title .discourse-tag+.utags_ul_1{margin-top:5px !important}:not(#a):not(#b):not(#c) .topic-body .topic-meta-data .names[data-utags_fit_content="1"]{max-width:max-content !important}:not(#a):not(#b):not(#c) .topic-body .topic-meta-data .names[data-utags_fit_content="1"] *:not(svg){width:fit-content !important}:not(#a):not(#b):not(#c) .topic-body .topic-meta-data .names a+.utags_ul_1{object-position:0% 200%;position:absolute;top:-9999px;z-index:100}:not(#a):not(#b):not(#c) .post-links-container .post-links .track-link[data-utags_fit_content="1"]{max-width:max-content !important;max-height:max-content !important}:not(#a):not(#b):not(#c) .user-card .names[data-utags_fit_content="1"]{max-width:max-content !important;max-height:max-content !important}:not(#a):not(#b):not(#c) .user-card .names a.user-profile-link+.utags_ul_0{object-position:200% 0%;margin-top:6px !important}:not(#a):not(#b):not(#c) .user-card .names a.user-profile-link+.utags_ul_1{object-position:0% 200%;position:absolute;top:-9999px;margin-left:16px !important}:not(#a):not(#b):not(#c) .column .category-list .category-title-link+.utags_ul_1{object-position:200% 50%;position:absolute;top:-9999px}:not(#a):not(#b):not(#c) .column .latest-topic-list .main-link .title+.utags_ul_1{margin-bottom:4px !important}:not(#a):not(#b):not(#c) .column .latest-topic-list .main-link .badge-category__wrapper+.utags_ul_1{padding-top:3px !important}:not(#a):not(#b):not(#c) .column .latest-topic-list .main-link .discourse-tag+.utags_ul_1{margin-top:4px !important}:not(#a):not(#b):not(#c) .column .latest-topic-list .topic-poster a+.utags_ul_0{object-position:0% 200%;--utags-notag-captain-tag-top: 13px;--utags-notag-captain-tag-left: -4px}:not(#a):not(#b):not(#c) .column .latest-topic-list .topic-poster a+.utags_ul_1{object-position:0% 200%;position:absolute;top:-9999px;margin-top:17px !important;margin-left:0px !important}:not(#a):not(#b):not(#c) .search-container{--utags-list-node-display: flex}:not(#a):not(#b):not(#c) .search-container .search-link[data-utags_fit_content="1"]{display:inline-block !important;width:fit-content !important}:not(#a):not(#b):not(#c) .search-container .search-link[data-utags_fit_content="1"] *:not(svg){width:fit-content !important}:not(#a):not(#b):not(#c) .search-container .search-link+.utags_ul_1{object-position:0% 0%;position:absolute;top:-9999px;margin-top:-14px !important}:not(#a):not(#b):not(#c) .search-container .search-results .author a+.utags_ul_0{object-position:0% 200%;--utags-notag-captain-tag-top: 13px;--utags-notag-captain-tag-left: -4px}:not(#a):not(#b):not(#c) .search-container .search-results .author a+.utags_ul_1{object-position:0% 200%;position:absolute;top:-9999px;margin-top:17px !important;margin-left:0px !important}:not(#a):not(#b):not(#c) .user-info .user-detail .name-line a[data-utags_fit_content="1"]{display:inline-block !important;width:fit-content !important}:not(#a):not(#b):not(#c) .user-info .user-detail .name-line a[data-utags_fit_content="1"] *:not(svg){width:fit-content !important}:not(#a):not(#b):not(#c) .bookmark-list.topic-list tr a.avatar+.utags_ul_0{object-position:0% 200%;--utags-notag-captain-tag-top: 6px}:not(#a):not(#b):not(#c) .bookmark-list.topic-list tr a.avatar+.utags_ul_1{position:absolute;top:-9999px;margin-top:10px !important}:not(#a):not(#b):not(#c) .user-content .user-stream-item__header a.avatar-link+.utags_ul_0,:not(#a):not(#b):not(#c) .user-content .filter-1 .post-list-item .post-list-item__header a.avatar-link+.utags_ul_0{object-position:0% 200%;--utags-notag-captain-tag-top: -4px;--utags-notag-captain-tag-left: -4px}:not(#a):not(#b):not(#c) .user-content .user-stream-item__header a.avatar-link+.utags_ul_1,:not(#a):not(#b):not(#c) .user-content .filter-1 .post-list-item .post-list-item__header a.avatar-link+.utags_ul_1{object-position:0% 200%;position:absolute;top:-9999px;margin-top:2px !important;margin-left:0px !important}:not(#a):not(#b):not(#c) .search-menu .results{position:relative}:not(#a):not(#b):not(#c) .search-menu .results .search-link+.utags_ul_0{object-position:0% 200%;--utags-notag-captain-tag-top: -14px;--utags-notag-captain-tag-left: -4px}:not(#a):not(#b):not(#c) .user-profile-names [data-utags][data-utags_fit_content="1"]{display:inline-block !important;width:fit-content !important}:not(#a):not(#b):not(#c) .user-profile-names [data-utags][data-utags_fit_content="1"] *:not(svg){width:fit-content !important}:not(#a):not(#b):not(#c) .leaderboard .winner{padding-bottom:50px}:not(#a):not(#b):not(#c) .leaderboard .winner .winner__avatar[data-user-card]+.utags_ul_0{object-position:0% 200%;--utags-notag-captain-tag-top: -56px;--utags-notag-captain-tag-left: -4px}:not(#a):not(#b):not(#c) .leaderboard .winner .winner__avatar[data-user-card]+.utags_ul_1{object-position:0% 200%;position:absolute;top:-9999px;margin-top:-56px !important;margin-left:0px !important}:not(#a):not(#b):not(#c) .notification a[data-utags_fit_content="1"]{display:inline-flex !important;width:fit-content !important}:not(#a):not(#b):not(#c) .notification a[data-utags_fit_content="1"] *:not(svg){width:fit-content !important}:not(#a):not(#b):not(#c) .notification a+.utags_ul_1{object-position:0% 200%;position:absolute;top:-9999px;margin-top:-6px !important;margin-left:42px !important}:not(#a):not(#b):not(#c) [data-utags_list_node]:last-of-type{display:var(--utags-list-node-display) !important}:not(#a):not(#b):not(#c) .user-menu.revamped .menu-tabs-container{z-index:91;background-color:var(--secondary)}.mobile-view:not(#a):not(#b):not(#c) .topic-list a[data-user-card]+.utags_ul_0{object-position:0% 200%;--utags-notag-captain-tag-top: 14px;--utags-notag-captain-tag-left: -8px}.mobile-view:not(#a):not(#b):not(#c) .topic-list a[data-user-card]+.utags_ul_1{object-position:0% 200%;position:absolute;top:-9999px;margin-top:18px !important;margin-left:-4px !important;max-width:58px !important}.mobile-view:not(#a):not(#b):not(#c) .topic-body .topic-meta-data .names a+.utags_ul_0{object-position:0% 200%;--utags-notag-captain-tag-top: -4px;--utags-notag-captain-tag-left: -4px}.mobile-view:not(#a):not(#b):not(#c) .topic-body .topic-meta-data .names a+.utags_ul_1{object-position:0% 200%;position:absolute;top:-9999px;z-index:100}'
  4744. var discourse_default2 = (() => {
  4745. const prefix3 = location.origin + "/"
  4746. const getUserProfileUrl = (url, exact = false) => {
  4747. if (url.startsWith(prefix3)) {
  4748. const href2 = url.slice(prefix3.length).toLowerCase()
  4749. if (exact) {
  4750. if (/^u\/[\w.-]+([?#].*)?$/.test(href2)) {
  4751. return prefix3 + href2.replace(/^(u\/[\w.-]+).*/, "$1")
  4752. }
  4753. } else if (/^u\/[\w.-]+/.test(href2)) {
  4754. return prefix3 + href2.replace(/^(u\/[\w.-]+).*/, "$1")
  4755. }
  4756. }
  4757. return void 0
  4758. }
  4759. function getPostUrl(url, exact = false) {
  4760. if (url.startsWith(prefix3)) {
  4761. const href2 = url.slice(prefix3.length).toLowerCase()
  4762. if (exact) {
  4763. if (/^t\/[^/]+\/\d+(\/\d+)?([?#].*)?$/.test(href2)) {
  4764. return prefix3 + href2.replace(/^(t\/[^/]+\/\d+).*/, "$1")
  4765. }
  4766. } else if (/^t\/[^/]+\/\d+?/.test(href2)) {
  4767. return prefix3 + href2.replace(/^(t\/[^/]+\/\d+).*/, "$1")
  4768. }
  4769. }
  4770. return void 0
  4771. }
  4772. function getCategoryUrl(url, exact = false) {
  4773. if (url.startsWith(prefix3)) {
  4774. const href2 = url.slice(prefix3.length).toLowerCase()
  4775. if (exact) {
  4776. if (/^c\/[\w-]+(\/[\w-]+)?\/\d+([?#].*)?$/.test(href2)) {
  4777. return (
  4778. prefix3 + href2.replace(/^(c\/[\w-]+(\/[\w-]+)?\/\d+).*/, "$1")
  4779. )
  4780. }
  4781. } else if (/^c\/[\w-]+(\/[\w-]+)?\/\d+?/.test(href2)) {
  4782. return prefix3 + href2.replace(/^(c\/[\w-]+(\/[\w-]+)?\/\d+).*/, "$1")
  4783. }
  4784. }
  4785. return void 0
  4786. }
  4787. function getTagUrl(url, exact = false) {
  4788. if (url.startsWith(prefix3)) {
  4789. const href2 = url.slice(prefix3.length).toLowerCase()
  4790. if (exact) {
  4791. if (/^tag\/[^/?#]+([?#].*)?$/.test(href2)) {
  4792. return prefix3 + href2.replace(/^(tag\/[^/?#]+).*/, "$1")
  4793. }
  4794. } else if (/^tag\/[^/?#]+?/.test(href2)) {
  4795. return prefix3 + href2.replace(/^(tag\/[^/?#]+).*/, "$1")
  4796. }
  4797. }
  4798. return void 0
  4799. }
  4800. return {
  4801. matches:
  4802. /meta\.discourse\.org|linux\.do|meta\.appinn\.net|community\.openai\.com|community\.cloudflare\.com|community\.wanikani\.com/,
  4803. preProcess() {
  4804. setVisitedAvailable(true)
  4805. },
  4806. listNodesSelectors: [
  4807. ".topic-list .topic-list-body tr",
  4808. ".topic-area .topic-post",
  4809. ".search-results .fps-result",
  4810. ],
  4811. conditionNodesSelectors: [
  4812. ".topic-list .topic-list-body tr .title",
  4813. ".topic-list .topic-list-body tr .badge-category__wrapper",
  4814. ".topic-list .topic-list-body tr .discourse-tag",
  4815. ".topic-list .topic-list-body tr .posters a:first-of-type",
  4816. ".mobile-view .topic-list a[data-user-card]",
  4817. ".topic-area .topic-post:nth-of-type(n+2) .names a",
  4818. ".search-results .fps-result .search-link",
  4819. ".search-results .fps-result .badge-category__wrapper",
  4820. ".search-results .fps-result .discourse-tag",
  4821. ],
  4822. validate(element) {
  4823. const href = element.href
  4824. if (!href.startsWith(prefix3)) {
  4825. return true
  4826. }
  4827. let key = getUserProfileUrl(href, true)
  4828. if (key) {
  4829. const title = element.textContent.trim()
  4830. if (
  4831. !title &&
  4832. !element.closest(".topic-list tr .posters a:first-of-type") &&
  4833. !element.closest(".bookmark-list tr a.avatar") && // https://linux.do/u/neo/activity/reactions
  4834. !element.closest(
  4835. ".user-content .user-stream-item__header a.avatar-link"
  4836. ) && // https://linux.do/u/neo/activity/likes-given
  4837. !element.closest(
  4838. ".user-content .filter-1 .post-list-item .post-list-item__header a.avatar-link"
  4839. ) &&
  4840. !element.closest(".column .latest-topic-list .topic-poster a") &&
  4841. !element.closest(".search-results .author a")
  4842. ) {
  4843. return false
  4844. }
  4845. const meta = { type: "user", title }
  4846. element.utags = { key, meta }
  4847. element.dataset.utags = element.dataset.utags || ""
  4848. if (element.closest(".topic-body .names a")) {
  4849. element.dataset.utags_position_selector = ".topic-body .names"
  4850. } else if (element.closest(".user-card .names a")) {
  4851. element.dataset.utags_position_selector = ".user-card .names"
  4852. }
  4853. return true
  4854. }
  4855. key = getPostUrl(href)
  4856. if (key) {
  4857. const title = element.textContent.trim()
  4858. if (
  4859. element.closest(".mobile-view .topic-list a[data-user-card]") &&
  4860. element.dataset.userCard
  4861. ) {
  4862. const title2 = element.dataset.userCard
  4863. key = prefix3 + "u/" + title2.toLowerCase()
  4864. const meta2 = { type: "user", title: title2 }
  4865. element.utags = { key, meta: meta2 }
  4866. element.dataset.utags = element.dataset.utags || ""
  4867. return true
  4868. }
  4869. if (!title) {
  4870. return false
  4871. }
  4872. if (
  4873. element.closest("header .topic-link") &&
  4874. getComputedStyle(element).display === "inline"
  4875. ) {
  4876. element.dataset.utags_flag = "inline"
  4877. }
  4878. const meta = { type: "post", title }
  4879. element.utags = { key, meta }
  4880. markElementWhetherVisited(key, element)
  4881. element.dataset.utags = element.dataset.utags || ""
  4882. return true
  4883. }
  4884. key = getCategoryUrl(href)
  4885. if (key) {
  4886. const title = element.textContent.trim()
  4887. if (!title) {
  4888. return false
  4889. }
  4890. const meta = { type: "category", title }
  4891. element.utags = { key, meta }
  4892. if (element.closest(".column .category-list .category-title-link")) {
  4893. element.dataset.utags_position_selector =
  4894. ".category-text-title .category-name"
  4895. }
  4896. return true
  4897. }
  4898. key = getTagUrl(href)
  4899. if (key) {
  4900. const title = element.textContent.trim()
  4901. if (!title) {
  4902. return false
  4903. }
  4904. const meta = { type: "tag", title }
  4905. element.utags = { key, meta }
  4906. return true
  4907. }
  4908. return true
  4909. },
  4910. excludeSelectors: [
  4911. ".topic-map",
  4912. ".names .second",
  4913. ".post-activity",
  4914. ".topic-last-activity",
  4915. ".topic-item-stats .activity",
  4916. ".topic-post-badges",
  4917. ".topic-excerpt",
  4918. ".topic-list-category-expert-tags",
  4919. ".list-vote-count",
  4920. ".post-date",
  4921. ".category__badges",
  4922. ".badge-posts",
  4923. ".topic-timeline",
  4924. ".with-timeline",
  4925. ".sidebar-wrapper",
  4926. ".topic-meta-data .post-link-arrow",
  4927. "#skip-link",
  4928. "#navigation-bar",
  4929. ".user-navigation",
  4930. ".search-menu",
  4931. "footer.category-topics-count",
  4932. '[role="tablist"]',
  4933. ".nav.nav-pills",
  4934. ".btn",
  4935. ".chat-time",
  4936. ],
  4937. validMediaSelectors: [
  4938. "a img.emoji",
  4939. "a svg.svg-string",
  4940. ".category-title-link",
  4941. ".topic-list tr .posters a:first-of-type",
  4942. ".search-results .author a .avatar",
  4943. ],
  4944. addExtraMatchedNodes(matchedNodesSet) {
  4945. var _a
  4946. const isDarkMode =
  4947. ((_a = $("header picture > source")) == null ? void 0 : _a.media) ===
  4948. "all"
  4949. doc.documentElement.dataset.utags_darkmode = isDarkMode ? "1" : "0"
  4950. let key = getUserProfileUrl(location.href)
  4951. if (key) {
  4952. for (const element2 of $$(
  4953. ".user-profile-names .username,.user-profile-names .user-profile-names__primary,.user-profile-names .user-profile-names__secondary"
  4954. )) {
  4955. delete element2.dataset.utags
  4956. delete element2.utags
  4957. }
  4958. const element =
  4959. $(".user-profile-names .username") ||
  4960. $(
  4961. ".user-profile-names .user-profile-names__primary,.user-profile-names .user-profile-names__secondary"
  4962. )
  4963. if (element) {
  4964. const title = element.textContent.trim()
  4965. if (title) {
  4966. const meta = { title, type: "user" }
  4967. element.utags = { key, meta }
  4968. matchedNodesSet.add(element)
  4969. }
  4970. }
  4971. }
  4972. key = getPostUrl(location.href)
  4973. if (key) {
  4974. addVisited(key)
  4975. }
  4976. for (const element of $$(".leaderboard div[data-user-card]")) {
  4977. const title = element.dataset.userCard
  4978. if (title) {
  4979. key = prefix3 + "u/" + title.toLowerCase()
  4980. const meta = { type: "user", title }
  4981. element.utags = { key, meta }
  4982. element.dataset.utags = element.dataset.utags || ""
  4983. element.dataset.utags_node_type = "link"
  4984. element.dataset.utags_position_selector = element.closest(".winner")
  4985. ? ".winner"
  4986. : ".user__name"
  4987. matchedNodesSet.add(element)
  4988. }
  4989. }
  4990. for (const element of $$(".chat-message span[data-user-card]")) {
  4991. const title = element.dataset.userCard
  4992. if (title) {
  4993. key = prefix3 + "u/" + title.toLowerCase()
  4994. const meta = { type: "user", title }
  4995. element.utags = { key, meta }
  4996. element.dataset.utags = element.dataset.utags || ""
  4997. element.dataset.utags_node_type = "link"
  4998. matchedNodesSet.add(element)
  4999. }
  5000. }
  5001. },
  5002. getStyle: () => discourse_default,
  5003. }
  5004. })()
  5005. var nga_cn_default = ""
  5006. var nga_cn_default2 = (() => {
  5007. const prefix3 = location.origin + "/"
  5008. function getUserProfileUrl(url) {
  5009. if (url.startsWith(prefix3)) {
  5010. const href2 = url.slice(prefix3.length).toLowerCase()
  5011. if (/^nuke\.php\?func=ucp&uid=\d+/.test(href2)) {
  5012. return (
  5013. prefix3 + href2.replace(/^(nuke\.php\?func=ucp&uid=\d+).*/, "$1")
  5014. )
  5015. }
  5016. }
  5017. return void 0
  5018. }
  5019. return {
  5020. matches: /bbs\.nga\.cn|nga\.178\.com|ngabbs\.com/,
  5021. validate(element) {
  5022. const href = element.href
  5023. if (!href.startsWith(prefix3)) {
  5024. return true
  5025. }
  5026. const key = getUserProfileUrl(href)
  5027. if (key) {
  5028. const title = element.textContent
  5029. if (!title) {
  5030. return false
  5031. }
  5032. const meta = { type: "user", title }
  5033. element.utags = { key, meta }
  5034. element.dataset.utags = element.dataset.utags || ""
  5035. return true
  5036. }
  5037. return false
  5038. },
  5039. excludeSelectors: [
  5040. ...default_default2.excludeSelectors,
  5041. ".xxxxxxxxxx",
  5042. ".xxxxxxxxxx",
  5043. ],
  5044. addExtraMatchedNodes(matchedNodesSet) {
  5045. const key = getUserProfileUrl(location.href)
  5046. if (key) {
  5047. const label = $(
  5048. "#ucpuser_info_blockContent > div > span > div:nth-child(2) > div:nth-child(3) > label"
  5049. )
  5050. if (label) {
  5051. const title = label.textContent.trim()
  5052. if (title === "\u7528\u2002\u6237\u2002\u540D") {
  5053. const element = label.nextElementSibling
  5054. if (element) {
  5055. const title2 = element.textContent.trim()
  5056. if (title2) {
  5057. const meta = { title: title2, type: "user" }
  5058. element.utags = { key, meta }
  5059. matchedNodesSet.add(element)
  5060. }
  5061. }
  5062. }
  5063. }
  5064. }
  5065. },
  5066. getStyle: () => nga_cn_default,
  5067. }
  5068. })()
  5069. var dlsite_com_default =
  5070. ':not(#a):not(#b):not(#c) *+.utags_ul_0{object-position:200% 50%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-5);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-5);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) *+.utags_ul_1{object-position:0% 200%;background-color:var(--utags-captain-tag-background-color) !important;border-radius:3px !important;--utags-emoji-tag-background-color: #fff0}:not(#a):not(#b):not(#c) .n_worklist a.work_name,:not(#a):not(#b):not(#c) .n_worklist dt.work_name,:not(#a):not(#b):not(#c) .recommend_list a.work_name,:not(#a):not(#b):not(#c) .recommend_list dt.work_name,:not(#a):not(#b):not(#c) .genre_ranking a.work_name,:not(#a):not(#b):not(#c) .genre_ranking dt.work_name{width:fit-content}:not(#a):not(#b):not(#c) .n_worklist a.work_name+.utags_ul_0,:not(#a):not(#b):not(#c) .n_worklist dt.work_name+.utags_ul_0,:not(#a):not(#b):not(#c) .recommend_list a.work_name+.utags_ul_0,:not(#a):not(#b):not(#c) .recommend_list dt.work_name+.utags_ul_0,:not(#a):not(#b):not(#c) .genre_ranking a.work_name+.utags_ul_0,:not(#a):not(#b):not(#c) .genre_ranking dt.work_name+.utags_ul_0{object-position:200% 0%}:not(#a):not(#b):not(#c) .n_worklist .maker_name,:not(#a):not(#b):not(#c) .recommend_list .maker_name,:not(#a):not(#b):not(#c) .genre_ranking .maker_name{white-space:wrap;-webkit-line-clamp:unset;height:unset}:not(#a):not(#b):not(#c) h1#work_name[data-utags_fit_content="1"]{max-width:max-content !important}'
  5071. var dlsite_com_default2 = (() => {
  5072. const prefix3 = "https://www.dlsite.com/"
  5073. function getProductUrl(url) {
  5074. if (url.startsWith(prefix3)) {
  5075. const href2 = url.slice(prefix3.length)
  5076. if (href2.includes("=/product_id/")) {
  5077. return prefix3 + href2.replace(/^(.+\.html).*/, "$1")
  5078. }
  5079. }
  5080. return void 0
  5081. }
  5082. function getMakerUrl(url) {
  5083. if (url.startsWith(prefix3)) {
  5084. const href2 = url.slice(prefix3.length)
  5085. if (href2.includes("/profile/=/maker_id/")) {
  5086. return prefix3 + href2.replace(/^(.+\.html).*/, "$1")
  5087. }
  5088. }
  5089. return void 0
  5090. }
  5091. return {
  5092. matches: /dlsite\.com/,
  5093. validate(element) {
  5094. if (element.tagName !== "A") {
  5095. return true
  5096. }
  5097. const href = element.href
  5098. if (!href.startsWith(prefix3)) {
  5099. return true
  5100. }
  5101. if (href.includes("/=/")) {
  5102. return true
  5103. }
  5104. return false
  5105. },
  5106. map(element) {
  5107. if (
  5108. element.tagName === "A" &&
  5109. element.closest(
  5110. ".n_worklist .work_name,.recommend_list dt.work_name,.genre_ranking .work_name"
  5111. )
  5112. ) {
  5113. const key = getProductUrl(element.href)
  5114. const title = element.textContent.trim()
  5115. if (!key || !title) {
  5116. return
  5117. }
  5118. const parentElement = element.parentElement
  5119. const meta = { title }
  5120. parentElement.utags = { key, meta }
  5121. parentElement.dataset.utags_node_type = "link"
  5122. return parentElement
  5123. }
  5124. },
  5125. excludeSelectors: [
  5126. ...default_default2.excludeSelectors,
  5127. "header",
  5128. "#top_header",
  5129. "#header",
  5130. ".topicpath",
  5131. ".link_dl_ch",
  5132. ".floating_cart_box",
  5133. "#work_buy_box_wrapper",
  5134. ".pagetop_block",
  5135. ".matome_btn",
  5136. ".review_all",
  5137. ".review_report",
  5138. ".work_cart",
  5139. ".work_favorite",
  5140. ".title_01",
  5141. ".search_more",
  5142. ".btn_category_sample",
  5143. ".btn_cart",
  5144. ".btn_favorite",
  5145. ".btn_follow",
  5146. ".btn_default",
  5147. ".btn_sample",
  5148. ".left_module",
  5149. ".more_work_btn",
  5150. ".heading_link",
  5151. ".work_edition",
  5152. ".work_btn_list",
  5153. ".trans_work_btn",
  5154. ".work_feature",
  5155. ".work_review",
  5156. ".work_rating",
  5157. ".work_category",
  5158. ".work_btn_link",
  5159. ".sort_box",
  5160. ".search_condition_box",
  5161. ".global_pagination",
  5162. ".page_bottom_link",
  5163. ".trial_download",
  5164. ".btn_trial",
  5165. ".work_win_only",
  5166. ".cp_overview_btn",
  5167. ".cp_overview_list",
  5168. ".option_tab_item",
  5169. ".dc_work_group_footer",
  5170. ".new_worklist_more",
  5171. "#work_win_only",
  5172. "#index2_header",
  5173. ".floor_link",
  5174. ".floor_link_creator",
  5175. ".floor_guide",
  5176. ".l-header",
  5177. ".hd_drawer",
  5178. ".index_header",
  5179. ".index_footer",
  5180. ".left_module_comipo",
  5181. "div#left",
  5182. ".footer_floor_nav",
  5183. ".prof_label_list",
  5184. ".type_btn",
  5185. ],
  5186. addExtraMatchedNodes(matchedNodesSet) {
  5187. let key = getProductUrl(location.href)
  5188. if (key) {
  5189. const element = $("h1#work_name")
  5190. if (element) {
  5191. const title = element.textContent.trim()
  5192. if (title) {
  5193. const meta = { title }
  5194. element.utags = { key, meta }
  5195. element.dataset.utags_node_type = "link"
  5196. matchedNodesSet.add(element)
  5197. }
  5198. }
  5199. }
  5200. key = getMakerUrl(location.href)
  5201. if (key) {
  5202. const element = $(".prof_maker_name")
  5203. if (element) {
  5204. const title = element.textContent.trim()
  5205. if (title) {
  5206. const meta = { title }
  5207. element.utags = { key, meta }
  5208. element.dataset.utags_node_type = "link"
  5209. matchedNodesSet.add(element)
  5210. }
  5211. }
  5212. }
  5213. },
  5214. getStyle: () => dlsite_com_default,
  5215. }
  5216. })()
  5217. var keylol_com_default =
  5218. ":not(#a):not(#b):not(#c) a+.utags_ul_0{object-position:200% 50%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-5);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-5);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) .frame-tab .dxb_bc .module{position:relative}:not(#a):not(#b):not(#c) .favatar .pi{height:unset}:not(#a):not(#b):not(#c) .ratl td:first-of-type{white-space:normal}"
  5219. var keylol_com_default2 = (() => {
  5220. const prefix3 = location.origin + "/"
  5221. function getUserProfileUrl(url, exact = false) {
  5222. if (url.startsWith(prefix3)) {
  5223. const href2 = url.slice(prefix3.length).toLowerCase()
  5224. if (exact) {
  5225. if (/^\?\d+(#.*)?$/.test(href2)) {
  5226. return (
  5227. prefix3 + href2.replace(/^\?(\d+).*/, "home.php?mod=space&uid=$1")
  5228. )
  5229. }
  5230. if (/^suid-\d+(#.*)?$/.test(href2)) {
  5231. return (
  5232. prefix3 +
  5233. href2.replace(/^suid-(\d+).*/, "home.php?mod=space&uid=$1")
  5234. )
  5235. }
  5236. if (/^home\.php\?mod=space&uid=\d+(#.*)?$/.test(href2)) {
  5237. return (
  5238. prefix3 +
  5239. href2.replace(
  5240. /^home\.php\?mod=space&uid=(\d+).*/,
  5241. "home.php?mod=space&uid=$1"
  5242. )
  5243. )
  5244. }
  5245. } else if (/^u\/[\w.-]+/.test(href2)) {
  5246. return prefix3 + href2.replace(/^(u\/[\w.-]+).*/, "$1")
  5247. }
  5248. }
  5249. return void 0
  5250. }
  5251. return {
  5252. matches: /keylol\.com/,
  5253. validate(element) {
  5254. const href = element.href
  5255. if (!href.startsWith(prefix3)) {
  5256. return true
  5257. }
  5258. const key = getUserProfileUrl(href, true)
  5259. if (key) {
  5260. const title = element.textContent
  5261. if (!title) {
  5262. return false
  5263. }
  5264. const meta = { type: "user", title }
  5265. element.utags = { key, meta }
  5266. element.dataset.utags = element.dataset.utags || ""
  5267. return true
  5268. }
  5269. return false
  5270. },
  5271. excludeSelectors: [
  5272. ...default_default2.excludeSelectors,
  5273. "nav",
  5274. "header",
  5275. "#pgt",
  5276. "#fd_page_bottom",
  5277. "#visitedforums",
  5278. "#pt",
  5279. ],
  5280. getStyle: () => keylol_com_default,
  5281. }
  5282. })()
  5283. var tampermonkey_net_cn_default =
  5284. ":not(#a):not(#b):not(#c) a+.utags_ul_0{object-position:200% 50%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-5);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-5);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) a+.utags_ul_1{object-position:0% 200%}:not(#a):not(#b):not(#c) .favatar .authi a+.utags_ul_1{position:absolute;top:-9999px;z-index:100;margin-top:0px !important;margin-left:-64px !important}:not(#a):not(#b):not(#c) .comiis_irbox a+.utags_ul_0{object-position:100% 0%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-5);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-5);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) .comiis_irbox a+.utags_ul_1{object-position:0% 0%;position:absolute;top:-9999px;z-index:100;margin-top:18px !important;margin-left:0px !important}"
  5285. var tampermonkey_net_cn_default2 = (() => {
  5286. const prefix3 = "https://bbs.tampermonkey.net.cn/"
  5287. function getCanonicalUrl2(url) {
  5288. if (url.startsWith(prefix3)) {
  5289. let href2 = getUserProfileUrl(url, true)
  5290. if (href2) {
  5291. return href2
  5292. }
  5293. href2 = getPostUrl(url, true)
  5294. if (href2) {
  5295. return href2
  5296. }
  5297. }
  5298. return url
  5299. }
  5300. function getUserProfileUrl(url, exact = false) {
  5301. if (url.startsWith(prefix3)) {
  5302. url = deleteUrlParameters(url, "do")
  5303. const href2 = url.slice(prefix3.length).toLowerCase()
  5304. if (exact) {
  5305. if (/^\?\d+(#.*)?$/.test(href2)) {
  5306. return (
  5307. prefix3 + href2.replace(/^\?(\d+).*/, "home.php?mod=space&uid=$1")
  5308. )
  5309. }
  5310. if (/^space-uid-\d+\.html([?#].*)?$/.test(href2)) {
  5311. return (
  5312. prefix3 +
  5313. href2.replace(/^space-uid-(\d+).*/, "home.php?mod=space&uid=$1")
  5314. )
  5315. }
  5316. if (/^home\.php\?mod=space&uid=\d+(#.*)?$/.test(href2)) {
  5317. return (
  5318. prefix3 +
  5319. href2.replace(
  5320. /^home\.php\?mod=space&uid=(\d+).*/,
  5321. "home.php?mod=space&uid=$1"
  5322. )
  5323. )
  5324. }
  5325. } else if (/^u\/[\w.-]+/.test(href2)) {
  5326. return prefix3 + href2.replace(/^(u\/[\w.-]+).*/, "$1")
  5327. }
  5328. }
  5329. return void 0
  5330. }
  5331. function getPostUrl(url) {
  5332. if (url.startsWith(prefix3)) {
  5333. const href2 = url.slice(prefix3.length).toLowerCase()
  5334. if (/^thread(?:-\d+){3}\.html([?#].*)?$/.test(href2)) {
  5335. return (
  5336. prefix3 +
  5337. href2.replace(/^thread-(\d+).*/, "forum.php?mod=viewthread&tid=$1")
  5338. )
  5339. }
  5340. if (/^forum\.php\?mod=redirect&tid=\d+([&#].*)?$/.test(href2)) {
  5341. return (
  5342. prefix3 +
  5343. href2.replace(
  5344. /^forum\.php\?mod=redirect&tid=(\d+).*/,
  5345. "forum.php?mod=viewthread&tid=$1"
  5346. )
  5347. )
  5348. }
  5349. if (/^forum\.php\?mod=viewthread&tid=\d+(#.*)?$/.test(href2)) {
  5350. return (
  5351. prefix3 +
  5352. href2.replace(
  5353. /^forum\.php\?mod=viewthread&tid=(\d+).*/,
  5354. "forum.php?mod=viewthread&tid=$1"
  5355. )
  5356. )
  5357. }
  5358. }
  5359. return void 0
  5360. }
  5361. return {
  5362. matches: /bbs\.tampermonkey\.net\.cn/,
  5363. preProcess() {
  5364. setVisitedAvailable(true)
  5365. },
  5366. listNodesSelectors: [
  5367. //
  5368. "#threadlist table tbody",
  5369. "#postlist .comiis_vrx",
  5370. ],
  5371. conditionNodesSelectors: [
  5372. //
  5373. "#threadlist table tbody h2 a",
  5374. "#threadlist table tbody .km_user a",
  5375. "#postlist .comiis_vrx .authi a",
  5376. ],
  5377. validate(element) {
  5378. const href = element.href
  5379. if (!href.startsWith(prefix3)) {
  5380. return true
  5381. }
  5382. let key = getUserProfileUrl(href, true)
  5383. if (key) {
  5384. let title2 = element.textContent.trim()
  5385. if (!title2) {
  5386. return false
  5387. }
  5388. if (/^https:\/\/bbs\.tampermonkey\.net\.cn\/\?\d+$/.test(title2)) {
  5389. const titleElement = $("#uhd h2")
  5390. if (titleElement) {
  5391. title2 = titleElement.textContent.trim()
  5392. }
  5393. }
  5394. if (
  5395. /^\d+$/.test(title2) &&
  5396. element.parentElement.parentElement.textContent.includes(
  5397. "\u79EF\u5206"
  5398. )
  5399. ) {
  5400. return false
  5401. }
  5402. const meta =
  5403. href === title2 ? { type: "user" } : { type: "user", title: title2 }
  5404. element.utags = { key, meta }
  5405. element.dataset.utags = element.dataset.utags || ""
  5406. return true
  5407. }
  5408. key = getPostUrl(href)
  5409. if (key) {
  5410. const title2 = element.textContent.trim()
  5411. if (!title2) {
  5412. return false
  5413. }
  5414. if (
  5415. title2 === "New" ||
  5416. title2 === "\u7F6E\u9876" ||
  5417. /^\d+$/.test(title2) ||
  5418. /^\d{4}(?:-\d{1,2}){2} \d{2}:\d{2}$/.test(title2)
  5419. ) {
  5420. return false
  5421. }
  5422. if ($('span[title^="20"]', element)) {
  5423. return false
  5424. }
  5425. if (
  5426. element.parentElement.textContent.includes(
  5427. "\u6700\u540E\u56DE\u590D\u4E8E"
  5428. )
  5429. ) {
  5430. return false
  5431. }
  5432. const meta =
  5433. href === title2 ? { type: "post" } : { type: "post", title: title2 }
  5434. element.utags = { key, meta }
  5435. markElementWhetherVisited(key, element)
  5436. return true
  5437. }
  5438. const title = element.textContent.trim()
  5439. if (!title) {
  5440. return false
  5441. }
  5442. if (
  5443. title === "New" ||
  5444. title === "\u7F6E\u9876" ||
  5445. /^\d+$/.test(title)
  5446. ) {
  5447. return false
  5448. }
  5449. return true
  5450. },
  5451. excludeSelectors: [
  5452. ...default_default2.excludeSelectors,
  5453. "#hd",
  5454. ".comiis_pgs",
  5455. "#scrolltop",
  5456. "#fd_page_bottom",
  5457. "#visitedforums",
  5458. "#pt",
  5459. ".tps",
  5460. ".pgbtn",
  5461. ".pgs",
  5462. "#f_pst",
  5463. 'a[href*="member.php?mod=logging"]',
  5464. 'a[href*="member.php?mod=register"]',
  5465. 'a[href*="login/oauth/"]',
  5466. 'a[href*="mod=spacecp&ac=usergroup"]',
  5467. 'a[href*="home.php?mod=spacecp"]',
  5468. "#gadmin_menu",
  5469. "#guser_menu",
  5470. "#gupgrade_menu",
  5471. "#gmy_menu",
  5472. ".showmenu",
  5473. "ul.tb.cl",
  5474. ".comiis_irbox_tit",
  5475. "#thread_types",
  5476. "#filter_special_menu",
  5477. 'a[title="RSS"]',
  5478. ".fa_fav",
  5479. ".p_pop",
  5480. ".comiis_topinfo",
  5481. ".bm .bm_h .kmfz",
  5482. "td.num a",
  5483. "td.plc .pi",
  5484. "td.plc .po.hin",
  5485. "td.pls .tns",
  5486. "ul.comiis_o",
  5487. 'a[onclick*="showMenu"]',
  5488. 'a[onclick*="showWindow"]',
  5489. ".toplist_7ree",
  5490. ],
  5491. addExtraMatchedNodes(matchedNodesSet) {
  5492. let key = getUserProfileUrl(location.href)
  5493. if (key) {
  5494. const element =
  5495. $(".user-profile-names .username") ||
  5496. $(
  5497. ".user-profile-names .user-profile-names__primary,.user-profile-names .user-profile-names__secondary"
  5498. )
  5499. if (element) {
  5500. const title = element.textContent.trim()
  5501. if (title) {
  5502. const meta = { title, type: "user" }
  5503. element.utags = { key, meta }
  5504. matchedNodesSet.add(element)
  5505. }
  5506. }
  5507. }
  5508. key = getPostUrl(location.href)
  5509. if (key) {
  5510. addVisited(key)
  5511. const element = $("#thread_subject")
  5512. if (element) {
  5513. const title = element.textContent.trim()
  5514. if (title) {
  5515. const meta = { title, type: "post" }
  5516. element.utags = { key, meta }
  5517. matchedNodesSet.add(element)
  5518. }
  5519. }
  5520. }
  5521. },
  5522. getStyle: () => tampermonkey_net_cn_default,
  5523. getCanonicalUrl: getCanonicalUrl2,
  5524. }
  5525. })()
  5526. var flarum_default =
  5527. ':not(#a):not(#b):not(#c) *+.utags_ul_0{object-position:200% 50%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-5);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-5);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) *+.utags_ul_1{object-position:0% 200%}:not(#a):not(#b):not(#c) a.DiscussionListItem-main+.utags_ul_1{object-position:200% 50%;position:absolute;top:-9999px;margin-top:0px !important;margin-left:0px !important}:not(#a):not(#b):not(#c) a.DiscussionListItem-author+.utags_ul_0{object-position:0% 0%;--utags-notag-captain-tag-top: -22px}:not(#a):not(#b):not(#c) a.DiscussionListItem-author+.utags_ul_1{object-position:0% 0%;position:absolute;top:-9999px;margin-top:-18px !important;margin-left:0px !important}:not(#a):not(#b):not(#c) .DiscussionList--searchResults a.DiscussionListItem-main+.utags_ul_0{object-position:0% 200%;--utags-notag-captain-tag-top: -18px}:not(#a):not(#b):not(#c) .DiscussionList--searchResults a.DiscussionListItem-main+.utags_ul_1{object-position:0% 200%;position:absolute;top:-9999px;margin-top:-14px !important;margin-left:0px !important}:not(#a):not(#b):not(#c) .TagTiles a.TagTile-info+.utags_ul_0{object-position:0% 0%}:not(#a):not(#b):not(#c) .TagTiles a.TagTile-info+.utags_ul_1{object-position:0% 0%;position:absolute;top:-9999px;margin-top:0px !important;margin-left:0px !important}:not(#a):not(#b):not(#c) .TagTiles a.TagTile-lastPostedDiscussion+.utags_ul_1{object-position:200% 50%;position:absolute;top:-9999px;margin-top:0px !important;margin-left:0px !important}:not(#a):not(#b):not(#c) h1.Hero-title[data-utags_fit_content="1"]{display:inline-block !important;width:fit-content !important}:not(#a):not(#b):not(#c) h1.Hero-title[data-utags_fit_content="1"] *:not(svg){width:fit-content !important}:not(#a):not(#b):not(#c) h1.Hero-title+.utags_ul_0{object-position:200% 50%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-5);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-5);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) h1.Hero-title+.utags_ul_1{object-position:200% 50%;position:absolute;top:-9999px;margin-top:0px !important;margin-left:0px !important}:not(#a):not(#b):not(#c) .PostStream .PostStream-item[data-index="0"]{display:block !important}:not(#a):not(#b):not(#c) .UserBio .UserBio-content p{position:relative}'
  5528. var flarum_default2 = (() => {
  5529. const prefix3 = location.origin + "/"
  5530. function getUserProfileUrl(url, exact = false) {
  5531. if (url.startsWith(prefix3)) {
  5532. const href2 = url.slice(prefix3.length).toLowerCase()
  5533. if (exact) {
  5534. if (/^u\/[\w-]+([?#].*)?$/.test(href2)) {
  5535. return prefix3 + href2.replace(/^(u\/[\w-]+).*/, "$1")
  5536. }
  5537. } else if (/^u\/[\w-]+/.test(href2)) {
  5538. return prefix3 + href2.replace(/^(u\/[\w-]+).*/, "$1")
  5539. }
  5540. }
  5541. return void 0
  5542. }
  5543. function getPostUrl(url, exact = false) {
  5544. if (url.startsWith(prefix3)) {
  5545. const href2 = url.slice(prefix3.length).toLowerCase()
  5546. if (exact) {
  5547. if (/^d\/\d+(?:-[^/?]+)?(?:\/\d+)?([?#].*)?$/.test(href2)) {
  5548. return prefix3 + href2.replace(/^(d\/\d+).*/, "$1")
  5549. }
  5550. } else if (/^d\/\d+(?:-[^/?]+)?/.test(href2)) {
  5551. return prefix3 + href2.replace(/^(d\/\d+).*/, "$1")
  5552. }
  5553. }
  5554. return void 0
  5555. }
  5556. function getTagUrl(url, exact = false) {
  5557. if (url.startsWith(prefix3)) {
  5558. const href2 = url.slice(prefix3.length).toLowerCase()
  5559. if (exact) {
  5560. if (/^t\/[\w-]+([?#].*)?$/.test(href2)) {
  5561. return prefix3 + href2.replace(/^(t\/[\w-]+).*/, "$1")
  5562. }
  5563. } else if (/^t\/[\w-]+/.test(href2)) {
  5564. return prefix3 + href2.replace(/^(t\/[\w-]+).*/, "$1")
  5565. }
  5566. }
  5567. return void 0
  5568. }
  5569. return {
  5570. matches:
  5571. /discuss\.flarum\.org|discuss\.flarum\.org\.cn|www\.nodeloc\.com|freesmth\.net|freesmth\.uk|veryfb\.com|kater\.me|bbs\.viva-la-vita\.org/,
  5572. preProcess() {
  5573. setVisitedAvailable(true)
  5574. },
  5575. listNodesSelectors: [
  5576. "ul.DiscussionList-discussions li",
  5577. ".hotDiscussion-content ul li",
  5578. ".PostStream .PostStream-item",
  5579. ],
  5580. conditionNodesSelectors: [
  5581. "ul.DiscussionList-discussions li a",
  5582. ".hotDiscussion-content ul li a",
  5583. ".PostStream .PostStream-item .PostUser-name a",
  5584. ],
  5585. validate(element) {
  5586. const href = element.href
  5587. if (!href.startsWith(prefix3)) {
  5588. return true
  5589. }
  5590. let key = getUserProfileUrl(href, true)
  5591. if (key) {
  5592. const titleElement = $(".GroupList-UserList-user .username", element)
  5593. const title = (titleElement || element).textContent.trim()
  5594. const meta = { type: "user", title }
  5595. element.utags = { key, meta }
  5596. element.dataset.utags = element.dataset.utags || ""
  5597. if (titleElement) {
  5598. element.dataset.utags_position_selector =
  5599. ".GroupList-UserList-user .username"
  5600. }
  5601. return true
  5602. }
  5603. key = getPostUrl(href, true)
  5604. if (key) {
  5605. const titleElement =
  5606. $(".DiscussionListItem-title", element) ||
  5607. $(".TagTile-lastPostedDiscussion-title", element)
  5608. const title = (titleElement || element).textContent.trim()
  5609. if (!title) {
  5610. return false
  5611. }
  5612. const meta = { type: "post", title }
  5613. element.utags = { key, meta }
  5614. element.dataset.utags = element.dataset.utags || ""
  5615. markElementWhetherVisited(key, element)
  5616. if (titleElement) {
  5617. element.dataset.utags_position_selector = hasClass(
  5618. element,
  5619. "TagTile-lastPostedDiscussion"
  5620. )
  5621. ? "time"
  5622. : ".item-terminalPost"
  5623. }
  5624. return true
  5625. }
  5626. key = getTagUrl(href)
  5627. if (key) {
  5628. const title = element.textContent.trim()
  5629. if (!title) {
  5630. return false
  5631. }
  5632. const meta = { type: "tag", title }
  5633. element.utags = { key, meta }
  5634. element.dataset.utags = element.dataset.utags || ""
  5635. return true
  5636. }
  5637. return true
  5638. },
  5639. excludeSelectors: [
  5640. ...default_default2.excludeSelectors,
  5641. "header.App-header",
  5642. ".sideNav",
  5643. ".PostMention",
  5644. ".Post-mentionedBy",
  5645. ".Post-mentionedBy-preview",
  5646. ".PostMention-preview",
  5647. ".Dropdown-menu",
  5648. ".Button",
  5649. ],
  5650. addExtraMatchedNodes(matchedNodesSet) {
  5651. var _a
  5652. const isDarkMode =
  5653. ((_a = $('meta[name="color-scheme"]')) == null
  5654. ? void 0
  5655. : _a.content) === "dark"
  5656. doc.documentElement.dataset.utags_darkmode = isDarkMode ? "1" : "0"
  5657. let key = getPostUrl(location.href)
  5658. if (key) {
  5659. addVisited(key)
  5660. const element = $(".item-title h1")
  5661. if (element) {
  5662. const title = element.textContent.trim()
  5663. if (title) {
  5664. const meta = { title, type: "post" }
  5665. element.utags = { key, meta }
  5666. element.dataset.utags_node_type = "link"
  5667. matchedNodesSet.add(element)
  5668. markElementWhetherVisited(key, element)
  5669. }
  5670. }
  5671. }
  5672. key = getTagUrl(location.href)
  5673. if (key) {
  5674. const element = $("h1.Hero-title")
  5675. if (element) {
  5676. const title = element.textContent.trim()
  5677. if (title) {
  5678. const meta = { title, type: "tag" }
  5679. element.utags = { key, meta }
  5680. element.dataset.utags_node_type = "link"
  5681. matchedNodesSet.add(element)
  5682. }
  5683. }
  5684. }
  5685. },
  5686. getStyle: () => flarum_default,
  5687. }
  5688. })()
  5689. var nodeseek_com_default =
  5690. ":not(#a):not(#b):not(#c) a+.utags_ul_0{object-position:200% 50%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-5);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-5);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) a+.utags_ul_1{object-position:0% 200%}:not(#a):not(#b):not(#c) ul.post-list li.post-list-item{--utags-list-node-display: flex}:not(#a):not(#b):not(#c) ul.post-list li.post-list-item a.post-category+.utags_ul_0{object-position:-100% 50%}:not(#a):not(#b):not(#c) ul.post-list li.post-list-item a.post-category+.utags_ul_1{object-position:-100% 50%;position:absolute;top:-9999px}:not(#a):not(#b):not(#c) .nsk-post-wrapper .author-info ul.utags_ul_1{vertical-align:middle !important}:not(#a):not(#b):not(#c) .nsk-post-wrapper .author-info ul.utags_ul_1 a.utags_text_tag{height:15px !important}:not(#a):not(#b):not(#c) .hover-user-card{z-index:100}"
  5691. var nodeseek_com_default2 = (() => {
  5692. const prefix3 = location.origin + "/"
  5693. function getUserProfileUrl(url, exact = false) {
  5694. if (url.startsWith(prefix3)) {
  5695. const href2 = url.slice(prefix3.length).toLowerCase()
  5696. if (exact) {
  5697. if (/^space\/\d+([?#].*)?$/.test(href2)) {
  5698. return prefix3 + href2.replace(/^(space\/\d+).*/, "$1")
  5699. }
  5700. } else if (/^space\/\d+/.test(href2)) {
  5701. return prefix3 + href2.replace(/^(space\/\d+).*/, "$1")
  5702. }
  5703. }
  5704. return void 0
  5705. }
  5706. function getPostUrl(url, exact = false) {
  5707. if (url.startsWith(prefix3)) {
  5708. const href2 = url.slice(prefix3.length).toLowerCase()
  5709. if (exact) {
  5710. if (/^post-\d+-\d+([?#].*)?$/.test(href2)) {
  5711. return prefix3 + href2.replace(/^(post-\d+)-.*/, "$1") + "-1"
  5712. }
  5713. } else if (/^post-\d+-\d+/.test(href2)) {
  5714. return prefix3 + href2.replace(/^(post-\d+)-.*/, "$1") + "-1"
  5715. }
  5716. }
  5717. return void 0
  5718. }
  5719. function getCategoryUrl(url, exact = false) {
  5720. if (url.startsWith(prefix3)) {
  5721. const href2 = url.slice(prefix3.length).toLowerCase()
  5722. if (exact) {
  5723. if (/^categories\/[\w-]+([?#].*)?$/.test(href2)) {
  5724. return prefix3 + href2.replace(/^(categories\/[\w-]+).*/, "$1")
  5725. }
  5726. } else if (/^categories\/[\w-]+/.test(href2)) {
  5727. return prefix3 + href2.replace(/^(categories\/[\w-]+).*/, "$1")
  5728. }
  5729. }
  5730. return void 0
  5731. }
  5732. return {
  5733. matches: /www\.nodeseek\.com/,
  5734. preProcess() {
  5735. setVisitedAvailable(true)
  5736. },
  5737. listNodesSelectors: [
  5738. "ul.post-list li.post-list-item",
  5739. "ul.comments li.content-item",
  5740. ],
  5741. conditionNodesSelectors: [
  5742. "ul.post-list li.post-list-item .post-title a",
  5743. "ul.post-list li.post-list-item .info-author a",
  5744. "ul.post-list li.post-list-item a.post-category",
  5745. "ul.comments li.content-item a.author-name",
  5746. ],
  5747. validate(element) {
  5748. const href = element.href
  5749. if (!href.startsWith(prefix3)) {
  5750. return true
  5751. }
  5752. let key = getUserProfileUrl(href, true)
  5753. if (key) {
  5754. const title = element.textContent.trim()
  5755. if (!title) {
  5756. return false
  5757. }
  5758. const meta = { type: "user", title }
  5759. element.utags = { key, meta }
  5760. return true
  5761. }
  5762. key = getPostUrl(href, true)
  5763. if (key) {
  5764. const title = element.textContent.trim()
  5765. if (!title || /^#\d+$/.test(title)) {
  5766. return false
  5767. }
  5768. const meta = { type: "post", title }
  5769. element.utags = { key, meta }
  5770. markElementWhetherVisited(key, element)
  5771. return true
  5772. }
  5773. key = getCategoryUrl(href)
  5774. if (key) {
  5775. const title = element.textContent.trim()
  5776. if (!title) {
  5777. return false
  5778. }
  5779. const meta = { type: "category", title }
  5780. element.utags = { key, meta }
  5781. return true
  5782. }
  5783. return true
  5784. },
  5785. excludeSelectors: [
  5786. ...default_default2.excludeSelectors,
  5787. "header",
  5788. '[aria-label="pagination"]',
  5789. 'a[href="/signIn.html"]',
  5790. 'a[href="/register.html"]',
  5791. 'a[href^="/notification"]',
  5792. ".info-last-comment-time",
  5793. ".floor-link",
  5794. ".avatar-wrapper",
  5795. ".select-item",
  5796. ".card-item",
  5797. ".nsk-new-member-board",
  5798. ".hover-user-card .user-stat",
  5799. ".btn",
  5800. ],
  5801. validMediaSelectors: ["svg.iconpark-icon"],
  5802. addExtraMatchedNodes(matchedNodesSet) {
  5803. const isDarkMode = hasClass(doc.body, "dark-layout")
  5804. doc.documentElement.dataset.utags_darkmode = isDarkMode ? "1" : "0"
  5805. let key = getUserProfileUrl(location.href)
  5806. if (key) {
  5807. const element = $("h1.username")
  5808. if (element) {
  5809. const title = element.textContent.trim()
  5810. if (title) {
  5811. const meta = { title, type: "user" }
  5812. element.utags = { key, meta }
  5813. matchedNodesSet.add(element)
  5814. }
  5815. }
  5816. }
  5817. key = getPostUrl(location.href)
  5818. if (key) {
  5819. addVisited(key)
  5820. }
  5821. },
  5822. getStyle: () => nodeseek_com_default,
  5823. }
  5824. })()
  5825. var inoreader_com_default =
  5826. ':not(#a):not(#b):not(#c) a+.utags_ul_0{object-position:200% 50%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-5);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-5);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) a+.utags_ul_1{object-position:0% 200%}:not(#a):not(#b):not(#c) .article_tile_footer_feed_title a+.utags_ul_1{position:absolute;top:-9999px;margin-top:-4px !important}:not(#a):not(#b):not(#c) .article_tile[data-utags_list_node^=","] .article_tile_content_wraper{position:unset}:not(#a):not(#b):not(#c) .ar .column_view_title a[data-utags_fit_content="1"],:not(#a):not(#b):not(#c) .article_tile a.article_title_link[data-utags_fit_content="1"],:not(#a):not(#b):not(#c) .article_magazine a.article_magazine_title_link[data-utags_fit_content="1"],:not(#a):not(#b):not(#c) .ar.article_card .article-details a.article_title_link[data-utags_fit_content="1"]{display:inline-block !important;width:fit-content !important}:not(#a):not(#b):not(#c) .article_full_contents div.article_title+.utags_ul_0{object-position:0% -100%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-5);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-5);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) .article_full_contents div.article_title+.utags_ul_1{object-position:0% -100%;position:absolute;top:-9999px;margin-top:0px !important}:not(#a):not(#b):not(#c) #search_content a.featured_category+.utags_ul_1{position:absolute;top:-9999px;z-index:100;margin-top:2px !important}:not(#a):not(#b):not(#c) #search_content a.search_feed_article+.utags_ul_1{position:absolute;top:-9999px;z-index:100;margin-top:2px !important}'
  5827. var inoreader_com_default2 = (() => {
  5828. const prefix3 = location.origin + "/"
  5829. function getArticleUrl(url) {
  5830. if (url.startsWith(prefix3)) {
  5831. const href2 = url.slice(prefix3.length).toLowerCase()
  5832. if (/^article\/\w+(-[^?#]*)?([?#].*)?$/.test(href2)) {
  5833. return prefix3 + href2.replace(/^(article\/\w+)-.*/, "$1")
  5834. }
  5835. }
  5836. return void 0
  5837. }
  5838. return {
  5839. matches: /\w+\.inoreader\.com/,
  5840. listNodesSelectors: [".ar"],
  5841. conditionNodesSelectors: [
  5842. ".article_tile .article_tile_footer_feed_title a",
  5843. ".article_tile a.article_title_link",
  5844. ".article_magazine .article_magazine_feed_title a",
  5845. ".article_magazine a.article_magazine_title_link",
  5846. ".ar .column_view_title a",
  5847. ".ar .article_title_wrapper a",
  5848. ".ar.article_card .article_sub_title a",
  5849. ".ar.article_card a.article_title_link",
  5850. ],
  5851. validate(element) {
  5852. const href = element.href
  5853. if (!href.startsWith(prefix3)) {
  5854. return true
  5855. }
  5856. if (element.closest("#search_content .featured_category")) {
  5857. element.dataset.utags_position_selector = "span"
  5858. }
  5859. const key = getArticleUrl(href)
  5860. if (key) {
  5861. const title = element.textContent.trim()
  5862. if (!title) {
  5863. return false
  5864. }
  5865. const meta = { type: "article", title }
  5866. element.utags = { key, meta }
  5867. element.dataset.utags = element.dataset.utags || ""
  5868. if (element.closest(".search_feed_article")) {
  5869. element.dataset.utags_position_selector = "h6"
  5870. }
  5871. return true
  5872. }
  5873. return true
  5874. },
  5875. excludeSelectors: [
  5876. ...default_default2.excludeSelectors,
  5877. "#side-nav",
  5878. 'a[href^="/preferences"]',
  5879. 'a[href^="/upgrade"]',
  5880. 'a[href^="/login"]',
  5881. 'a[href^="/signup"]',
  5882. 'a[href^="/sign_up"]',
  5883. 'a[href^="/forgot-password"]',
  5884. "#preference-section-content",
  5885. "#preference-section-settings",
  5886. ".inno_tabs_tab",
  5887. ".profile_checklist",
  5888. ".gadget_overview_feed_title",
  5889. ".header_name",
  5890. ],
  5891. addExtraMatchedNodes(matchedNodesSet) {
  5892. const key = getArticleUrl(location.href)
  5893. if (key) {
  5894. const element = $(".article_full_contents div.article_title")
  5895. if (element) {
  5896. const title = element.textContent.trim()
  5897. if (title) {
  5898. const meta = { title, type: "article" }
  5899. element.utags = { key, meta }
  5900. matchedNodesSet.add(element)
  5901. }
  5902. }
  5903. }
  5904. },
  5905. postProcess() {
  5906. const isDarkMode = hasClass(doc.body, "theme_dark")
  5907. doc.documentElement.dataset.utags_darkmode = isDarkMode ? "1" : "0"
  5908. },
  5909. getStyle: () => inoreader_com_default,
  5910. }
  5911. })()
  5912. var pornhub_com_default =
  5913. ':not(#a):not(#b):not(#c) .usernameWrap .utags_ul_0 .utags_captain_tag{left:-20px}:not(#a):not(#b):not(#c) .usernameWrap .utags_ul_1::before{content:"";display:block}:not(#a):not(#b):not(#c) .vidTitleWrapper .title .utags_ul_0{display:block !important;height:0;position:absolute;top:0}:not(#a):not(#b):not(#c) .vidTitleWrapper .title .utags_ul_0 .utags_captain_tag{background-color:rgba(255,255,255,.8666666667) !important}:not(#a):not(#b):not(#c) .vidTitleWrapper .title .utags_ul_1{display:block !important;height:0;position:absolute;bottom:0}:not(#a):not(#b):not(#c) ul.videos .thumbnail-info-wrapper{position:relative}:not(#a):not(#b):not(#c) ul.videos .thumbnail-info-wrapper .title .utags_ul_0{display:block !important;height:0;position:absolute;top:0}:not(#a):not(#b):not(#c) ul.videos .thumbnail-info-wrapper .title .utags_ul_0 .utags_captain_tag{background-color:rgba(255,255,255,.8666666667) !important}:not(#a):not(#b):not(#c) ul.videos .thumbnail-info-wrapper .title .utags_ul_1{display:block !important;height:0;position:absolute;bottom:0}'
  5914. var pornhub_com_default2 = (() => {
  5915. const prefix3 = "https://www.pornhub.com/"
  5916. function getUserProfileUrl(href, exact = false) {
  5917. if (href.includes("pornhub.com")) {
  5918. const index = href.indexOf("pornhub.com") + 12
  5919. const href2 = href.slice(index)
  5920. if (exact) {
  5921. if (/^(model|users)\/[\w-]+(\?.*)?$/.test(href2)) {
  5922. return prefix3 + href2.replace(/(^(model|users)\/[\w-]+).*/, "$1")
  5923. }
  5924. } else if (/^(model|users)\/[\w-]+/.test(href2)) {
  5925. return prefix3 + href2.replace(/(^(model|users)\/[\w-]+).*/, "$1")
  5926. }
  5927. }
  5928. return void 0
  5929. }
  5930. function getChannelUrl(href, exact = false) {
  5931. if (href.includes("pornhub.com")) {
  5932. const index = href.indexOf("pornhub.com") + 12
  5933. const href2 = href.slice(index)
  5934. if (exact) {
  5935. if (/^channels\/[\w-]+(\?.*)?$/.test(href2)) {
  5936. return prefix3 + href2.replace(/(^channels\/[\w-]+).*/, "$1")
  5937. }
  5938. } else if (/^channels\/[\w-]+/.test(href2)) {
  5939. return prefix3 + href2.replace(/(^channels\/[\w-]+).*/, "$1")
  5940. }
  5941. }
  5942. return void 0
  5943. }
  5944. function getVideoUrl(href) {
  5945. if (href.includes("pornhub.com")) {
  5946. const index = href.indexOf("pornhub.com") + 12
  5947. const href2 = href.slice(index)
  5948. if (/^view_video.php\?viewkey=\w+/.test(href2)) {
  5949. return (
  5950. prefix3 + href2.replace(/(view_video.php\?viewkey=\w+).*/, "$1")
  5951. )
  5952. }
  5953. }
  5954. return void 0
  5955. }
  5956. return {
  5957. matches: /pornhub\.com/,
  5958. validate(element) {
  5959. const hrefAttr = getAttribute(element, "href")
  5960. if (!hrefAttr || hrefAttr === "null" || hrefAttr === "#") {
  5961. return false
  5962. }
  5963. const href = element.href
  5964. let key = getChannelUrl(href, true)
  5965. if (key) {
  5966. const meta = { type: "channel" }
  5967. element.utags = { key, meta }
  5968. return true
  5969. }
  5970. key = getUserProfileUrl(href, true)
  5971. if (key) {
  5972. const meta = { type: "user" }
  5973. element.utags = { key, meta }
  5974. return true
  5975. }
  5976. key = getVideoUrl(href)
  5977. if (key) {
  5978. let title
  5979. const titleElement = $("#video-title", element)
  5980. if (titleElement) {
  5981. title = titleElement.textContent
  5982. }
  5983. const meta = title ? { title, type: "video" } : { type: "video" }
  5984. element.utags = { key, meta }
  5985. return true
  5986. }
  5987. return true
  5988. },
  5989. excludeSelectors: [
  5990. ...default_default2.excludeSelectors,
  5991. ".networkBarWrapper",
  5992. "#headerWrapper",
  5993. "#headerMenuContainer",
  5994. "#mainMenuProfile",
  5995. "#mainMenuAmateurModelProfile",
  5996. "#countryRedirectMessage",
  5997. "aside#leftMenu",
  5998. ".profileSubNav",
  5999. ".subFilterList",
  6000. ".greyButton",
  6001. ".orangeButton",
  6002. ],
  6003. addExtraMatchedNodes(matchedNodesSet) {
  6004. let key = getUserProfileUrl(location.href)
  6005. if (key) {
  6006. const element = $(".name h1")
  6007. if (element) {
  6008. const title = element.textContent.trim()
  6009. if (title) {
  6010. const meta = { title, type: "user" }
  6011. element.utags = { key, meta }
  6012. matchedNodesSet.add(element)
  6013. }
  6014. }
  6015. }
  6016. key = getChannelUrl(location.href)
  6017. if (key) {
  6018. const element = $(".title h1")
  6019. if (element && !$("a", element)) {
  6020. const title = element.textContent.trim()
  6021. if (title) {
  6022. const meta = { title, type: "channel" }
  6023. element.utags = { key, meta }
  6024. matchedNodesSet.add(element)
  6025. }
  6026. }
  6027. }
  6028. key = getVideoUrl(location.href)
  6029. if (key) {
  6030. const element = $("h1.title")
  6031. if (element) {
  6032. const title = element.textContent.trim()
  6033. if (title) {
  6034. const meta = { title, type: "video" }
  6035. element.utags = { key, meta }
  6036. matchedNodesSet.add(element)
  6037. }
  6038. }
  6039. }
  6040. },
  6041. getStyle: () => pornhub_com_default,
  6042. }
  6043. })()
  6044. var e_hentai_org_default =
  6045. ":not(#a):not(#b):not(#c) div.gt a+.utags_ul_0,:not(#a):not(#b):not(#c) div.gtl a+.utags_ul_0,:not(#a):not(#b):not(#c) div.gtw a+.utags_ul_0,:not(#a):not(#b):not(#c) div.gl4e.glname .glink+.utags_ul_0,:not(#a):not(#b):not(#c) .gltm .glname a+.utags_ul_0,:not(#a):not(#b):not(#c) .gltc .glname a+.utags_ul_0{--utags-notag-ul-disply: var(--utags-notag-ul-disply-3);--utags-notag-ul-height: var(--utags-notag-ul-height-3);--utags-notag-ul-position: var(--utags-notag-ul-position-3);--utags-notag-ul-top: var(--utags-notag-ul-top-3);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-3);--utags-notag-captain-tag-left: 24px;--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap );z-index:200}:not(#a):not(#b):not(#c) div.gl1t a+.utags_ul_0{--utags-notag-ul-disply: var(--utags-notag-ul-disply-4);--utags-notag-ul-height: var(--utags-notag-ul-height-4);--utags-notag-ul-position: var(--utags-notag-ul-position-4);--utags-notag-ul-top: var(--utags-notag-ul-top-4);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-4);--utags-notag-captain-tag-left: 24px;--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}"
  6046. var e_hentai_org_default2 = (() => {
  6047. const prefix3 = "https://e-hentai.org/"
  6048. const prefix22 = "https://exhentai.org/"
  6049. function getPostUrl(url) {
  6050. if (url.startsWith(prefix3)) {
  6051. const href2 = url.slice(21)
  6052. if (/^g\/\w+/.test(href2)) {
  6053. return prefix3 + href2.replace(/^(g\/\w+\/\w+\/).*/, "$1")
  6054. }
  6055. }
  6056. if (url.startsWith(prefix22)) {
  6057. const href2 = url.slice(21)
  6058. if (/^g\/\w+/.test(href2)) {
  6059. return prefix22 + href2.replace(/^(g\/\w+\/\w+\/).*/, "$1")
  6060. }
  6061. }
  6062. return void 0
  6063. }
  6064. function isImageViewUrl(url) {
  6065. if (url.startsWith(prefix3)) {
  6066. const href2 = url.slice(21)
  6067. return /^s\/\w+/.test(href2)
  6068. }
  6069. if (url.startsWith(prefix22)) {
  6070. const href2 = url.slice(21)
  6071. return /^s\/\w+/.test(href2)
  6072. }
  6073. return false
  6074. }
  6075. return {
  6076. matches: /e-hentai\.org|exhentai\.org/,
  6077. validate(element) {
  6078. if (element.tagName !== "A") {
  6079. return true
  6080. }
  6081. const href = element.href
  6082. if (href && (href.startsWith(prefix3) || href.startsWith(prefix22))) {
  6083. const key = getPostUrl(href)
  6084. if (key) {
  6085. const titleElement = $(".glink", element)
  6086. let title
  6087. if (titleElement) {
  6088. title = titleElement.textContent
  6089. }
  6090. const meta = { type: "post" }
  6091. if (title) {
  6092. meta.title = title
  6093. }
  6094. element.utags = { key, meta }
  6095. return true
  6096. }
  6097. if (isImageViewUrl(href)) {
  6098. return false
  6099. }
  6100. }
  6101. return true
  6102. },
  6103. map(element) {
  6104. const titleElement = $(".gl4e.glname .glink", element)
  6105. if (titleElement) {
  6106. titleElement.utags = element.utags
  6107. titleElement.dataset.utags = titleElement.dataset.utags || ""
  6108. titleElement.dataset.utags_node_type = "link"
  6109. return titleElement
  6110. }
  6111. return void 0
  6112. },
  6113. excludeSelectors: [
  6114. ...default_default2.excludeSelectors,
  6115. "#nb",
  6116. ".searchnav",
  6117. ".gtb",
  6118. 'a[href*="report=select"]',
  6119. 'a[href*="act=expunge"]',
  6120. ],
  6121. addExtraMatchedNodes(matchedNodesSet) {
  6122. const key = getPostUrl(location.href)
  6123. if (key) {
  6124. const element = getFirstHeadElement()
  6125. if (element) {
  6126. const title = element.textContent.trim()
  6127. if (title) {
  6128. const meta = { title, type: "post" }
  6129. element.utags = { key, meta }
  6130. matchedNodesSet.add(element)
  6131. }
  6132. }
  6133. }
  6134. },
  6135. getStyle: () => e_hentai_org_default,
  6136. }
  6137. })()
  6138. var panda_chaika_moe_default =
  6139. ":not(#a):not(#b):not(#c) h5+.utags_ul{display:block !important;margin-top:-4px !important;margin-bottom:6px !important}"
  6140. var panda_chaika_moe_default2 = (() => {
  6141. const prefix3 = "https://panda.chaika.moe/"
  6142. function getPostUrl(url, exact = false) {
  6143. if (url.startsWith(prefix3)) {
  6144. const href2 = url.slice(25)
  6145. if (exact) {
  6146. if (/^archive\/\d+\/(\?.*)?$/.test(href2)) {
  6147. return prefix3 + href2.replace(/^(archive\/\d+\/).*/, "$1")
  6148. }
  6149. } else if (/^archive\/\d+\//.test(href2)) {
  6150. return prefix3 + href2.replace(/^(archive\/\d+\/).*/, "$1")
  6151. }
  6152. }
  6153. return void 0
  6154. }
  6155. return {
  6156. matches: /panda\.chaika\.moe/,
  6157. excludeSelectors: [
  6158. ...default_default2.excludeSelectors,
  6159. ".navbar",
  6160. "th",
  6161. ".pagination",
  6162. ".btn",
  6163. ".caption",
  6164. ],
  6165. addExtraMatchedNodes(matchedNodesSet) {
  6166. const key = getPostUrl(location.href)
  6167. if (key) {
  6168. const element = $("h5")
  6169. if (element) {
  6170. const title = element.textContent.trim()
  6171. if (title) {
  6172. const meta = { title, type: "post" }
  6173. element.utags = { key, meta }
  6174. matchedNodesSet.add(element)
  6175. }
  6176. }
  6177. }
  6178. for (const element of $$(".gallery a.cover")) {
  6179. const key2 = element.href
  6180. const titleElement = $(".cover-title", element)
  6181. if (titleElement) {
  6182. const title = titleElement.textContent
  6183. const meta = { title, type: "post" }
  6184. titleElement.utags = { key: key2, meta }
  6185. titleElement.dataset.utags_node_type = "link"
  6186. matchedNodesSet.add(titleElement)
  6187. }
  6188. }
  6189. for (const element of $$('.td-extended > a[href^="/archive/"]')) {
  6190. const key2 = element.href
  6191. const titleElement = $("h5", element.parentElement.parentElement)
  6192. if (titleElement) {
  6193. const title = titleElement.textContent
  6194. const meta = { title, type: "post" }
  6195. titleElement.utags = { key: key2, meta }
  6196. titleElement.dataset.utags_node_type = "link"
  6197. matchedNodesSet.add(titleElement)
  6198. }
  6199. }
  6200. },
  6201. getStyle: () => panda_chaika_moe_default,
  6202. }
  6203. })()
  6204. var dmm_co_jp_default =
  6205. ":not(#a):not(#b):not(#c) a+.utags_ul_0{object-position:200% 50%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-5);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-5);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) a+.utags_ul_1{background-color:var(--utags-captain-tag-background-color) !important;border-radius:3px !important;--utags-emoji-tag-background-color: #fff0}:not(#a):not(#b):not(#c) .mainList__item a+.utags_ul_0{object-position:0% 100%;--utags-notag-captain-tag-top: -90px;--utags-notag-captain-tag-left: 4px}:not(#a):not(#b):not(#c) .mainList__item a+.utags_ul_1{margin-top:6px !important;width:100%}:not(#a):not(#b):not(#c) .pickup .fn-responsiveImg a+.utags_ul_0{object-position:0% 100%;--utags-notag-captain-tag-top: -70px;--utags-notag-captain-tag-left: 4px}:not(#a):not(#b):not(#c) .pickup .fn-responsiveImg a+.utags_ul_1{margin-top:6px !important;width:100%}:not(#a):not(#b):not(#c) .productList .tileListTtl__txt{height:unset}:not(#a):not(#b):not(#c) .productList .tileListTtl__txt--author{white-space:normal}:not(#a):not(#b):not(#c) #l-areaRecommendProduct a+.utags_ul_0{object-position:0% 100%;--utags-notag-captain-tag-top: -80px;--utags-notag-captain-tag-left: 4px}:not(#a):not(#b):not(#c) #l-areaRecommendProduct a+.utags_ul_1{margin-top:6px !important;width:100%}"
  6206. var dmm_co_jp_default2 = (() => {
  6207. const prefix3 = "https://www.dmm.co.jp/"
  6208. function getCanonicalUrl2(url) {
  6209. if (url.startsWith(prefix3)) {
  6210. const href2 = url.slice(prefix3.length)
  6211. if (href2.includes("/=/")) {
  6212. return prefix3 + href2.replace(/\?.*/, "")
  6213. }
  6214. }
  6215. return url
  6216. }
  6217. function getProductUrl(url) {
  6218. if (url.startsWith(prefix3)) {
  6219. const href2 = url.slice(prefix3.length)
  6220. if (href2.includes("/detail/=/cid=")) {
  6221. return prefix3 + href2.replace(/\?.*/, "")
  6222. }
  6223. }
  6224. return void 0
  6225. }
  6226. function getMakerUrl(url) {
  6227. if (url.startsWith(prefix3)) {
  6228. const href2 = url.slice(prefix3.length)
  6229. if (href2.includes("/list/=/article=maker/id=")) {
  6230. return prefix3 + href2.replace(/\?.*/, "")
  6231. }
  6232. }
  6233. return void 0
  6234. }
  6235. return {
  6236. matches: /dmm\.co\.jp/,
  6237. validate(element) {
  6238. const href = element.href
  6239. if (!href.startsWith(prefix3)) {
  6240. return true
  6241. }
  6242. if (href.includes("/=/")) {
  6243. const key = getProductUrl(href)
  6244. if (key) {
  6245. const titleElement = $(
  6246. ".mainListLinkWork__txt,.responsive-name",
  6247. element
  6248. )
  6249. const title = titleElement
  6250. ? getTrimmedTitle(titleElement)
  6251. : getTrimmedTitle(element)
  6252. if (title) {
  6253. const meta = { title, type: "product" }
  6254. element.utags = { key, meta }
  6255. }
  6256. }
  6257. return true
  6258. }
  6259. return false
  6260. },
  6261. excludeSelectors: [
  6262. ...default_default2.excludeSelectors,
  6263. "header",
  6264. ".localNav-list",
  6265. ".m-leftNavigation",
  6266. ".l-areaSideNavColumn",
  6267. ".top-leftcolumn",
  6268. ".top-rightcolumn",
  6269. ".d-btn-xhi-st",
  6270. ".headingTitle__txt--more",
  6271. ".recommendCapt__txt",
  6272. ".circleFanButton__content",
  6273. ".displayFormat",
  6274. ".pageNationList",
  6275. ".nav-text-container",
  6276. ".sub-nav-link",
  6277. ".m-listHeader",
  6278. ".dcd-review__rating_map",
  6279. ".dcd-review_boxpagenation",
  6280. ".sampleButton",
  6281. ".right_navi_link",
  6282. ],
  6283. validMediaSelectors: [
  6284. ".mainList",
  6285. ".pickup .fn-responsiveImg",
  6286. "#l-areaRecommendProduct",
  6287. ],
  6288. addExtraMatchedNodes(matchedNodesSet) {
  6289. let key = getProductUrl(location.href)
  6290. if (key) {
  6291. const element = $("h1.productTitle__txt")
  6292. if (element) {
  6293. const title = element.textContent.trim()
  6294. if (title) {
  6295. const meta = { title }
  6296. element.utags = { key, meta }
  6297. matchedNodesSet.add(element)
  6298. }
  6299. }
  6300. }
  6301. key = getMakerUrl(location.href)
  6302. if (key) {
  6303. const element = $(".circleProfile__name span")
  6304. if (element) {
  6305. const title = element.textContent.trim()
  6306. if (title) {
  6307. const meta = { title }
  6308. element.utags = { key, meta }
  6309. matchedNodesSet.add(element)
  6310. }
  6311. }
  6312. }
  6313. },
  6314. getCanonicalUrl: getCanonicalUrl2,
  6315. getStyle: () => dmm_co_jp_default,
  6316. }
  6317. })()
  6318. var kemono_su_default =
  6319. ":not(#a):not(#b):not(#c) a.user-header__avatar+.utags_ul_0,:not(#a):not(#b):not(#c) a.user-card+.utags_ul_0,:not(#a):not(#b):not(#c) .post-card a+.utags_ul_0{object-position:0% 100%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: -4px;--utags-notag-captain-tag-left: 2px;--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap );transition:top ease .1s,left ease .1s}:not(#a):not(#b):not(#c) a.user-header__avatar+.utags_ul_1,:not(#a):not(#b):not(#c) a.user-card+.utags_ul_1,:not(#a):not(#b):not(#c) .post-card a+.utags_ul_1{object-position:0% 100%;position:absolute;top:-9999px;z-index:100;margin-top:-6px !important;margin-left:4px !important;transition:top ease .1s,left ease .1s}:not(#a):not(#b):not(#c) a.user-header__avatar+.utags_ul_1 .utags_text_tag,:not(#a):not(#b):not(#c) a.user-card+.utags_ul_1 .utags_text_tag,:not(#a):not(#b):not(#c) .post-card a+.utags_ul_1 .utags_text_tag{--utags-text-tag-background-color: yellow}"
  6320. var kemono_su_default2 = (() => {
  6321. const prefix3 = location.origin + "/"
  6322. function getPostUrl(url) {
  6323. if (url.startsWith(prefix3)) {
  6324. const href2 = url.slice(prefix3.length)
  6325. if (/^\w+\/user\/\w+\/post\/\w+/.test(href2)) {
  6326. return prefix3 + href2.replace(/^(\w+\/user\/\w+\/post\/\w+).*/, "$1")
  6327. }
  6328. }
  6329. return void 0
  6330. }
  6331. return {
  6332. matches: /kemono\.su|coomer\.su|nekohouse\.su/,
  6333. validate(element) {
  6334. const hrefAttr = getAttribute(element, "href")
  6335. if (hrefAttr.startsWith("#")) {
  6336. return false
  6337. }
  6338. const href = element.href
  6339. if (!href.startsWith(prefix3)) {
  6340. return true
  6341. }
  6342. if (
  6343. hasClass(element, "user-card") ||
  6344. hasClass(element, "user-header__avatar") ||
  6345. element.closest(".post-card")
  6346. ) {
  6347. element.dataset.utags = element.dataset.utags || ""
  6348. }
  6349. return true
  6350. },
  6351. validMediaSelectors: [
  6352. ".user-header .user-header__avatar",
  6353. ".user-header .user-header__profile",
  6354. ".user-card",
  6355. ".post-card__image",
  6356. ".post-card",
  6357. ],
  6358. excludeSelectors: [
  6359. ...default_default2.excludeSelectors,
  6360. ".global-sidebar",
  6361. ".paginator",
  6362. ".post__nav-links",
  6363. ".scrape__nav-links",
  6364. ".tabs",
  6365. ".user-header__actions",
  6366. ".posts-board__sidebar",
  6367. "#add-new-link",
  6368. 'a[href^="/authentication/"]',
  6369. ],
  6370. addExtraMatchedNodes(matchedNodesSet) {
  6371. const key = getPostUrl(location.href)
  6372. if (key) {
  6373. const element = $("h1.post__title,h1.scrape__title")
  6374. if (element) {
  6375. const title = element.textContent.trim()
  6376. if (title) {
  6377. const meta = { title, type: "post" }
  6378. element.utags = { key, meta }
  6379. matchedNodesSet.add(element)
  6380. }
  6381. }
  6382. }
  6383. },
  6384. getStyle: () => kemono_su_default,
  6385. }
  6386. })()
  6387. var rule34video_com_default =
  6388. ":not(#a):not(#b):not(#c) a+.utags_ul_0{object-position:200% 50%;--utags-notag-ul-disply: var(--utags-notag-ul-disply-5);--utags-notag-ul-height: var(--utags-notag-ul-height-5);--utags-notag-ul-position: var(--utags-notag-ul-position-5);--utags-notag-ul-top: var(--utags-notag-ul-top-5);--utags-notag-captain-tag-top: var(--utags-notag-captain-tag-top-5);--utags-notag-captain-tag-left: var(--utags-notag-captain-tag-left-5);--utags-captain-tag-background-color: var( --utags-captain-tag-background-color-overlap )}:not(#a):not(#b):not(#c) a+.utags_ul_1{object-position:0% 200%}:not(#a):not(#b):not(#c) .thumbs .thumb a+.utags_ul_0{object-position:0% 200%;--utags-notag-captain-tag-top: -2px;--utags-notag-captain-tag-left: -4px}:not(#a):not(#b):not(#c) .list_items .item a.wrap_item+.utags_ul_0,:not(#a):not(#b):not(#c) .aside_wrap a.item+.utags_ul_0{object-position:100% 50%}"
  6389. var rule34video_com_default2 = (() => {
  6390. const prefix3 = location.origin + "/"
  6391. function getModelUrl(url) {
  6392. if (url.startsWith(prefix3)) {
  6393. const href2 = url.slice(prefix3.length)
  6394. if (/^models\/[\w-]+/.test(href2)) {
  6395. return prefix3 + href2.replace(/^(models\/[\w-]+).*/, "$1") + "/"
  6396. }
  6397. }
  6398. return void 0
  6399. }
  6400. function getMemberUrl(url) {
  6401. if (url.startsWith(prefix3)) {
  6402. const href2 = url.slice(prefix3.length)
  6403. if (/^members\/\d+/.test(href2)) {
  6404. return prefix3 + href2.replace(/^(members\/\d+).*/, "$1") + "/"
  6405. }
  6406. }
  6407. return void 0
  6408. }
  6409. function getCategoryUrl(url) {
  6410. if (url.startsWith(prefix3)) {
  6411. const href2 = url.slice(prefix3.length)
  6412. if (/^categories\/[\w-]+/.test(href2)) {
  6413. return prefix3 + href2.replace(/^(categories\/[\w-]+).*/, "$1") + "/"
  6414. }
  6415. }
  6416. return void 0
  6417. }
  6418. function getVideoUrl(url) {
  6419. if (url.startsWith(prefix3)) {
  6420. const href2 = url.slice(prefix3.length)
  6421. if (/^video\/\d+(\/[\w-]+)?/.test(href2)) {
  6422. return (
  6423. prefix3 + href2.replace(/^(video\/\d+(\/[\w-]+)?).*/, "$1") + "/"
  6424. )
  6425. }
  6426. }
  6427. return void 0
  6428. }
  6429. return {
  6430. matches: /rule34video\.com|rule34gen\.com/,
  6431. listNodesSelectors: [
  6432. //
  6433. ".list-comments .item",
  6434. ".thumbs .item",
  6435. ],
  6436. conditionNodesSelectors: [
  6437. //
  6438. ".list-comments .item .comment-info .inner a",
  6439. ".thumbs .item a.th",
  6440. ],
  6441. validate(element) {
  6442. const href = element.href
  6443. if (!href.startsWith(prefix3)) {
  6444. if ($("header", element.parentElement)) {
  6445. const key2 = href.replace(/(https?:\/\/[^/]+\/).*/, "$1")
  6446. const meta = { type: "AD", title: "AD" }
  6447. element.utags = { key: key2, meta }
  6448. element.dataset.utags = element.dataset.utags || ""
  6449. }
  6450. return true
  6451. }
  6452. const key = getVideoUrl(href)
  6453. if (key) {
  6454. const titleElement = $(".thumb_title", element)
  6455. const title = titleElement
  6456. ? titleElement.textContent.trim()
  6457. : element.textContent.trim()
  6458. if (!title) {
  6459. return false
  6460. }
  6461. const meta = { type: "video", title }
  6462. element.utags = { key, meta }
  6463. element.dataset.utags = element.dataset.utags || ""
  6464. return true
  6465. }
  6466. element.dataset.utags = element.dataset.utags || ""
  6467. return true
  6468. },
  6469. excludeSelectors: [
  6470. ...default_default2.excludeSelectors,
  6471. ".header",
  6472. ".btn_more",
  6473. ".tabs-menu",
  6474. ".pagination",
  6475. ".headline",
  6476. ".prev",
  6477. ".next",
  6478. ".btn",
  6479. ".all",
  6480. ".tag_item_suggest",
  6481. 'a[href*="download"]',
  6482. ".list-comments .wrap_image",
  6483. ],
  6484. addExtraMatchedNodes(matchedNodesSet) {
  6485. let key = getModelUrl(location.href)
  6486. if (key) {
  6487. const element = $(".brand_inform .title")
  6488. if (element) {
  6489. const title = element.textContent.trim()
  6490. if (title) {
  6491. const meta = { title, type: "model" }
  6492. element.utags = { key, meta }
  6493. matchedNodesSet.add(element)
  6494. }
  6495. }
  6496. }
  6497. key = getMemberUrl(location.href)
  6498. if (key) {
  6499. const element = $(".channel_logo .title")
  6500. if (element) {
  6501. const title = element.textContent.trim()
  6502. if (title) {
  6503. const meta = { title, type: "user" }
  6504. element.utags = { key, meta }
  6505. matchedNodesSet.add(element)
  6506. }
  6507. }
  6508. }
  6509. key = getCategoryUrl(location.href)
  6510. if (key) {
  6511. const element = $(".brand_inform .title")
  6512. if (element) {
  6513. const title = element.textContent.trim()
  6514. if (title) {
  6515. const meta = { title, type: "category" }
  6516. element.utags = { key, meta }
  6517. matchedNodesSet.add(element)
  6518. }
  6519. }
  6520. }
  6521. key = getVideoUrl(location.href)
  6522. if (key) {
  6523. const element = $("h1.title_video")
  6524. if (element) {
  6525. const title = element.textContent.trim()
  6526. if (title) {
  6527. const meta = { title, type: "video" }
  6528. element.utags = { key, meta }
  6529. matchedNodesSet.add(element)
  6530. }
  6531. }
  6532. }
  6533. },
  6534. getStyle: () => rule34video_com_default,
  6535. }
  6536. })()
  6537. var sites = [
  6538. github_com_default2,
  6539. v2ex_default2,
  6540. twitter_com_default2,
  6541. reddit_com_default2,
  6542. greasyfork_org_default2,
  6543. news_ycombinator_com_default,
  6544. lobste_rs_default,
  6545. mp_weixin_qq_com_default,
  6546. instagram_com_default2,
  6547. threads_net_default2,
  6548. facebook_com_default2,
  6549. youtube_com_default2,
  6550. bilibili_com_default2,
  6551. tiktok_com_default2,
  6552. pojie_cn_default2,
  6553. juejin_cn_default,
  6554. zhihu_com_default,
  6555. xiaohongshu_com_default2,
  6556. weibo_com_default,
  6557. sspai_com_default2,
  6558. douyin_com_default2,
  6559. podcasts_google_com_default2,
  6560. rebang_today_default2,
  6561. myanimelist_net_default2,
  6562. douban_com_default,
  6563. pixiv_net_default2,
  6564. discourse_default2,
  6565. nga_cn_default2,
  6566. keylol_com_default2,
  6567. tampermonkey_net_cn_default2,
  6568. flarum_default2,
  6569. nodeseek_com_default2,
  6570. inoreader_com_default2,
  6571. pornhub_com_default2,
  6572. e_hentai_org_default2,
  6573. panda_chaika_moe_default2,
  6574. dlsite_com_default2,
  6575. dmm_co_jp_default2,
  6576. kemono_su_default2,
  6577. rule34video_com_default2,
  6578. ]
  6579. var getCanonicalUrlFunctionList = [default_default2, ...sites]
  6580. .map((site) => site.getCanonicalUrl)
  6581. .filter((v) => typeof v === "function")
  6582. function matchedSite(hostname2) {
  6583. for (const s of sites) {
  6584. if (s.matches.test(hostname2)) {
  6585. return s
  6586. }
  6587. }
  6588. if (false) {
  6589. return siteForExtensions(hostname2)
  6590. }
  6591. return default_default2
  6592. }
  6593. function joinSelectors(selectors) {
  6594. return selectors ? selectors.join(",") : void 0
  6595. }
  6596. var hostname = location.hostname
  6597. var currentSite = matchedSite(hostname)
  6598. var listNodesSelector = joinSelectors(currentSite.listNodesSelectors)
  6599. var conditionNodesSelector = joinSelectors(
  6600. currentSite.conditionNodesSelectors
  6601. )
  6602. var matchedNodesSelector = joinSelectors(
  6603. currentSite.matchedNodesSelectors ||
  6604. (currentSite.matches ? default_default2.matchedNodesSelectors : void 0)
  6605. )
  6606. var excludeSelector = joinSelectors(currentSite.excludeSelectors)
  6607. var validMediaSelector = joinSelectors(currentSite.validMediaSelectors)
  6608. var validateFunction = currentSite.validate || default_default2.validate
  6609. var mappingFunction =
  6610. typeof currentSite.map === "function" ? currentSite.map : void 0
  6611. function getListNodes() {
  6612. if (typeof currentSite.preProcess === "function") {
  6613. currentSite.preProcess()
  6614. }
  6615. if (typeof currentSite.getStyle === "function" && !$("#utags_site_style")) {
  6616. const styleText = currentSite.getStyle()
  6617. if (styleText) {
  6618. addElement2("style", {
  6619. textContent: styleText,
  6620. id: "utags_site_style",
  6621. })
  6622. }
  6623. }
  6624. return listNodesSelector ? $$(listNodesSelector) : []
  6625. }
  6626. function getConditionNodes() {
  6627. return conditionNodesSelector ? $$(conditionNodesSelector) : []
  6628. }
  6629. function getCanonicalUrl(url) {
  6630. if (!url) {
  6631. return void 0
  6632. }
  6633. for (const getCanonicalUrlFunc of getCanonicalUrlFunctionList) {
  6634. if (getCanonicalUrlFunc) {
  6635. url = getCanonicalUrlFunc(url)
  6636. }
  6637. }
  6638. return url
  6639. }
  6640. var preValidate = (element) => {
  6641. if (!element) {
  6642. return false
  6643. }
  6644. if (element.tagName === "A") {
  6645. let href = getAttribute(element, "href")
  6646. if (!href) {
  6647. return false
  6648. }
  6649. href = href.trim()
  6650. if (href.length === 0 || href === "#") {
  6651. return false
  6652. }
  6653. const protocol = element.protocol
  6654. if (protocol !== "http:" && protocol !== "https:") {
  6655. return false
  6656. }
  6657. }
  6658. if (
  6659. element.closest(
  6660. ".utags_text_tag,.browser_extension_settings_container,a a"
  6661. )
  6662. ) {
  6663. return false
  6664. }
  6665. return true
  6666. }
  6667. var isValidUtagsElement = (element) => {
  6668. if (element.dataset.utags !== void 0) {
  6669. return true
  6670. }
  6671. if (!element.textContent) {
  6672. return false
  6673. }
  6674. if (!element.textContent.trim()) {
  6675. return false
  6676. }
  6677. const media = $(
  6678. 'img,svg,audio,video,button,.icon,[style*="background-image"]',
  6679. element
  6680. )
  6681. if (media) {
  6682. if (!validMediaSelector) {
  6683. return false
  6684. }
  6685. if (!media.closest(validMediaSelector)) {
  6686. return false
  6687. }
  6688. }
  6689. return true
  6690. }
  6691. var isExcludedUtagsElement = (element) => {
  6692. return excludeSelector ? Boolean(element.closest(excludeSelector)) : false
  6693. }
  6694. var addMatchedNodes = (matchedNodesSet) => {
  6695. if (!matchedNodesSelector) {
  6696. return
  6697. }
  6698. const elements = $$(matchedNodesSelector)
  6699. if (elements.length === 0) {
  6700. return
  6701. }
  6702. const process2 = (element) => {
  6703. var _a
  6704. if (!preValidate(element) || !validateFunction(element)) {
  6705. delete element.utags
  6706. return
  6707. }
  6708. if (mappingFunction) {
  6709. const newElement = mappingFunction(element)
  6710. if (newElement && newElement !== element) {
  6711. process2(newElement)
  6712. return
  6713. }
  6714. }
  6715. if (isExcludedUtagsElement(element) || !isValidUtagsElement(element)) {
  6716. delete element.utags
  6717. return
  6718. }
  6719. const utags = element.utags || {}
  6720. const key = utags.key || getCanonicalUrl(element.href)
  6721. if (!key) {
  6722. return
  6723. }
  6724. const title = getTrimmedTitle(element)
  6725. const meta = {}
  6726. if (title && !isUrl(title)) {
  6727. meta.title = title
  6728. }
  6729. if ((_a = utags.meta) == null ? void 0 : _a.title) {
  6730. utags.meta.title = trimTitle(utags.meta.title)
  6731. }
  6732. element.utags = {
  6733. key,
  6734. meta: utags.meta ? Object.assign(meta, utags.meta) : meta,
  6735. }
  6736. matchedNodesSet.add(element)
  6737. }
  6738. for (const element of elements) {
  6739. try {
  6740. process2(element)
  6741. } catch (error) {
  6742. console.error(error)
  6743. }
  6744. }
  6745. }
  6746. function matchedNodes() {
  6747. const matchedNodesSet = /* @__PURE__ */ new Set()
  6748. addMatchedNodes(matchedNodesSet)
  6749. if (typeof currentSite.addExtraMatchedNodes === "function") {
  6750. currentSite.addExtraMatchedNodes(matchedNodesSet)
  6751. }
  6752. if (typeof currentSite.postProcess === "function") {
  6753. currentSite.postProcess()
  6754. }
  6755. return [...matchedNodesSet]
  6756. }
  6757. var config = {
  6758. run_at: "document_start",
  6759. matches: ["https://*/*"],
  6760. all_frames: false,
  6761. }
  6762. var emojiTags2
  6763. var host2 = location.host
  6764. var isEnabledByDefault = () => {
  6765. if (host2.includes("www.bilibili.com")) {
  6766. return false
  6767. }
  6768. return true
  6769. }
  6770. var isTagManager = location.href.includes("utags.pipecraft.net/tags/")
  6771. var groupNumber = 1
  6772. var settingsTable2 = {
  6773. ["enableCurrentSite_".concat(host2)]: {
  6774. title: i2("settings.enableCurrentSite"),
  6775. defaultValue: isEnabledByDefault(),
  6776. },
  6777. showHidedItems: {
  6778. title: i2("settings.showHidedItems"),
  6779. defaultValue: false,
  6780. group: ++groupNumber,
  6781. },
  6782. noOpacityEffect: {
  6783. title: i2("settings.noOpacityEffect"),
  6784. defaultValue: false,
  6785. group: groupNumber,
  6786. },
  6787. ["useVisitedFunction_".concat(host2)]: {
  6788. title: i2("settings.useVisitedFunction"),
  6789. defaultValue: false,
  6790. group: ++groupNumber,
  6791. },
  6792. ["displayEffectOfTheVisitedContent_".concat(host2)]: {
  6793. title: i2("settings.displayEffectOfTheVisitedContent"),
  6794. type: "select",
  6795. defaultValue: "2",
  6796. options: {
  6797. [i2("settings.displayEffectOfTheVisitedContent.recordingonly")]: "0",
  6798. [i2("settings.displayEffectOfTheVisitedContent.showtagonly")]: "1",
  6799. [i2("settings.displayEffectOfTheVisitedContent.changecolor")]: "4",
  6800. [i2("settings.displayEffectOfTheVisitedContent.translucent")]: "2",
  6801. [i2("settings.displayEffectOfTheVisitedContent.hide")]: "3",
  6802. },
  6803. group: groupNumber,
  6804. },
  6805. pinnedTagsTitle: {
  6806. title: i2("settings.pinnedTags"),
  6807. type: "action",
  6808. async onclick() {
  6809. const input = $('textarea[data-key="pinnedTags"]')
  6810. if (input) {
  6811. input.scrollIntoView({ block: "start" })
  6812. input.selectionStart = input.value.length
  6813. input.selectionEnd = input.value.length
  6814. input.focus()
  6815. }
  6816. },
  6817. group: ++groupNumber,
  6818. },
  6819. pinnedTags: {
  6820. title: i2("settings.pinnedTags"),
  6821. defaultValue: i2("settings.pinnedTagsDefaultValue"),
  6822. placeholder: i2("settings.pinnedTagsPlaceholder"),
  6823. type: "textarea",
  6824. group: groupNumber,
  6825. },
  6826. emojiTagsTitle: {
  6827. title: i2("settings.emojiTags"),
  6828. type: "action",
  6829. async onclick() {
  6830. const input = $('textarea[data-key="emojiTags"]')
  6831. if (input) {
  6832. input.scrollIntoView({ block: "start" })
  6833. input.selectionStart = input.value.length
  6834. input.selectionEnd = input.value.length
  6835. input.focus()
  6836. }
  6837. },
  6838. group: groupNumber,
  6839. },
  6840. emojiTags: {
  6841. title: i2("settings.emojiTags"),
  6842. defaultValue:
  6843. "\u{1F44D}, \u{1F44E}, \u2764\uFE0F, \u2B50, \u{1F31F}, \u{1F525}, \u{1F4A9}, \u26A0\uFE0F, \u{1F4AF}, \u{1F44F}, \u{1F437}, \u{1F4CC}, \u{1F4CD}, \u{1F3C6}, \u{1F48E}, \u{1F4A1}, \u{1F916}, \u{1F4D4}, \u{1F4D6}, \u{1F4DA}, \u{1F4DC}, \u{1F4D5}, \u{1F4D7}, \u{1F9F0}, \u26D4, \u{1F6AB}, \u{1F534}, \u{1F7E0}, \u{1F7E1}, \u{1F7E2}, \u{1F535}, \u{1F7E3}, \u2757, \u2753, \u2705, \u274C",
  6844. placeholder: "\u{1F44D}, \u{1F44E}",
  6845. type: "textarea",
  6846. group: groupNumber,
  6847. },
  6848. customStyle: {
  6849. title: i2("settings.customStyle"),
  6850. defaultValue: false,
  6851. group: ++groupNumber,
  6852. },
  6853. customStyleValue: {
  6854. title: "Custom style value",
  6855. defaultValue: i2("settings.customStyleDefaultValue"),
  6856. placeholder: i2("settings.customStyleDefaultValue"),
  6857. type: "textarea",
  6858. group: groupNumber,
  6859. },
  6860. customStyleTip: {
  6861. title: i2("settings.customStyleExamples"),
  6862. type: "tip",
  6863. tipContent: i2("settings.customStyleExamplesContent"),
  6864. group: groupNumber,
  6865. },
  6866. ["customStyle_".concat(host2)]: {
  6867. title: i2("settings.customStyleCurrentSite"),
  6868. defaultValue: false,
  6869. group: ++groupNumber,
  6870. },
  6871. ["customStyleValue_".concat(host2)]: {
  6872. title: "Custom style value",
  6873. defaultValue: "",
  6874. placeholder: i2("settings.customStyleDefaultValue"),
  6875. type: "textarea",
  6876. group: groupNumber,
  6877. },
  6878. useSimplePrompt: {
  6879. title: i2("settings.useSimplePrompt"),
  6880. defaultValue: false,
  6881. group: ++groupNumber,
  6882. },
  6883. openTagsPage: {
  6884. title: i2("settings.openTagsPage"),
  6885. type: "externalLink",
  6886. url: "https://utags.pipecraft.net/tags/",
  6887. group: ++groupNumber,
  6888. },
  6889. openDataPage: {
  6890. title: i2("settings.openDataPage"),
  6891. type: "externalLink",
  6892. url: "https://utags.pipecraft.net/data/",
  6893. group: groupNumber,
  6894. },
  6895. }
  6896. var addUtagsStyle = () => {
  6897. const style = addStyle(content_default)
  6898. style.id = "utags_style"
  6899. }
  6900. function updateCustomStyle() {
  6901. const customStyleValue = getSettingsValue("customStyleValue") || ""
  6902. if (getSettingsValue("customStyle") && customStyleValue) {
  6903. if ($("#utags_custom_style")) {
  6904. $("#utags_custom_style").textContent = customStyleValue
  6905. } else {
  6906. addElement2("style", {
  6907. id: "utags_custom_style",
  6908. textContent: customStyleValue,
  6909. })
  6910. if ($("#utags_custom_style_2")) {
  6911. $("#utags_custom_style_2").remove()
  6912. }
  6913. }
  6914. } else if ($("#utags_custom_style")) {
  6915. $("#utags_custom_style").remove()
  6916. }
  6917. const customStyleValue2 =
  6918. getSettingsValue("customStyleValue_".concat(host2)) || ""
  6919. if (getSettingsValue("customStyle_".concat(host2)) && customStyleValue2) {
  6920. if ($("#utags_custom_style_2")) {
  6921. $("#utags_custom_style_2").textContent = customStyleValue2
  6922. } else {
  6923. addElement2("style", {
  6924. id: "utags_custom_style_2",
  6925. textContent: customStyleValue2,
  6926. })
  6927. }
  6928. } else if ($("#utags_custom_style_2")) {
  6929. $("#utags_custom_style_2").remove()
  6930. }
  6931. }
  6932. function onSettingsChange2() {
  6933. if (getSettingsValue("showHidedItems")) {
  6934. addClass(doc.documentElement, "utags_no_hide")
  6935. } else {
  6936. removeClass(doc.documentElement, "utags_no_hide")
  6937. }
  6938. if (getSettingsValue("noOpacityEffect")) {
  6939. addClass(doc.documentElement, "utags_no_opacity_effect")
  6940. } else {
  6941. removeClass(doc.documentElement, "utags_no_opacity_effect")
  6942. }
  6943. doc.documentElement.dataset.utags_displayEffectOfTheVisitedContent =
  6944. getSettingsValue("displayEffectOfTheVisitedContent_".concat(host2))
  6945. if (getSettingsValue("enableCurrentSite_".concat(host2))) {
  6946. doc.documentElement.dataset.utags = "".concat(host2)
  6947. displayTagsThrottled()
  6948. updateCustomStyle()
  6949. } else {
  6950. doc.documentElement.dataset.utags = "off"
  6951. if ($("#utags_custom_style")) {
  6952. $("#utags_custom_style").remove()
  6953. }
  6954. if ($("#utags_custom_style_2")) {
  6955. $("#utags_custom_style_2").remove()
  6956. }
  6957. if ($("#utags_site_style")) {
  6958. $("#utags_site_style").remove()
  6959. }
  6960. }
  6961. }
  6962. var start = 0
  6963. if (start) {
  6964. start = Date.now()
  6965. }
  6966. function appendTagsToPage(element, key, tags, meta) {
  6967. const utagsUl = element.nextSibling
  6968. if (hasClass(utagsUl, "utags_ul")) {
  6969. if (
  6970. element.dataset.utags === tags.join(",") &&
  6971. key === getAttribute(utagsUl, "data-utags_key")
  6972. ) {
  6973. return
  6974. }
  6975. utagsUl.remove()
  6976. } else if (key === getAttribute(utagsUl, "data-utags_key")) {
  6977. utagsUl.remove()
  6978. }
  6979. const ul = createElement("ul", {
  6980. class: tags.length === 0 ? "utags_ul utags_ul_0" : "utags_ul utags_ul_1",
  6981. "data-utags_key": key,
  6982. })
  6983. let li = createElement("li")
  6984. const a = createElement("button", {
  6985. type: "button",
  6986. title: "Add tags",
  6987. "data-utags_tag": "\u{1F3F7}\uFE0F",
  6988. "data-utags_key": key,
  6989. "data-utags_tags": tags.join(", "),
  6990. "data-utags_meta": meta ? JSON.stringify(meta) : "",
  6991. class:
  6992. tags.length === 0
  6993. ? "utags_text_tag utags_captain_tag"
  6994. : "utags_text_tag utags_captain_tag2",
  6995. })
  6996. const svg =
  6997. '<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" fill="currentColor" class="bi bi-tags-fill" viewBox="0 0 16 16">\n<path d="M2 2a1 1 0 0 1 1-1h4.586a1 1 0 0 1 .707.293l7 7a1 1 0 0 1 0 1.414l-4.586 4.586a1 1 0 0 1-1.414 0l-7-7A1 1 0 0 1 2 6.586V2zm3.5 4a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z"/>\n<path d="M1.293 7.793A1 1 0 0 1 1 7.086V2a1 1 0 0 0-1 1v4.586a1 1 0 0 0 .293.707l7 7a1 1 0 0 0 1.414 0l.043-.043-7.457-7.457z"/>\n</svg>\n'
  6998. a.innerHTML = createHTML(svg)
  6999. li.append(a)
  7000. ul.append(li)
  7001. for (const tag of tags) {
  7002. li = createElement("li")
  7003. const a2 = createTag(tag, {
  7004. isEmoji: emojiTags2.includes(tag),
  7005. noLink: isTagManager,
  7006. enableSelect: isTagManager,
  7007. })
  7008. li.append(a2)
  7009. ul.append(li)
  7010. }
  7011. element.after(ul)
  7012. element.dataset.utags = tags.join(",")
  7013. setTimeout(() => {
  7014. const style = getComputedStyle(element)
  7015. const zIndex = style.zIndex
  7016. if (zIndex && zIndex !== "auto") {
  7017. setStyle(ul, { zIndex })
  7018. }
  7019. }, 200)
  7020. }
  7021. function cleanUnusedUtags() {
  7022. const utagsUlList = $$(".utags_ul")
  7023. for (const utagsUl of utagsUlList) {
  7024. const element = utagsUl.previousSibling
  7025. if (element && getAttribute(element, "data-utags") !== null) {
  7026. continue
  7027. }
  7028. utagsUl.remove()
  7029. }
  7030. }
  7031. async function displayTags() {
  7032. if (start) {
  7033. console.error("start of displayTags", Date.now() - start)
  7034. }
  7035. emojiTags2 = await getEmojiTags()
  7036. const listNodes = getListNodes()
  7037. for (const node of listNodes) {
  7038. node.dataset.utags_list_node = ""
  7039. }
  7040. if (start) {
  7041. console.error("before matchedNodes", Date.now() - start)
  7042. }
  7043. const nodes = matchedNodes()
  7044. if (start) {
  7045. console.error("after matchedNodes", Date.now() - start, nodes.length)
  7046. }
  7047. await getCachedUrlMap()
  7048. for (const node of nodes) {
  7049. const utags = node.utags
  7050. if (!utags) {
  7051. continue
  7052. }
  7053. const key = utags.key
  7054. if (!key) {
  7055. continue
  7056. }
  7057. const object = getTags(key)
  7058. const tags = (object.tags || []).slice()
  7059. if (node.dataset.utags_visited === "1") {
  7060. tags.push(TAG_VISITED)
  7061. }
  7062. appendTagsToPage(node, key, tags, utags.meta)
  7063. setTimeout(() => {
  7064. updateTagPosition(node)
  7065. })
  7066. }
  7067. if (start) {
  7068. console.error("after appendTagsToPage", Date.now() - start)
  7069. }
  7070. const conditionNodes = getConditionNodes()
  7071. for (const node of conditionNodes) {
  7072. if (getAttribute(node, "data-utags") !== null) {
  7073. node.dataset.utags_condition_node = ""
  7074. }
  7075. }
  7076. for (const node of listNodes) {
  7077. const conditionNodes2 = $$("[data-utags_condition_node]", node)
  7078. const tagsArray = []
  7079. for (const node2 of conditionNodes2) {
  7080. if (!node2.dataset.utags) {
  7081. continue
  7082. }
  7083. if (node2.closest("[data-utags_list_node]") !== node) {
  7084. continue
  7085. }
  7086. tagsArray.push(node2.dataset.utags)
  7087. }
  7088. if (tagsArray.length === 1) {
  7089. node.dataset.utags_list_node = "," + tagsArray[0] + ","
  7090. } else if (tagsArray.length > 1) {
  7091. node.dataset.utags_list_node =
  7092. "," + uniq(tagsArray.join(",").split(",")).join(",") + ","
  7093. }
  7094. }
  7095. cleanUnusedUtags()
  7096. if (start) {
  7097. console.error("end of displayTags", Date.now() - start)
  7098. }
  7099. }
  7100. var displayTagsThrottled = throttle(displayTags, 1e3)
  7101. async function initStorage() {
  7102. await migration()
  7103. addTagsValueChangeListener(() => {
  7104. if (!doc.hidden) {
  7105. setTimeout(displayTags)
  7106. }
  7107. })
  7108. }
  7109. var nodeNameCheckPattern = /^(A|H\d|DIV|SPAN|P|UL|LI|SECTION)$/
  7110. function shouldUpdateUtagsWhenNodeUpdated(nodeList) {
  7111. for (const node of nodeList) {
  7112. if (nodeNameCheckPattern.test(node.nodeName)) {
  7113. return true
  7114. }
  7115. }
  7116. return false
  7117. }
  7118. function getMaxOffsetLeft(utags, utagsSizeFix) {
  7119. const offsetParent = utags.offsetParent
  7120. let maxOffsetRight
  7121. if (offsetParent && offsetParent.offsetWidth > 0) {
  7122. maxOffsetRight = offsetParent.offsetWidth
  7123. } else {
  7124. maxOffsetRight =
  7125. document.body.offsetWidth -
  7126. getOffsetPosition(offsetParent || doc.body).left -
  7127. 2
  7128. }
  7129. return maxOffsetRight - utags.clientWidth - utagsSizeFix
  7130. }
  7131. function updateTagPosition(element) {
  7132. const utags = element.nextElementSibling
  7133. if (!utags || utags.tagName !== "UL" || !hasClass(utags, "utags_ul")) {
  7134. return
  7135. }
  7136. if (
  7137. !utags.offsetParent &&
  7138. utags.offsetHeight === 0 &&
  7139. utags.offsetWidth === 0
  7140. ) {
  7141. return
  7142. }
  7143. const style = getComputedStyle(utags)
  7144. if (style.position !== "absolute") {
  7145. return
  7146. }
  7147. if (element.dataset.utags_position_selector) {
  7148. element =
  7149. $(element.dataset.utags_position_selector, element) ||
  7150. element.closest(element.dataset.utags_position_selector) ||
  7151. element
  7152. }
  7153. element.dataset.utags_fit_content = "1"
  7154. const utagsSizeFix = hasClass(utags, "utags_ul_0") ? 22 : 0
  7155. const offset = getOffsetPosition(element, utags.offsetParent || doc.body)
  7156. const objectPosition = style.objectPosition
  7157. switch (objectPosition) {
  7158. case "-100% 50%": {
  7159. utags.style.left =
  7160. Math.max(offset.left - utags.clientWidth - utagsSizeFix, 0) + "px"
  7161. utags.style.top =
  7162. offset.top +
  7163. ((element.clientHeight || element.offsetHeight) -
  7164. utags.clientHeight -
  7165. utagsSizeFix) /
  7166. 2 +
  7167. "px"
  7168. break
  7169. }
  7170. case "0% -100%": {
  7171. utags.style.left = offset.left + "px"
  7172. utags.style.top = offset.top - utags.clientHeight - utagsSizeFix + "px"
  7173. break
  7174. }
  7175. case "0% 0%": {
  7176. utags.style.left = offset.left + "px"
  7177. utags.style.top = offset.top + "px"
  7178. break
  7179. }
  7180. case "0% 100%": {
  7181. utags.style.left = offset.left + "px"
  7182. utags.style.top =
  7183. offset.top +
  7184. (element.clientHeight || element.offsetHeight) -
  7185. utags.clientHeight -
  7186. utagsSizeFix +
  7187. "px"
  7188. break
  7189. }
  7190. case "0% 200%": {
  7191. utags.style.left = offset.left + "px"
  7192. utags.style.top =
  7193. offset.top + (element.clientHeight || element.offsetHeight) + "px"
  7194. break
  7195. }
  7196. case "100% -100%": {
  7197. utags.style.left =
  7198. offset.left +
  7199. (element.clientWidth || element.offsetWidth) -
  7200. utags.clientWidth -
  7201. utagsSizeFix +
  7202. "px"
  7203. utags.style.top = offset.top - utags.clientHeight - utagsSizeFix + "px"
  7204. break
  7205. }
  7206. case "100% 0%": {
  7207. let offsetLeft =
  7208. (element.clientWidth || element.offsetWidth) -
  7209. utags.clientWidth -
  7210. utagsSizeFix
  7211. if (offsetLeft < 100) {
  7212. offsetLeft = element.clientWidth || element.offsetWidth
  7213. }
  7214. utags.style.left =
  7215. Math.min(
  7216. offset.left + offsetLeft,
  7217. getMaxOffsetLeft(utags, utagsSizeFix)
  7218. ) + "px"
  7219. utags.style.top = offset.top + "px"
  7220. break
  7221. }
  7222. case "100% 50%": {
  7223. let offsetLeft =
  7224. (element.clientWidth || element.offsetWidth) -
  7225. utags.clientWidth -
  7226. utagsSizeFix
  7227. if (offsetLeft < 100) {
  7228. offsetLeft = element.clientWidth || element.offsetWidth
  7229. }
  7230. utags.style.left =
  7231. Math.min(
  7232. offset.left + offsetLeft,
  7233. getMaxOffsetLeft(utags, utagsSizeFix)
  7234. ) + "px"
  7235. utags.style.top =
  7236. offset.top +
  7237. ((element.clientHeight || element.offsetHeight) -
  7238. utags.clientHeight -
  7239. utagsSizeFix) /
  7240. 2 +
  7241. "px"
  7242. break
  7243. }
  7244. case "100% 100%": {
  7245. let offsetLeft =
  7246. (element.clientWidth || element.offsetWidth) -
  7247. utags.clientWidth -
  7248. utagsSizeFix
  7249. if (offsetLeft < 100) {
  7250. offsetLeft = element.clientWidth || element.offsetWidth
  7251. }
  7252. utags.style.left =
  7253. Math.min(
  7254. offset.left + offsetLeft,
  7255. getMaxOffsetLeft(utags, utagsSizeFix)
  7256. ) + "px"
  7257. utags.style.top =
  7258. offset.top +
  7259. (element.clientHeight || element.offsetHeight) -
  7260. utags.clientHeight -
  7261. utagsSizeFix +
  7262. "px"
  7263. break
  7264. }
  7265. case "100% 200%": {
  7266. utags.style.left =
  7267. offset.left +
  7268. (element.clientWidth || element.offsetWidth) -
  7269. utags.clientWidth -
  7270. utagsSizeFix +
  7271. "px"
  7272. utags.style.top =
  7273. offset.top + (element.clientHeight || element.offsetHeight) + "px"
  7274. break
  7275. }
  7276. case "200% 0%": {
  7277. utags.style.left =
  7278. Math.min(
  7279. offset.left + (element.clientWidth || element.offsetWidth),
  7280. getMaxOffsetLeft(utags, utagsSizeFix)
  7281. ) + "px"
  7282. utags.style.top = offset.top + "px"
  7283. break
  7284. }
  7285. case "200% 50%": {
  7286. utags.style.left =
  7287. Math.min(
  7288. offset.left + (element.clientWidth || element.offsetWidth),
  7289. getMaxOffsetLeft(utags, utagsSizeFix)
  7290. ) + "px"
  7291. utags.style.top =
  7292. offset.top +
  7293. ((element.clientHeight || element.offsetHeight) -
  7294. utags.clientHeight -
  7295. utagsSizeFix) /
  7296. 2 +
  7297. "px"
  7298. break
  7299. }
  7300. case "200% 100%": {
  7301. utags.style.left =
  7302. Math.min(
  7303. offset.left + (element.clientWidth || element.offsetWidth),
  7304. getMaxOffsetLeft(utags, utagsSizeFix)
  7305. ) + "px"
  7306. utags.style.top =
  7307. offset.top +
  7308. (element.clientHeight || element.offsetHeight) -
  7309. utags.clientHeight -
  7310. utagsSizeFix +
  7311. "px"
  7312. break
  7313. }
  7314. default: {
  7315. break
  7316. }
  7317. }
  7318. element.dataset.utags_fit_content = "0"
  7319. }
  7320. async function main() {
  7321. addUtagsStyle()
  7322. await initSettings({
  7323. id: "utags",
  7324. title: i2("settings.title"),
  7325. footer: "\n <p>"
  7326. .concat(
  7327. i2("settings.information"),
  7328. '</p>\n <p>\n <a href="https://github.com/utags/utags/issues" target="_blank">\n '
  7329. )
  7330. .concat(
  7331. i2("settings.report"),
  7332. '\n </a></p>\n <p>Made with \u2764\uFE0F by\n <a href="https://www.pipecraft.net/" target="_blank">\n Pipecraft\n </a></p>'
  7333. ),
  7334. settingsTable: settingsTable2,
  7335. async onValueChange() {
  7336. onSettingsChange()
  7337. onSettingsChange2()
  7338. },
  7339. onViewUpdate(settingsMainView) {
  7340. let item = $(
  7341. '[data-key="useVisitedFunction_'.concat(host2, '"]'),
  7342. settingsMainView
  7343. )
  7344. if (!isAvailableOnCurrentSite() && item) {
  7345. item.style.display = "none"
  7346. item.parentElement.style.display = "none"
  7347. }
  7348. item = $(
  7349. '[data-key="displayEffectOfTheVisitedContent_'.concat(host2, '"]'),
  7350. settingsMainView
  7351. )
  7352. if (item) {
  7353. item.style.display = getSettingsValue(
  7354. "useVisitedFunction_".concat(host2)
  7355. )
  7356. ? "flex"
  7357. : "none"
  7358. }
  7359. item = $('[data-key="customStyleValue"]', settingsMainView)
  7360. if (item) {
  7361. item.parentElement.style.display = getSettingsValue("customStyle")
  7362. ? "block"
  7363. : "none"
  7364. }
  7365. item = $(".bes_tip", settingsMainView)
  7366. if (item) {
  7367. item.style.display = getSettingsValue("customStyle")
  7368. ? "block"
  7369. : "none"
  7370. }
  7371. item = $(
  7372. '[data-key="customStyleValue_'.concat(host2, '"]'),
  7373. settingsMainView
  7374. )
  7375. if (item) {
  7376. item.parentElement.style.display = getSettingsValue(
  7377. "customStyle_".concat(host2)
  7378. )
  7379. ? "block"
  7380. : "none"
  7381. }
  7382. },
  7383. })
  7384. if (!getSettingsValue("enableCurrentSite_".concat(host2))) {
  7385. return
  7386. }
  7387. await initStorage()
  7388. setTimeout(outputData, 1)
  7389. onSettingsChange()
  7390. onSettingsChange2()
  7391. await displayTags()
  7392. addEventListener(doc, "visibilitychange", async () => {
  7393. if (!doc.hidden) {
  7394. await displayTags()
  7395. }
  7396. })
  7397. bindDocumentEvents()
  7398. bindWindowEvents()
  7399. const observer = new MutationObserver(async (mutationsList) => {
  7400. let shouldUpdate = false
  7401. for (const mutationRecord of mutationsList) {
  7402. if (shouldUpdateUtagsWhenNodeUpdated(mutationRecord.addedNodes)) {
  7403. shouldUpdate = true
  7404. break
  7405. }
  7406. if (shouldUpdateUtagsWhenNodeUpdated(mutationRecord.removedNodes)) {
  7407. shouldUpdate = true
  7408. break
  7409. }
  7410. }
  7411. if (shouldUpdate) {
  7412. cleanUnusedUtags()
  7413. displayTagsThrottled()
  7414. }
  7415. if ($("#vimiumHintMarkerContainer")) {
  7416. addClass(doc.body, "utags_show_all")
  7417. addClass(doc.documentElement, "utags_vimium_hint")
  7418. } else if (hasClass(doc.documentElement, "utags_vimium_hint")) {
  7419. removeClass(doc.documentElement, "utags_vimium_hint")
  7420. hideAllUtagsInArea()
  7421. }
  7422. })
  7423. observer.observe(doc, {
  7424. childList: true,
  7425. subtree: true,
  7426. })
  7427. addEventListener(doc, "mouseover", (event) => {
  7428. const target = event.target
  7429. if (
  7430. target &&
  7431. (target.tagName === "A" || target.dataset.utags !== void 0)
  7432. ) {
  7433. displayTagsThrottled()
  7434. }
  7435. })
  7436. }
  7437. runWhenHeadExists(async () => {
  7438. if (doc.documentElement.dataset.utags === void 0) {
  7439. doc.documentElement.dataset.utags = "".concat(host2)
  7440. await main()
  7441. }
  7442. })
  7443. })()