🏷️ UTags - Add usertags to links

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.

  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.11
  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, BOSS直聘等网站。
  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://greatest.deepsurf.us/*
  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://meta.discourse.org/*
  47. // @match https://linux.do/*
  48. // @match https://meta.appinn.net/*
  49. // @match https://community.openai.com/*
  50. // @match https://community.cloudflare.com/*
  51. // @match https://community.wanikani.com/*
  52. // @match https://forum.cursor.com/*
  53. // @match https://bbs.nga.cn/*
  54. // @match https://nga.178.com/*
  55. // @match https://ngabbs.com/*
  56. // @match https://www.dlsite.com/*
  57. // @match https://keylol.com/*
  58. // @match https://kemono.su/*
  59. // @match https://coomer.su/*
  60. // @match https://nekohouse.su/*
  61. // @match https://rule34video.com/*
  62. // @match https://rule34gen.com/*
  63. // @match https://panda.chaika.moe/*
  64. // @match https://bbs.tampermonkey.net.cn/*
  65. // @match https://discuss.flarum.org/*
  66. // @match https://discuss.flarum.org.cn/*
  67. // @match https://www.nodeloc.com/*
  68. // @match https://freesmth.net/*
  69. // @match https://freesmth.uk/*
  70. // @match https://veryfb.com/*
  71. // @match https://www.nodeseek.com/*
  72. // @match https://*.inoreader.com/*
  73. // @match https://kater.me/*
  74. // @match https://bbs.viva-la-vita.org/*
  75. // @match https://www.zhipin.com/*
  76. // @match https://v2hot.pipecraft.net/*
  77. // @match https://utags.pipecraft.net/*
  78. // @match https://*.pipecraft.net/*
  79. // @run-at document-start
  80. // @grant GM.getValue
  81. // @grant GM.setValue
  82. // @grant GM_addValueChangeListener
  83. // @grant GM_removeValueChangeListener
  84. // @grant GM_addElement
  85. // @grant GM.registerMenuCommand
  86. // ==/UserScript==
  87. //
  88. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  89. //// The Official Installation URLs ////
  90. //// 官方安装网址 ////
  91. //// ////
  92. //// * https://greatest.deepsurf.us/scripts/460718-utags-add-usertags-to-links ////
  93. //// ** downloadURL https://update.greatest.deepsurf.us/scripts/460718/%F0%9F%8F%B7%EF%B8%8F%20UTags%20-%20Add%20usertags%20to%20links.user.js ////
  94. //// * https://scriptcat.org/script-show-page/2784 ////
  95. //// ** downloadURL https://scriptcat.org/scripts/code/2784/%F0%9F%8F%B7%EF%B8%8F+UTags+-+Add+usertags+to+links.user.js ////
  96. //// * https://github.com/utags/utags ////
  97. //// ** downloadURL https://github.com/utags/utags/raw/main/build/userscript-prod/utags.user.js ////
  98. //// * https://gist.github.com/PipecraftNet/38d90a567ff04660f2a1b5430af9ae96 ////
  99. //// ** downloadURL https://gist.github.com/PipecraftNet/38d90a567ff04660f2a1b5430af9ae96/raw/utags.user.js ////
  100. //// ////
  101. //// ////
  102. //// Extension Version ////
  103. //// 浏览器扩展版本 ////
  104. //// * Chrome Web Store - https://chromewebstore.google.com/detail/utags-add-usertags-to-lin/kofjcnaphffjoookgahgjidofbdplgig ////
  105. //// * Edge Add-ons - https://microsoftedge.microsoft.com/addons/detail/utags-add-usertags-to-l/bhlbflbehfoccjjenpekilgabbjjnphe ////
  106. //// * Firefox Addon Store - https://addons.mozilla.org/firefox/addon/utags/ ////
  107. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  108. //
  109. ;(() => {
  110. "use strict"
  111. var listeners = {}
  112. var getValue = async (key) => {
  113. const value = await GM.getValue(key)
  114. return value && value !== "undefined" ? JSON.parse(value) : void 0
  115. }
  116. var setValue = async (key, value) => {
  117. if (value !== void 0) {
  118. const newValue = JSON.stringify(value)
  119. if (listeners[key]) {
  120. const oldValue = await GM.getValue(key)
  121. await GM.setValue(key, newValue)
  122. if (newValue !== oldValue) {
  123. for (const func of listeners[key]) {
  124. func(key, oldValue, newValue)
  125. }
  126. }
  127. } else {
  128. await GM.setValue(key, newValue)
  129. }
  130. }
  131. }
  132. var _addValueChangeListener = (key, func) => {
  133. listeners[key] = listeners[key] || []
  134. listeners[key].push(func)
  135. return () => {
  136. if (listeners[key] && listeners[key].length > 0) {
  137. for (let i3 = listeners[key].length - 1; i3 >= 0; i3--) {
  138. if (listeners[key][i3] === func) {
  139. listeners[key].splice(i3, 1)
  140. }
  141. }
  142. }
  143. }
  144. }
  145. var addValueChangeListener = (key, func) => {
  146. if (typeof GM_addValueChangeListener !== "function") {
  147. console.warn("Do not support GM_addValueChangeListener!")
  148. return _addValueChangeListener(key, func)
  149. }
  150. const listenerId = GM_addValueChangeListener(key, func)
  151. return () => {
  152. GM_removeValueChangeListener(listenerId)
  153. }
  154. }
  155. var doc = document
  156. var win = window
  157. var uniq = (array) => [...new Set(array)]
  158. if (typeof String.prototype.replaceAll !== "function") {
  159. String.prototype.replaceAll = String.prototype.replace
  160. }
  161. var $ = (selectors, element) => (element || doc).querySelector(selectors)
  162. var $$ = (selectors, element) => [
  163. ...(element || doc).querySelectorAll(selectors),
  164. ]
  165. var getRootElement = (type) =>
  166. type === 1
  167. ? doc.head || doc.body || doc.documentElement
  168. : type === 2
  169. ? doc.body || doc.documentElement
  170. : doc.documentElement
  171. var createElement = (tagName, attributes) =>
  172. setAttributes(doc.createElement(tagName), attributes)
  173. var addElement = (parentNode, tagName, attributes) => {
  174. if (typeof parentNode === "string") {
  175. return addElement(null, parentNode, tagName)
  176. }
  177. if (!tagName) {
  178. return
  179. }
  180. if (!parentNode) {
  181. parentNode = /^(script|link|style|meta)$/.test(tagName)
  182. ? getRootElement(1)
  183. : getRootElement(2)
  184. }
  185. if (typeof tagName === "string") {
  186. const element = createElement(tagName, attributes)
  187. parentNode.append(element)
  188. return element
  189. }
  190. setAttributes(tagName, attributes)
  191. parentNode.append(tagName)
  192. return tagName
  193. }
  194. var addEventListener = (element, type, listener, options) => {
  195. if (!element) {
  196. return
  197. }
  198. if (typeof type === "object") {
  199. for (const type1 in type) {
  200. if (Object.hasOwn(type, type1)) {
  201. element.addEventListener(type1, type[type1])
  202. }
  203. }
  204. } else if (typeof type === "string" && typeof listener === "function") {
  205. element.addEventListener(type, listener, options)
  206. }
  207. }
  208. var removeEventListener = (element, type, listener, options) => {
  209. if (!element) {
  210. return
  211. }
  212. if (typeof type === "object") {
  213. for (const type1 in type) {
  214. if (Object.hasOwn(type, type1)) {
  215. element.removeEventListener(type1, type[type1])
  216. }
  217. }
  218. } else if (typeof type === "string" && typeof listener === "function") {
  219. element.removeEventListener(type, listener, options)
  220. }
  221. }
  222. var getAttribute = (element, name) =>
  223. element && element.getAttribute ? element.getAttribute(name) : null
  224. var setAttribute = (element, name, value) =>
  225. element && element.setAttribute ? element.setAttribute(name, value) : void 0
  226. var setAttributes = (element, attributes) => {
  227. if (element && attributes) {
  228. for (const name in attributes) {
  229. if (Object.hasOwn(attributes, name)) {
  230. const value = attributes[name]
  231. if (value === void 0) {
  232. continue
  233. }
  234. if (/^(value|textContent|innerText)$/.test(name)) {
  235. element[name] = value
  236. } else if (/^(innerHTML)$/.test(name)) {
  237. element[name] = createHTML(value)
  238. } else if (name === "style") {
  239. setStyle(element, value, true)
  240. } else if (/on\w+/.test(name)) {
  241. const type = name.slice(2)
  242. addEventListener(element, type, value)
  243. } else {
  244. setAttribute(element, name, value)
  245. }
  246. }
  247. }
  248. }
  249. return element
  250. }
  251. var addClass = (element, className) => {
  252. if (!element || !element.classList) {
  253. return
  254. }
  255. element.classList.add(className)
  256. }
  257. var removeClass = (element, className) => {
  258. if (!element || !element.classList) {
  259. return
  260. }
  261. element.classList.remove(className)
  262. }
  263. var hasClass = (element, className) => {
  264. if (!element || !element.classList) {
  265. return false
  266. }
  267. return element.classList.contains(className)
  268. }
  269. var setStyle = (element, values, overwrite) => {
  270. if (!element) {
  271. return
  272. }
  273. const style = element.style
  274. if (typeof values === "string") {
  275. style.cssText = overwrite ? values : style.cssText + ";" + values
  276. return
  277. }
  278. if (overwrite) {
  279. style.cssText = ""
  280. }
  281. for (const key in values) {
  282. if (Object.hasOwn(values, key)) {
  283. style[key] = values[key].replace("!important", "")
  284. }
  285. }
  286. }
  287. var isUrl = (text) => /^https?:\/\//.test(text)
  288. var throttle = (func, interval) => {
  289. let timeoutId = null
  290. let next = false
  291. const handler = (...args) => {
  292. if (timeoutId) {
  293. next = true
  294. } else {
  295. func.apply(void 0, args)
  296. timeoutId = setTimeout(() => {
  297. timeoutId = null
  298. if (next) {
  299. next = false
  300. handler()
  301. }
  302. }, interval)
  303. }
  304. }
  305. return handler
  306. }
  307. if (typeof Object.hasOwn !== "function") {
  308. Object.hasOwn = (instance, prop) =>
  309. Object.prototype.hasOwnProperty.call(instance, prop)
  310. }
  311. var extendHistoryApi = () => {
  312. const pushState = history.pushState
  313. const replaceState = history.replaceState
  314. history.pushState = function () {
  315. pushState.apply(history, arguments)
  316. window.dispatchEvent(new Event("pushstate"))
  317. window.dispatchEvent(new Event("locationchange"))
  318. }
  319. history.replaceState = function () {
  320. replaceState.apply(history, arguments)
  321. window.dispatchEvent(new Event("replacestate"))
  322. window.dispatchEvent(new Event("locationchange"))
  323. }
  324. window.addEventListener("popstate", function () {
  325. window.dispatchEvent(new Event("locationchange"))
  326. })
  327. }
  328. var getOffsetPosition = (element, referElement) => {
  329. const position = { top: 0, left: 0 }
  330. referElement = referElement || doc.body
  331. while (element && element !== referElement) {
  332. position.top += element.offsetTop
  333. position.left += element.offsetLeft
  334. element = element.offsetParent
  335. }
  336. return position
  337. }
  338. var parseInt10 = (number, defaultValue) => {
  339. if (typeof number === "number" && !Number.isNaN(number)) {
  340. return number
  341. }
  342. if (typeof defaultValue !== "number") {
  343. defaultValue = Number.NaN
  344. }
  345. if (!number) {
  346. return defaultValue
  347. }
  348. const result = Number.parseInt(number, 10)
  349. return Number.isNaN(result) ? defaultValue : result
  350. }
  351. var rootFuncArray = []
  352. var headFuncArray = []
  353. var bodyFuncArray = []
  354. var headBodyObserver
  355. var startObserveHeadBodyExists = () => {
  356. if (headBodyObserver) {
  357. return
  358. }
  359. headBodyObserver = new MutationObserver(() => {
  360. if (doc.head && doc.body) {
  361. headBodyObserver.disconnect()
  362. }
  363. if (doc.documentElement && rootFuncArray.length > 0) {
  364. for (const func of rootFuncArray) {
  365. func()
  366. }
  367. rootFuncArray.length = 0
  368. }
  369. if (doc.head && headFuncArray.length > 0) {
  370. for (const func of headFuncArray) {
  371. func()
  372. }
  373. headFuncArray.length = 0
  374. }
  375. if (doc.body && bodyFuncArray.length > 0) {
  376. for (const func of bodyFuncArray) {
  377. func()
  378. }
  379. bodyFuncArray.length = 0
  380. }
  381. })
  382. headBodyObserver.observe(doc, {
  383. childList: true,
  384. subtree: true,
  385. })
  386. }
  387. var runWhenHeadExists = (func) => {
  388. if (!doc.head) {
  389. headFuncArray.push(func)
  390. startObserveHeadBodyExists()
  391. return
  392. }
  393. func()
  394. }
  395. var runWhenDomReady = (func) => {
  396. if (doc.readyState === "interactive" || doc.readyState === "complete") {
  397. return func()
  398. }
  399. const handler = () => {
  400. if (doc.readyState === "interactive" || doc.readyState === "complete") {
  401. func()
  402. removeEventListener(doc, "readystatechange", handler)
  403. }
  404. }
  405. addEventListener(doc, "readystatechange", handler)
  406. }
  407. var isVisible = (element) => {
  408. if (typeof element.checkVisibility === "function") {
  409. return element.checkVisibility()
  410. }
  411. return element.offsetParent !== null
  412. }
  413. var isTouchScreen = () => "ontouchstart" in win
  414. var escapeHTMLPolicy =
  415. typeof trustedTypes !== "undefined" &&
  416. typeof trustedTypes.createPolicy === "function"
  417. ? trustedTypes.createPolicy("beuEscapePolicy", {
  418. createHTML: (string) => string,
  419. })
  420. : void 0
  421. var createHTML = (html) => {
  422. return escapeHTMLPolicy ? escapeHTMLPolicy.createHTML(html) : html
  423. }
  424. var addElement2 =
  425. typeof GM_addElement === "function"
  426. ? (parentNode, tagName, attributes) => {
  427. if (typeof parentNode === "string") {
  428. return addElement2(null, parentNode, tagName)
  429. }
  430. if (!tagName) {
  431. return
  432. }
  433. if (!parentNode) {
  434. parentNode = /^(script|link|style|meta)$/.test(tagName)
  435. ? getRootElement(1)
  436. : getRootElement(2)
  437. }
  438. if (typeof tagName === "string") {
  439. let attributes2
  440. if (attributes) {
  441. const entries1 = []
  442. const entries2 = []
  443. for (const entry of Object.entries(attributes)) {
  444. if (/^(on\w+|innerHTML)$/.test(entry[0])) {
  445. entries2.push(entry)
  446. } else {
  447. entries1.push(entry)
  448. }
  449. }
  450. attributes = Object.fromEntries(entries1)
  451. attributes2 = Object.fromEntries(entries2)
  452. }
  453. const element = GM_addElement(null, tagName, attributes)
  454. setAttributes(element, attributes2)
  455. parentNode.append(element)
  456. return element
  457. }
  458. setAttributes(tagName, attributes)
  459. parentNode.append(tagName)
  460. return tagName
  461. }
  462. : addElement
  463. var addStyle = (styleText) =>
  464. addElement2(null, "style", { textContent: styleText })
  465. var registerMenuCommand = (name, callback, accessKey) => {
  466. if (window !== top) {
  467. return
  468. }
  469. if (typeof GM.registerMenuCommand !== "function") {
  470. console.warn("Do not support GM.registerMenuCommand!")
  471. return
  472. }
  473. GM.registerMenuCommand(name, callback, accessKey)
  474. }
  475. var style_default =
  476. '#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}}'
  477. function createSwitch(options = {}) {
  478. const container = createElement("label", { class: "bes_switch_container" })
  479. const checkbox = createElement(
  480. "input",
  481. options.checked ? { type: "checkbox", checked: "" } : { type: "checkbox" }
  482. )
  483. addElement2(container, checkbox)
  484. const switchElm = createElement("span", { class: "bes_switch" })
  485. addElement2(switchElm, "span", { class: "bes_slider" })
  486. addElement2(container, switchElm)
  487. if (options.onchange) {
  488. addEventListener(checkbox, "change", options.onchange)
  489. }
  490. return container
  491. }
  492. function createSwitchOption(icon, text, options) {
  493. if (typeof text !== "string") {
  494. return createSwitchOption(void 0, icon, text)
  495. }
  496. const div = createElement("div", { class: "switch_option bes_option" })
  497. if (icon) {
  498. addElement2(div, "img", { src: icon, class: "bes_icon" })
  499. }
  500. addElement2(div, "span", { textContent: text, class: "bes_title" })
  501. div.append(createSwitch(options))
  502. return div
  503. }
  504. var besVersion = 55
  505. var openButton =
  506. '<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>'
  507. var openInNewTabButton =
  508. '<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>'
  509. var settingButton =
  510. '<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>'
  511. function initI18n(messageMaps, language) {
  512. language = (language || navigator.language).toLowerCase()
  513. const language2 = language.slice(0, 2)
  514. let messagesDefault
  515. let messagesLocal
  516. for (const entry of Object.entries(messageMaps)) {
  517. const langs = new Set(
  518. entry[0]
  519. .toLowerCase()
  520. .split(",")
  521. .map((v) => v.trim())
  522. )
  523. const value = entry[1]
  524. if (langs.has(language)) {
  525. messagesLocal = value
  526. }
  527. if (langs.has(language2) && !messagesLocal) {
  528. messagesLocal = value
  529. }
  530. if (langs.has("en")) {
  531. messagesDefault = value
  532. }
  533. if (langs.has("en-us") && !messagesDefault) {
  534. messagesDefault = value
  535. }
  536. }
  537. if (!messagesLocal) {
  538. messagesLocal = {}
  539. }
  540. if (!messagesDefault || messagesDefault === messagesLocal) {
  541. messagesDefault = {}
  542. }
  543. return function (key, ...parameters) {
  544. let text = messagesLocal[key] || messagesDefault[key] || key
  545. if (parameters && parameters.length > 0 && text !== key) {
  546. for (let i3 = 0; i3 < parameters.length; i3++) {
  547. text = text.replaceAll(
  548. new RegExp("\\{".concat(i3 + 1, "\\}"), "g"),
  549. String(parameters[i3])
  550. )
  551. }
  552. }
  553. return text
  554. }
  555. }
  556. var messages = {
  557. "settings.title": "Settings",
  558. "settings.otherExtensions": "Other Extensions",
  559. "settings.displaySettingsButtonInSideMenu":
  560. "Display Settings Button in Side Menu",
  561. "settings.menu.settings": "\u2699\uFE0F Settings",
  562. "settings.extensions.utags.title":
  563. "\u{1F3F7}\uFE0F UTags - Add usertags to links",
  564. "settings.extensions.links-helper.title": "\u{1F517} Links Helper",
  565. "settings.extensions.v2ex.rep.title":
  566. "V2EX.REP - \u4E13\u6CE8\u63D0\u5347 V2EX \u4E3B\u9898\u56DE\u590D\u6D4F\u89C8\u4F53\u9A8C",
  567. "settings.extensions.v2ex.min.title":
  568. "v2ex.min - V2EX Minimalist (\u6781\u7B80\u98CE\u683C)",
  569. "settings.extensions.replace-ugly-avatars.title": "Replace Ugly Avatars",
  570. "settings.extensions.more-by-pipecraft.title":
  571. "Find more useful userscripts",
  572. }
  573. var en_default = messages
  574. var messages2 = {
  575. "settings.title": "\u8BBE\u7F6E",
  576. "settings.otherExtensions": "\u5176\u4ED6\u6269\u5C55",
  577. "settings.displaySettingsButtonInSideMenu":
  578. "\u5728\u4FA7\u8FB9\u680F\u83DC\u5355\u4E2D\u663E\u793A\u8BBE\u7F6E\u6309\u94AE",
  579. "settings.menu.settings": "\u2699\uFE0F \u8BBE\u7F6E",
  580. "settings.extensions.utags.title":
  581. "\u{1F3F7}\uFE0F \u5C0F\u9C7C\u6807\u7B7E (UTags) - \u4E3A\u94FE\u63A5\u6DFB\u52A0\u7528\u6237\u6807\u7B7E",
  582. "settings.extensions.links-helper.title":
  583. "\u{1F517} \u94FE\u63A5\u52A9\u624B",
  584. "settings.extensions.v2ex.rep.title":
  585. "V2EX.REP - \u4E13\u6CE8\u63D0\u5347 V2EX \u4E3B\u9898\u56DE\u590D\u6D4F\u89C8\u4F53\u9A8C",
  586. "settings.extensions.v2ex.min.title":
  587. "v2ex.min - V2EX \u6781\u7B80\u98CE\u683C",
  588. "settings.extensions.replace-ugly-avatars.title":
  589. "\u8D50\u4F60\u4E2A\u5934\u50CF\u5427",
  590. "settings.extensions.more-by-pipecraft.title":
  591. "\u66F4\u591A\u6709\u8DA3\u7684\u811A\u672C",
  592. }
  593. var zh_cn_default = messages2
  594. var i = initI18n({
  595. "en,en-US": en_default,
  596. "zh,zh-CN": zh_cn_default,
  597. })
  598. var lang = navigator.language
  599. var locale
  600. if (lang === "zh-TW" || lang === "zh-HK") {
  601. locale = "zh-TW"
  602. } else if (lang.includes("zh")) {
  603. locale = "zh-CN"
  604. } else {
  605. locale = "en"
  606. }
  607. var relatedExtensions = [
  608. {
  609. id: "utags",
  610. title: i("settings.extensions.utags.title"),
  611. url: "https://greatest.deepsurf.us/".concat(
  612. locale,
  613. "/scripts/460718-utags-add-usertags-to-links"
  614. ),
  615. },
  616. {
  617. id: "links-helper",
  618. title: i("settings.extensions.links-helper.title"),
  619. description:
  620. "\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",
  621. url: "https://greatest.deepsurf.us/".concat(
  622. locale,
  623. "/scripts/464541-links-helper"
  624. ),
  625. },
  626. {
  627. id: "v2ex.rep",
  628. title: i("settings.extensions.v2ex.rep.title"),
  629. url: "https://greatest.deepsurf.us/".concat(
  630. locale,
  631. "/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"
  632. ),
  633. },
  634. {
  635. id: "v2ex.min",
  636. title: i("settings.extensions.v2ex.min.title"),
  637. url: "https://greatest.deepsurf.us/".concat(
  638. locale,
  639. "/scripts/463552-v2ex-min-v2ex-%E6%9E%81%E7%AE%80%E9%A3%8E%E6%A0%BC"
  640. ),
  641. },
  642. {
  643. id: "replace-ugly-avatars",
  644. title: i("settings.extensions.replace-ugly-avatars.title"),
  645. url: "https://greatest.deepsurf.us/".concat(
  646. locale,
  647. "/scripts/472616-replace-ugly-avatars"
  648. ),
  649. },
  650. {
  651. id: "more-by-pipecraft",
  652. title: i("settings.extensions.more-by-pipecraft.title"),
  653. url: "https://greatest.deepsurf.us/".concat(locale, "/users/1030884-pipecraft"),
  654. },
  655. ]
  656. var getInstalledExtesionList = () => {
  657. return $(".extension_list_container .installed_extension_list")
  658. }
  659. var getRelatedExtesionList = () => {
  660. return $(".extension_list_container .related_extension_list")
  661. }
  662. var isInstalledExtension = (id) => {
  663. const list = getInstalledExtesionList()
  664. if (!list) {
  665. return false
  666. }
  667. const installed = $('[data-extension-id="'.concat(id, '"]'), list)
  668. return Boolean(installed)
  669. }
  670. var addCurrentExtension = (extension) => {
  671. const list = getInstalledExtesionList()
  672. if (!list) {
  673. return
  674. }
  675. if (isInstalledExtension(extension.id)) {
  676. return
  677. }
  678. const element = createInstalledExtension(extension)
  679. list.append(element)
  680. const list2 = getRelatedExtesionList()
  681. if (list2) {
  682. updateRelatedExtensions(list2)
  683. }
  684. }
  685. var activeExtension = (id) => {
  686. const list = getInstalledExtesionList()
  687. if (!list) {
  688. return false
  689. }
  690. for (const element of $$(".active", list)) {
  691. removeClass(element, "active")
  692. }
  693. const installed = $('[data-extension-id="'.concat(id, '"]'), list)
  694. if (installed) {
  695. addClass(installed, "active")
  696. }
  697. }
  698. var activeExtensionList = () => {
  699. const extensionListContainer = $(".extension_list_container")
  700. if (extensionListContainer) {
  701. addClass(extensionListContainer, "bes_active")
  702. }
  703. }
  704. var deactiveExtensionList = () => {
  705. const extensionListContainer = $(".extension_list_container")
  706. if (extensionListContainer) {
  707. removeClass(extensionListContainer, "bes_active")
  708. }
  709. }
  710. var createInstalledExtension = (installedExtension) => {
  711. const div = createElement("div", {
  712. class: "installed_extension",
  713. "data-extension-id": installedExtension.id,
  714. })
  715. const a = addElement2(div, "a", {
  716. onclick: installedExtension.onclick,
  717. })
  718. addElement2(a, "span", {
  719. textContent: installedExtension.title,
  720. })
  721. const svg = addElement2(a, "svg")
  722. svg.outerHTML = createHTML(openButton)
  723. return div
  724. }
  725. var updateRelatedExtensions = (container) => {
  726. const relatedExtensionElements = $$("[data-extension-id]", container)
  727. if (relatedExtensionElements.length > 0) {
  728. for (const relatedExtensionElement of relatedExtensionElements) {
  729. if (
  730. isInstalledExtension(
  731. relatedExtensionElement.dataset.extensionId || "noid"
  732. )
  733. ) {
  734. relatedExtensionElement.remove()
  735. }
  736. }
  737. } else {
  738. container.innerHTML = createHTML("")
  739. }
  740. for (const relatedExtension of relatedExtensions) {
  741. if (
  742. isInstalledExtension(relatedExtension.id) ||
  743. $('[data-extension-id="'.concat(relatedExtension.id, '"]'), container)
  744. ) {
  745. continue
  746. }
  747. if ($$("[data-extension-id]", container).length >= 4) {
  748. return
  749. }
  750. const div4 = addElement2(container, "div", {
  751. class: "related_extension",
  752. "data-extension-id": relatedExtension.id,
  753. })
  754. const a = addElement2(div4, "a", {
  755. href: relatedExtension.url,
  756. target: "_blank",
  757. })
  758. addElement2(a, "span", {
  759. textContent: relatedExtension.title,
  760. })
  761. const svg = addElement2(a, "svg")
  762. svg.outerHTML = createHTML(openInNewTabButton)
  763. }
  764. }
  765. function createExtensionList(installedExtensions) {
  766. const div = createElement("div", {
  767. class: "extension_list_container thin_scrollbar",
  768. })
  769. addElement2(div, "h1", { textContent: i("settings.title") })
  770. const div2 = addElement2(div, "div", {
  771. class: "installed_extension_list",
  772. })
  773. for (const installedExtension of installedExtensions) {
  774. if (isInstalledExtension(installedExtension.id)) {
  775. continue
  776. }
  777. const element = createInstalledExtension(installedExtension)
  778. div2.append(element)
  779. }
  780. addElement2(div, "h2", { textContent: i("settings.otherExtensions") })
  781. const div3 = addElement2(div, "div", {
  782. class: "related_extension_list",
  783. })
  784. updateRelatedExtensions(div3)
  785. return div
  786. }
  787. var prefix = "browser_extension_settings_"
  788. var randomId = String(Math.round(Math.random() * 1e4))
  789. var settingsContainerId = prefix + "container_" + randomId
  790. var settingsElementId = prefix + "main_" + randomId
  791. var getSettingsElement = () => $("#" + settingsElementId)
  792. var getSettingsStyle = () =>
  793. style_default
  794. .replaceAll(/browser_extension_settings_container/gm, settingsContainerId)
  795. .replaceAll(/browser_extension_settings_main/gm, settingsElementId)
  796. var storageKey = "settings"
  797. var settingsOptions
  798. var settingsTable = {}
  799. var settings = {}
  800. async function getSettings() {
  801. var _a
  802. return (_a = await getValue(storageKey)) != null ? _a : {}
  803. }
  804. async function saveSettingsValue(key, value) {
  805. const settings2 = await getSettings()
  806. settings2[key] =
  807. settingsTable[key] && settingsTable[key].defaultValue === value
  808. ? void 0
  809. : value
  810. await setValue(storageKey, settings2)
  811. }
  812. function getSettingsValue(key) {
  813. var _a
  814. return Object.hasOwn(settings, key)
  815. ? settings[key]
  816. : (_a = settingsTable[key]) == null
  817. ? void 0
  818. : _a.defaultValue
  819. }
  820. var closeModal = () => {
  821. const settingsContainer = getSettingsContainer()
  822. if (settingsContainer) {
  823. settingsContainer.style.display = "none"
  824. }
  825. removeEventListener(document, "click", onDocumentClick, true)
  826. removeEventListener(document, "keydown", onDocumentKeyDown, true)
  827. }
  828. var onDocumentClick = (event) => {
  829. const target = event.target
  830. if (
  831. target == null ? void 0 : target.closest(".".concat(prefix, "container"))
  832. ) {
  833. return
  834. }
  835. closeModal()
  836. }
  837. var onDocumentKeyDown = (event) => {
  838. if (event.defaultPrevented) {
  839. return
  840. }
  841. if (event.key === "Escape") {
  842. closeModal()
  843. event.preventDefault()
  844. }
  845. }
  846. async function updateOptions() {
  847. if (!getSettingsElement()) {
  848. return
  849. }
  850. for (const key in settingsTable) {
  851. if (Object.hasOwn(settingsTable, key)) {
  852. const item = settingsTable[key]
  853. const type = item.type || "switch"
  854. switch (type) {
  855. case "switch": {
  856. const checkbox = $(
  857. "#"
  858. .concat(
  859. settingsElementId,
  860. ' .option_groups .switch_option[data-key="'
  861. )
  862. .concat(key, '"] input')
  863. )
  864. if (checkbox) {
  865. checkbox.checked = getSettingsValue(key)
  866. }
  867. break
  868. }
  869. case "select": {
  870. const options = $$(
  871. "#"
  872. .concat(
  873. settingsElementId,
  874. ' .option_groups .select_option[data-key="'
  875. )
  876. .concat(key, '"] .bes_select option')
  877. )
  878. for (const option of options) {
  879. option.selected = option.value === String(getSettingsValue(key))
  880. }
  881. break
  882. }
  883. case "textarea": {
  884. const textArea = $(
  885. "#"
  886. .concat(
  887. settingsElementId,
  888. ' .option_groups textarea[data-key="'
  889. )
  890. .concat(key, '"]')
  891. )
  892. if (textArea) {
  893. textArea.value = getSettingsValue(key)
  894. }
  895. break
  896. }
  897. default: {
  898. break
  899. }
  900. }
  901. }
  902. }
  903. if (typeof settingsOptions.onViewUpdate === "function") {
  904. const settingsMain = createSettingsElement()
  905. settingsOptions.onViewUpdate(settingsMain)
  906. }
  907. }
  908. function getSettingsContainer() {
  909. const container = $(".".concat(prefix, "container"))
  910. if (container) {
  911. const theVersion = parseInt10(container.dataset.besVersion, 0)
  912. if (theVersion < besVersion) {
  913. container.id = settingsContainerId
  914. container.dataset.besVersion = String(besVersion)
  915. }
  916. return container
  917. }
  918. return addElement2(doc.body, "div", {
  919. id: settingsContainerId,
  920. class: "".concat(prefix, "container"),
  921. "data-bes-version": besVersion,
  922. style: "display: none;",
  923. })
  924. }
  925. function getSettingsWrapper() {
  926. const container = getSettingsContainer()
  927. return (
  928. $(".".concat(prefix, "wrapper"), container) ||
  929. addElement2(container, "div", {
  930. class: "".concat(prefix, "wrapper"),
  931. })
  932. )
  933. }
  934. function initExtensionList() {
  935. const wrapper = getSettingsWrapper()
  936. if (!$(".extension_list_container", wrapper)) {
  937. const list = createExtensionList([])
  938. wrapper.append(list)
  939. }
  940. addCurrentExtension({
  941. id: settingsOptions.id,
  942. title: settingsOptions.title,
  943. onclick: showSettings,
  944. })
  945. }
  946. function createSettingsElement() {
  947. let settingsMain = getSettingsElement()
  948. if (!settingsMain) {
  949. const wrapper = getSettingsWrapper()
  950. for (const element of $$(".".concat(prefix, "main"))) {
  951. element.remove()
  952. }
  953. settingsMain = addElement2(wrapper, "div", {
  954. id: settingsElementId,
  955. class: "".concat(prefix, "main thin_scrollbar"),
  956. })
  957. addElement2(settingsMain, "a", {
  958. textContent: "Settings",
  959. class: "navigation_go_previous",
  960. onclick() {
  961. activeExtensionList()
  962. },
  963. })
  964. if (settingsOptions.title) {
  965. addElement2(settingsMain, "h2", { textContent: settingsOptions.title })
  966. }
  967. const optionGroups = []
  968. const getOptionGroup = (index) => {
  969. if (index > optionGroups.length) {
  970. for (let i3 = optionGroups.length; i3 < index; i3++) {
  971. optionGroups.push(
  972. addElement2(settingsMain, "div", {
  973. class: "option_groups",
  974. })
  975. )
  976. }
  977. }
  978. return optionGroups[index - 1]
  979. }
  980. for (const key in settingsTable) {
  981. if (Object.hasOwn(settingsTable, key)) {
  982. const item = settingsTable[key]
  983. const type = item.type || "switch"
  984. const group = item.group || 1
  985. const optionGroup = getOptionGroup(group)
  986. switch (type) {
  987. case "switch": {
  988. const switchOption = createSwitchOption(item.icon, item.title, {
  989. async onchange(event) {
  990. const checkbox = event.target
  991. if (checkbox) {
  992. let result = true
  993. if (typeof item.onConfirmChange === "function") {
  994. result = item.onConfirmChange(checkbox.checked)
  995. }
  996. if (result) {
  997. await saveSettingsValue(key, checkbox.checked)
  998. } else {
  999. checkbox.checked = !checkbox.checked
  1000. }
  1001. }
  1002. },
  1003. })
  1004. switchOption.dataset.key = key
  1005. addElement2(optionGroup, switchOption)
  1006. break
  1007. }
  1008. case "textarea": {
  1009. let timeoutId
  1010. const div = addElement2(optionGroup, "div", {
  1011. class: "bes_textarea",
  1012. })
  1013. addElement2(div, "textarea", {
  1014. "data-key": key,
  1015. placeholder: item.placeholder || "",
  1016. onkeyup(event) {
  1017. const textArea = event.target
  1018. if (timeoutId) {
  1019. clearTimeout(timeoutId)
  1020. timeoutId = void 0
  1021. }
  1022. timeoutId = setTimeout(async () => {
  1023. if (textArea) {
  1024. await saveSettingsValue(key, textArea.value.trim())
  1025. }
  1026. }, 100)
  1027. },
  1028. })
  1029. break
  1030. }
  1031. case "action": {
  1032. addElement2(optionGroup, "a", {
  1033. class: "action",
  1034. textContent: item.title,
  1035. onclick: item.onclick,
  1036. })
  1037. break
  1038. }
  1039. case "externalLink": {
  1040. const div4 = addElement2(optionGroup, "div", {
  1041. class: "bes_external_link",
  1042. })
  1043. addElement2(div4, "a", {
  1044. textContent: item.title,
  1045. href: item.url,
  1046. target: "_blank",
  1047. })
  1048. break
  1049. }
  1050. case "select": {
  1051. const div = addElement2(optionGroup, "div", {
  1052. class: "select_option bes_option",
  1053. "data-key": key,
  1054. })
  1055. if (item.icon) {
  1056. addElement2(div, "img", { src: item.icon, class: "bes_icon" })
  1057. }
  1058. addElement2(div, "span", {
  1059. textContent: item.title,
  1060. class: "bes_title",
  1061. })
  1062. const select = addElement2(div, "select", {
  1063. class: "bes_select",
  1064. async onchange() {
  1065. await saveSettingsValue(key, select.value)
  1066. },
  1067. })
  1068. for (const option of Object.entries(item.options)) {
  1069. addElement2(select, "option", {
  1070. textContent: option[0],
  1071. value: option[1],
  1072. })
  1073. }
  1074. break
  1075. }
  1076. case "tip": {
  1077. const tip = addElement2(optionGroup, "div", {
  1078. class: "bes_tip",
  1079. })
  1080. addElement2(tip, "a", {
  1081. class: "bes_tip_anchor",
  1082. textContent: item.title,
  1083. })
  1084. const tipContent = addElement2(tip, "div", {
  1085. class: "bes_tip_content",
  1086. innerHTML: createHTML(item.tipContent),
  1087. })
  1088. break
  1089. }
  1090. }
  1091. }
  1092. }
  1093. if (settingsOptions.footer) {
  1094. const footer = addElement2(settingsMain, "footer")
  1095. footer.innerHTML = createHTML(
  1096. typeof settingsOptions.footer === "string"
  1097. ? settingsOptions.footer
  1098. : '<p>Made with \u2764\uFE0F by\n <a href="https://www.pipecraft.net/" target="_blank">\n Pipecraft\n </a></p>'
  1099. )
  1100. }
  1101. }
  1102. return settingsMain
  1103. }
  1104. function addSideMenu() {
  1105. if (!getSettingsValue("displaySettingsButtonInSideMenu")) {
  1106. return
  1107. }
  1108. const menu =
  1109. $("#browser_extension_side_menu") ||
  1110. addElement2(doc.body, "div", {
  1111. id: "browser_extension_side_menu",
  1112. "data-bes-version": besVersion,
  1113. })
  1114. const button = $("button[data-bes-version]", menu)
  1115. if (button) {
  1116. const theVersion = parseInt10(button.dataset.besVersion, 0)
  1117. if (theVersion >= besVersion) {
  1118. return
  1119. }
  1120. button.remove()
  1121. }
  1122. addElement2(menu, "button", {
  1123. type: "button",
  1124. "data-bes-version": besVersion,
  1125. title: i("settings.menu.settings"),
  1126. onclick() {
  1127. setTimeout(showSettings, 1)
  1128. },
  1129. innerHTML: settingButton,
  1130. })
  1131. }
  1132. function addCommonSettings(settingsTable3) {
  1133. let maxGroup = 0
  1134. for (const key in settingsTable3) {
  1135. if (Object.hasOwn(settingsTable3, key)) {
  1136. const item = settingsTable3[key]
  1137. const group = item.group || 1
  1138. if (group > maxGroup) {
  1139. maxGroup = group
  1140. }
  1141. }
  1142. }
  1143. settingsTable3.displaySettingsButtonInSideMenu = {
  1144. title: i("settings.displaySettingsButtonInSideMenu"),
  1145. defaultValue: !(
  1146. typeof GM === "object" && typeof GM.registerMenuCommand === "function"
  1147. ),
  1148. group: maxGroup + 1,
  1149. }
  1150. }
  1151. function handleShowSettingsUrl() {
  1152. if (location.hash === "#bes-show-settings") {
  1153. setTimeout(showSettings, 100)
  1154. }
  1155. }
  1156. async function showSettings() {
  1157. const settingsContainer = getSettingsContainer()
  1158. const settingsMain = createSettingsElement()
  1159. await updateOptions()
  1160. settingsContainer.style.display = "block"
  1161. addEventListener(document, "click", onDocumentClick, true)
  1162. addEventListener(document, "keydown", onDocumentKeyDown, true)
  1163. activeExtension(settingsOptions.id)
  1164. deactiveExtensionList()
  1165. }
  1166. var initSettings = async (options) => {
  1167. settingsOptions = options
  1168. settingsTable = options.settingsTable || {}
  1169. addCommonSettings(settingsTable)
  1170. addValueChangeListener(storageKey, async () => {
  1171. settings = await getSettings()
  1172. await updateOptions()
  1173. addSideMenu()
  1174. if (typeof options.onValueChange === "function") {
  1175. options.onValueChange()
  1176. }
  1177. })
  1178. settings = await getSettings()
  1179. runWhenHeadExists(() => {
  1180. addStyle(getSettingsStyle())
  1181. })
  1182. runWhenDomReady(() => {
  1183. initExtensionList()
  1184. addSideMenu()
  1185. })
  1186. registerMenuCommand(i("settings.menu.settings"), showSettings, "o")
  1187. handleShowSettingsUrl()
  1188. }
  1189. var content_default =
  1190. '#TOFIX_uFEFF{display:block}:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) ul:not(.utags_ul)[data-utags_key],:not(#utags_should_has_higher_specificity):not(#utags_should_has_higher_specificity) ol:not(.utags_ul)[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]::after{display:none}: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:hsla(0,0%,100%,.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:99.99% !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}'
  1191. function createTag(tagName, options) {
  1192. const a = createElement("a", {
  1193. title: tagName,
  1194. class: options.isEmoji
  1195. ? "utags_text_tag utags_emoji_tag"
  1196. : "utags_text_tag",
  1197. })
  1198. if (options.enableSelect) {
  1199. a.textContent = tagName
  1200. } else {
  1201. a.dataset.utags_tag = tagName
  1202. }
  1203. if (!options.noLink) {
  1204. a.setAttribute(
  1205. "href",
  1206. "https://utags.pipecraft.net/tags/#" + encodeURIComponent(tagName)
  1207. )
  1208. a.setAttribute("target", "_blank")
  1209. }
  1210. return a
  1211. }
  1212. var messages3 = {
  1213. "settings.enableCurrentSite": "Enable UTags on the current website",
  1214. "settings.showHidedItems": "Show hidden items (tags with 'block', 'hide')",
  1215. "settings.noOpacityEffect":
  1216. "No opacity mask effect (tags with 'ignore', 'clickbait', 'promotion')",
  1217. "settings.useVisitedFunction":
  1218. "Enable browsing content tagging on the current website",
  1219. "settings.displayEffectOfTheVisitedContent":
  1220. "The display effect of the browsed content",
  1221. "settings.displayEffectOfTheVisitedContent.recordingonly":
  1222. "Save records only, no mark display",
  1223. "settings.displayEffectOfTheVisitedContent.showtagonly":
  1224. "Only display marks",
  1225. "settings.displayEffectOfTheVisitedContent.changecolor":
  1226. "Change the title color",
  1227. "settings.displayEffectOfTheVisitedContent.translucent": "Translucent",
  1228. "settings.displayEffectOfTheVisitedContent.hide": "Hide",
  1229. "settings.pinnedTags": "Add the tags you want to pin, separated by commas.",
  1230. "settings.pinnedTagsDefaultValue":
  1231. "block, hide, ignore, clickbait, promotion",
  1232. "settings.pinnedTagsPlaceholder": "foo, bar",
  1233. "settings.emojiTags": "Add the emoji tags, separated by commas",
  1234. "settings.customStyle": "Enable custom style for all websites",
  1235. "settings.customStyleCurrentSite":
  1236. "Enable custom style for the current website",
  1237. "settings.customStyleDefaultValue":
  1238. "/* 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}",
  1239. "settings.customStyleExamples": "Examples",
  1240. "settings.customStyleExamplesContent":
  1241. '<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 ',
  1242. "settings.useSimplePrompt": "Use simple prompt method to add tags",
  1243. "settings.openTagsPage": "Open the tag list page",
  1244. "settings.openDataPage": "Open the import data/export data page",
  1245. "settings.title": "\u{1F3F7}\uFE0F UTags - Add usertags to links",
  1246. "settings.information":
  1247. "After changing the settings, reload the page to take effect",
  1248. "settings.report": "Report and Issue...",
  1249. "prompt.addTags":
  1250. "[UTags] Please enter tags, multiple tags are separated by commas",
  1251. "prompt.pinnedTags": "Pinned",
  1252. "prompt.mostUsedTags": "Recently commonly used",
  1253. "prompt.recentAddedTags": "Newly added",
  1254. "prompt.emojiTags": "Emoji",
  1255. "prompt.copy": "Copy",
  1256. "prompt.cancel": "Cancle",
  1257. "prompt.ok": "OK",
  1258. "prompt.settings": "Settings",
  1259. }
  1260. var en_default2 = messages3
  1261. var messages4 = {
  1262. "settings.enableCurrentSite":
  1263. "\u5728\u5F53\u524D\u7F51\u7AD9\u542F\u7528\u5C0F\u9C7C\u6807\u7B7E",
  1264. "settings.showHidedItems":
  1265. "\u663E\u793A\u88AB\u9690\u85CF\u7684\u5185\u5BB9 (\u6DFB\u52A0\u4E86 'block', 'hide', '\u9690\u85CF'\u7B49\u6807\u7B7E\u7684\u5185\u5BB9)",
  1266. "settings.noOpacityEffect":
  1267. "\u53BB\u9664\u534A\u900F\u660E\u6548\u679C (\u6DFB\u52A0\u4E86 'sb', '\u5FFD\u7565', '\u6807\u9898\u515A'\u7B49\u6807\u7B7E\u7684\u5185\u5BB9)",
  1268. "settings.useVisitedFunction":
  1269. "\u5728\u5F53\u524D\u7F51\u7AD9\u542F\u7528\u6D4F\u89C8\u5185\u5BB9\u6807\u8BB0\u529F\u80FD",
  1270. "settings.displayEffectOfTheVisitedContent":
  1271. "\u5F53\u524D\u7F51\u7AD9\u7684\u5DF2\u6D4F\u89C8\u5185\u5BB9\u7684\u5C55\u793A\u6548\u679C",
  1272. "settings.displayEffectOfTheVisitedContent.recordingonly":
  1273. "\u53EA\u4FDD\u5B58\u8BB0\u5F55\uFF0C\u4E0D\u663E\u793A\u6807\u8BB0",
  1274. "settings.displayEffectOfTheVisitedContent.showtagonly":
  1275. "\u53EA\u663E\u793A\u6807\u8BB0",
  1276. "settings.displayEffectOfTheVisitedContent.changecolor":
  1277. "\u66F4\u6539\u6807\u9898\u989C\u8272",
  1278. "settings.displayEffectOfTheVisitedContent.translucent":
  1279. "\u534A\u900F\u660E",
  1280. "settings.displayEffectOfTheVisitedContent.hide": "\u9690\u85CF",
  1281. "settings.pinnedTags":
  1282. "\u5728\u4E0B\u9762\u6DFB\u52A0\u8981\u7F6E\u9876\u7684\u6807\u7B7E\uFF0C\u4EE5\u9017\u53F7\u5206\u9694",
  1283. "settings.pinnedTagsDefaultValue":
  1284. "\u6536\u85CF, block, sb, \u5C4F\u853D, \u9690\u85CF, \u5DF2\u9605, \u5FFD\u7565, \u6807\u9898\u515A, \u63A8\u5E7F, \u5173\u6CE8",
  1285. "settings.pinnedTagsPlaceholder": "foo, bar",
  1286. "settings.emojiTags":
  1287. "\u5728\u4E0B\u9762\u6DFB\u52A0\u8868\u60C5\u7B26\u53F7\u6807\u7B7E\uFF0C\u4EE5\u9017\u53F7\u5206\u9694",
  1288. "settings.customStyle":
  1289. "\u542F\u7528\u5168\u5C40\u81EA\u5B9A\u4E49\u6837\u5F0F",
  1290. "settings.customStyleCurrentSite":
  1291. "\u542F\u7528\u5F53\u524D\u7F51\u7AD9\u7684\u81EA\u5B9A\u4E49\u6837\u5F0F",
  1292. "settings.customStyleDefaultValue":
  1293. "/* \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}",
  1294. "settings.customStyleExamples": "\u793A\u4F8B",
  1295. "settings.customStyleExamplesContent":
  1296. '<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 ',
  1297. "settings.useSimplePrompt":
  1298. "\u4F7F\u7528\u7B80\u5355\u65B9\u5F0F\u6DFB\u52A0\u6807\u7B7E",
  1299. "settings.openTagsPage": "\u6807\u7B7E\u5217\u8868",
  1300. "settings.openDataPage":
  1301. "\u5BFC\u51FA\u6570\u636E/\u5BFC\u5165\u6570\u636E",
  1302. "settings.title":
  1303. "\u{1F3F7}\uFE0F \u5C0F\u9C7C\u6807\u7B7E (UTags) - \u4E3A\u94FE\u63A5\u6DFB\u52A0\u7528\u6237\u6807\u7B7E",
  1304. "settings.information":
  1305. "\u66F4\u6539\u8BBE\u7F6E\u540E\uFF0C\u91CD\u65B0\u52A0\u8F7D\u9875\u9762\u5373\u53EF\u751F\u6548",
  1306. "settings.report": "\u53CD\u9988\u95EE\u9898",
  1307. "prompt.addTags":
  1308. "[UTags] \u8BF7\u8F93\u5165\u6807\u7B7E\uFF0C\u591A\u4E2A\u6807\u7B7E\u4EE5\u9017\u53F7\u5206\u9694",
  1309. "prompt.pinnedTags": "\u7F6E\u9876",
  1310. "prompt.mostUsedTags": "\u6700\u8FD1\u5E38\u7528",
  1311. "prompt.recentAddedTags": "\u6700\u65B0\u6DFB\u52A0",
  1312. "prompt.emojiTags": "\u7B26\u53F7",
  1313. "prompt.copy": "\u590D\u5236",
  1314. "prompt.cancel": "\u53D6\u6D88",
  1315. "prompt.ok": "\u786E\u8BA4",
  1316. "prompt.settings": "\u8BBE\u7F6E",
  1317. }
  1318. var zh_cn_default2 = messages4
  1319. var i2 = initI18n({
  1320. "en,en-US": en_default2,
  1321. "zh,zh-CN": zh_cn_default2,
  1322. })
  1323. function trimTitle(title) {
  1324. return title ? title.replaceAll(/\s+/gm, " ").trim() : ""
  1325. }
  1326. function getTrimmedTitle(element) {
  1327. return trimTitle(element.textContent)
  1328. }
  1329. function splitTags(text) {
  1330. if (!text) {
  1331. return []
  1332. }
  1333. return [
  1334. ...new Set(
  1335. text
  1336. .replaceAll(/[\n\r\t\s]+/g, " ")
  1337. .split(/[,,]/)
  1338. .map((tag) => tag.trim())
  1339. .filter(Boolean)
  1340. ),
  1341. ]
  1342. }
  1343. var extensionVersion = "0.8.0"
  1344. var databaseVersion = 2
  1345. var storageKey2 = "extension.utags.urlmap"
  1346. var storageKeyRecentTags = "extension.utags.recenttags"
  1347. var storageKeyMostUsedTags = "extension.utags.mostusedtags"
  1348. var storageKeyRecentAddedTags = "extension.utags.recentaddedtags"
  1349. var cachedUrlMap
  1350. async function getUrlMap() {
  1351. return (await getValue(storageKey2)) || {}
  1352. }
  1353. async function getUrlMapVesion1() {
  1354. return getValue("plugin.utags.tags.v1")
  1355. }
  1356. async function getCachedUrlMap() {
  1357. if (!cachedUrlMap) {
  1358. cachedUrlMap = await getUrlMap()
  1359. }
  1360. return cachedUrlMap
  1361. }
  1362. function getTags(key) {
  1363. return (cachedUrlMap && cachedUrlMap[key]) || { tags: [] }
  1364. }
  1365. async function saveTags(key, tags, meta) {
  1366. const urlMap = await getUrlMap()
  1367. urlMap.meta = Object.assign({}, urlMap.meta, {
  1368. extensionVersion,
  1369. databaseVersion,
  1370. })
  1371. const newTags = mergeTags(tags, [])
  1372. let oldTags = []
  1373. if (newTags.length === 0) {
  1374. delete urlMap[key]
  1375. } else {
  1376. const now = Date.now()
  1377. const data = urlMap[key] || {}
  1378. oldTags = data.tags
  1379. const newMeta = Object.assign({}, data.meta, meta, {
  1380. updated: now,
  1381. })
  1382. newMeta.created = newMeta.created || now
  1383. urlMap[key] = {
  1384. tags: newTags,
  1385. meta: newMeta,
  1386. }
  1387. }
  1388. await setValue(storageKey2, urlMap)
  1389. await addRecentTags(newTags, oldTags)
  1390. }
  1391. function getScore(weight = 1) {
  1392. return (Math.floor(Date.now() / 1e3) / 1e9) * weight
  1393. }
  1394. async function addRecentTags(newTags, oldTags) {
  1395. if (newTags.length === 0) {
  1396. return
  1397. }
  1398. newTags =
  1399. oldTags && oldTags.length > 0
  1400. ? newTags.filter((v) => !oldTags.includes(v))
  1401. : newTags
  1402. if (newTags.length > 0) {
  1403. const recentTags = (await getValue(storageKeyRecentTags)) || []
  1404. const score = getScore()
  1405. for (const tag of newTags) {
  1406. recentTags.push({
  1407. tag,
  1408. score,
  1409. })
  1410. }
  1411. if (recentTags.length > 1e3) {
  1412. recentTags.splice(0, 100)
  1413. }
  1414. await setValue(storageKeyRecentTags, recentTags)
  1415. await generateMostUsedAndRecentAddedTags(recentTags)
  1416. }
  1417. }
  1418. async function generateMostUsedAndRecentAddedTags(recentTags) {
  1419. const mostUsed = {}
  1420. for (const recentTag of recentTags) {
  1421. if (!recentTag.tag) {
  1422. continue
  1423. }
  1424. if (mostUsed[recentTag.tag]) {
  1425. mostUsed[recentTag.tag].score += recentTag.score
  1426. } else if (recentTag.tag) {
  1427. mostUsed[recentTag.tag] = {
  1428. tag: recentTag.tag,
  1429. score: recentTag.score,
  1430. }
  1431. }
  1432. }
  1433. const mostUsedTags2 = Object.values(mostUsed)
  1434. .filter((v) => v.score > getScore(1.5))
  1435. .sort((a, b) => {
  1436. return b.score - a.score
  1437. })
  1438. .map((v) => v.tag)
  1439. .slice(0, 200)
  1440. const uniqSet = /* @__PURE__ */ new Set()
  1441. const recentAddedTags2 = recentTags
  1442. .map((v) => v.tag)
  1443. .reverse()
  1444. .filter((v) => v && !uniqSet.has(v) && uniqSet.add(v))
  1445. .slice(0, 200)
  1446. await setValue(storageKeyMostUsedTags, mostUsedTags2)
  1447. await setValue(storageKeyRecentAddedTags, recentAddedTags2)
  1448. }
  1449. async function getMostUsedTags() {
  1450. return (await getValue(storageKeyMostUsedTags)) || []
  1451. }
  1452. async function getRecentAddedTags() {
  1453. return (await getValue(storageKeyRecentAddedTags)) || []
  1454. }
  1455. async function getPinnedTags() {
  1456. return splitTags(getSettingsValue("pinnedTags") || "")
  1457. }
  1458. async function getEmojiTags() {
  1459. return splitTags(getSettingsValue("emojiTags") || "")
  1460. }
  1461. function addTagsValueChangeListener(func) {
  1462. addValueChangeListener(storageKey2, func)
  1463. }
  1464. addTagsValueChangeListener(async () => {
  1465. cachedUrlMap = void 0
  1466. await checkVersion()
  1467. })
  1468. async function reload() {
  1469. console.log("Current extionsion is outdated, need reload page")
  1470. const urlMap = await getUrlMap()
  1471. urlMap.meta = urlMap.meta || {}
  1472. await setValue(storageKey2, urlMap)
  1473. location.reload()
  1474. }
  1475. async function checkVersion() {
  1476. cachedUrlMap = await getUrlMap()
  1477. const meta = cachedUrlMap.meta || {}
  1478. if (meta.extensionVersion !== extensionVersion) {
  1479. console.log(
  1480. "Previous extension version:",
  1481. meta.extensionVersion,
  1482. "current extension version:",
  1483. extensionVersion
  1484. )
  1485. if (meta.extensionVersion > extensionVersion) {
  1486. }
  1487. }
  1488. if (meta.databaseVersion !== databaseVersion) {
  1489. console.log(
  1490. "Previous database version:",
  1491. meta.databaseVersion,
  1492. "current database version:",
  1493. databaseVersion
  1494. )
  1495. if (meta.databaseVersion > databaseVersion) {
  1496. await reload()
  1497. return false
  1498. }
  1499. }
  1500. return true
  1501. }
  1502. function isValidKey(key) {
  1503. return isUrl(key)
  1504. }
  1505. function isValidTags(tags) {
  1506. return Array.isArray(tags)
  1507. }
  1508. function mergeTags(tags, tags2) {
  1509. tags = tags || []
  1510. tags2 = tags2 || []
  1511. return uniq(
  1512. tags
  1513. .concat(tags2)
  1514. .map((v) => (v ? String(v).trim() : v))
  1515. .filter(Boolean)
  1516. )
  1517. }
  1518. async function migrationData(urlMap) {
  1519. console.log("Before migration", JSON.stringify(urlMap))
  1520. const meta = urlMap.meta || {}
  1521. const now = Date.now()
  1522. const meta2 = { created: now, updated: now }
  1523. if (!meta.databaseVersion) {
  1524. meta.databaseVersion = 1
  1525. }
  1526. if (meta.databaseVersion === 1) {
  1527. for (const key in urlMap) {
  1528. if (!Object.hasOwn(urlMap, key)) {
  1529. continue
  1530. }
  1531. if (!isValidKey(key)) {
  1532. continue
  1533. }
  1534. const tags = urlMap[key]
  1535. if (!isValidTags(tags)) {
  1536. throw new Error("Invaid data format.")
  1537. }
  1538. const newTags = mergeTags(tags, [])
  1539. if (newTags.length > 0) {
  1540. urlMap[key] = { tags: newTags, meta: meta2 }
  1541. } else {
  1542. delete urlMap[key]
  1543. }
  1544. }
  1545. meta.databaseVersion = 2
  1546. }
  1547. if (meta.databaseVersion === 2) {
  1548. }
  1549. urlMap.meta = meta
  1550. console.log("After migration", JSON.stringify(urlMap))
  1551. return urlMap
  1552. }
  1553. async function mergeData(urlMapNew) {
  1554. if (typeof urlMapNew !== "object") {
  1555. throw new TypeError("Invalid data format")
  1556. }
  1557. let numberOfLinks = 0
  1558. let numberOfTags = 0
  1559. const urlMap = await getUrlMap()
  1560. if (
  1561. !urlMapNew.meta ||
  1562. urlMapNew.meta.databaseVersion !== urlMap.meta.databaseVersion
  1563. ) {
  1564. urlMapNew = await migrationData(urlMapNew)
  1565. }
  1566. if (urlMapNew.meta.databaseVersion !== urlMap.meta.databaseVersion) {
  1567. throw new Error("Invalid database version")
  1568. }
  1569. for (const key in urlMapNew) {
  1570. if (!Object.hasOwn(urlMapNew, key)) {
  1571. continue
  1572. }
  1573. if (!isValidKey(key)) {
  1574. continue
  1575. }
  1576. const tags = urlMapNew[key].tags || []
  1577. const meta = urlMapNew[key].meta || {}
  1578. if (!isValidTags(tags)) {
  1579. throw new Error("Invaid data format.")
  1580. }
  1581. const orgData = urlMap[key] || { tags: [] }
  1582. const orgTags = orgData.tags || []
  1583. const newTags = mergeTags(orgTags, tags)
  1584. const now = Date.now()
  1585. if (newTags.length > 0) {
  1586. const orgMeta = orgData.meta || {}
  1587. const created = Math.min(orgMeta.created || now, meta.created || now)
  1588. const updated = Math.max(
  1589. orgMeta.updated || 0,
  1590. meta.updated || 0,
  1591. created
  1592. )
  1593. const newMata = Object.assign({}, orgMeta, meta, { created, updated })
  1594. urlMap[key] = Object.assign({}, orgData, {
  1595. tags: newTags,
  1596. meta: newMata,
  1597. })
  1598. numberOfTags += Math.max(newTags.length - orgTags.length, 0)
  1599. if (orgTags.length === 0) {
  1600. numberOfLinks++
  1601. }
  1602. } else {
  1603. delete urlMap[key]
  1604. }
  1605. }
  1606. await setValue(storageKey2, urlMap)
  1607. console.log(
  1608. "\u6570\u636E\u5DF2\u6210\u529F\u5BFC\u5165\uFF0C\u65B0\u589E "
  1609. .concat(numberOfLinks, " \u6761\u94FE\u63A5\uFF0C\u65B0\u589E ")
  1610. .concat(numberOfTags, " \u6761\u6807\u7B7E\u3002")
  1611. )
  1612. return { numberOfLinks, numberOfTags }
  1613. }
  1614. async function migration() {
  1615. const result = await checkVersion()
  1616. if (!result) {
  1617. return
  1618. }
  1619. cachedUrlMap = await getUrlMap()
  1620. const meta = cachedUrlMap.meta || {}
  1621. if (meta.databaseVersion !== databaseVersion) {
  1622. meta.databaseVersion = meta.databaseVersion || 1
  1623. if (meta.databaseVersion < databaseVersion) {
  1624. console.log("Migration start")
  1625. await saveTags("any", [])
  1626. console.log("Migration done")
  1627. }
  1628. }
  1629. const urlMapVer1 = await getUrlMapVesion1()
  1630. if (urlMapVer1) {
  1631. console.log(
  1632. "Migration start: database version 1 to database version",
  1633. databaseVersion
  1634. )
  1635. const result2 = await mergeData(urlMapVer1)
  1636. if (result2) {
  1637. await setValue("plugin.utags.tags.v1", null)
  1638. }
  1639. }
  1640. }
  1641. async function outputData() {
  1642. if (
  1643. /^(utags\.pipecraft\.net|localhost|127\.0\.0\.1)$/.test(location.hostname)
  1644. ) {
  1645. const urlMap = await getUrlMap()
  1646. const textarea = createElement("textarea")
  1647. textarea.id = "utags_output"
  1648. textarea.setAttribute("style", "display:none")
  1649. textarea.value = JSON.stringify(urlMap)
  1650. doc.body.append(textarea)
  1651. textarea.addEventListener("click", async () => {
  1652. if (textarea.dataset.utags_type === "export") {
  1653. const urlMap2 = await getUrlMap()
  1654. textarea.value = JSON.stringify(urlMap2)
  1655. textarea.dataset.utags_type = "export_done"
  1656. textarea.click()
  1657. } else if (textarea.dataset.utags_type === "import") {
  1658. const data = textarea.value
  1659. try {
  1660. const result = await mergeData(JSON.parse(data))
  1661. textarea.value = JSON.stringify(result)
  1662. textarea.dataset.utags_type = "import_done"
  1663. textarea.click()
  1664. } catch (error) {
  1665. console.error(error)
  1666. textarea.value = JSON.stringify(error)
  1667. textarea.dataset.utags_type = "import_failed"
  1668. textarea.click()
  1669. }
  1670. }
  1671. })
  1672. }
  1673. }
  1674. function getFirstHeadElement(tagName = "h1") {
  1675. for (const element of $$(tagName)) {
  1676. if (element.closest(".browser_extension_settings_container")) {
  1677. continue
  1678. }
  1679. return element
  1680. }
  1681. return void 0
  1682. }
  1683. function sortTags(tags, privilegedTags) {
  1684. return tags.sort((a, b) => {
  1685. const pA = privilegedTags.includes(a)
  1686. const pB = privilegedTags.includes(b)
  1687. if (pA && pB) {
  1688. return 0
  1689. }
  1690. if (pA) {
  1691. return -1
  1692. }
  1693. if (pB) {
  1694. return 1
  1695. }
  1696. return 0
  1697. })
  1698. }
  1699. function filterTags(tags, removed) {
  1700. if (typeof removed === "string") {
  1701. removed = [removed]
  1702. }
  1703. if (removed.length === 0) {
  1704. return tags
  1705. }
  1706. return tags.filter((value) => {
  1707. return !removed.includes(value)
  1708. })
  1709. }
  1710. async function copyText(data) {
  1711. const textArea = createElement("textarea", {
  1712. style: "position: absolute; left: -100%;",
  1713. contentEditable: "true",
  1714. })
  1715. textArea.value = data.replaceAll("\xA0", " ")
  1716. document.body.append(textArea)
  1717. textArea.select()
  1718. await navigator.clipboard.writeText(textArea.value)
  1719. textArea.remove()
  1720. }
  1721. function deleteUrlParameters(urlString, keys, excepts) {
  1722. const url = new URL(urlString)
  1723. if (keys === "*") {
  1724. if (excepts && excepts.length > 0) {
  1725. const parameters2 = new URLSearchParams(url.search)
  1726. keys = []
  1727. for (const key of parameters2.keys()) {
  1728. if (!excepts.includes(key)) {
  1729. keys.push(key)
  1730. }
  1731. }
  1732. } else {
  1733. url.search = ""
  1734. return url.toString()
  1735. }
  1736. }
  1737. if (typeof keys === "string") {
  1738. keys = [keys]
  1739. }
  1740. const parameters = new URLSearchParams(url.search)
  1741. for (const key of keys) {
  1742. parameters.delete(key)
  1743. }
  1744. url.search = parameters.size === 0 ? "" : "?" + parameters.toString()
  1745. return url.toString()
  1746. }
  1747. function getUrlParameters(urlString, keys, allowEmpty = false) {
  1748. const url = new URL(urlString)
  1749. if (typeof keys === "string") {
  1750. keys = [keys]
  1751. }
  1752. const result = {}
  1753. const parameters = new URLSearchParams(url.search)
  1754. for (const key of keys) {
  1755. if (key) {
  1756. const value = parameters.get(key)
  1757. if (
  1758. (allowEmpty && value !== void 0 && value !== null) ||
  1759. (!allowEmpty && value)
  1760. ) {
  1761. result[key] = value
  1762. }
  1763. }
  1764. }
  1765. return result
  1766. }
  1767. function createModal(attributes) {
  1768. const div = createElement("div", {
  1769. class: "utags_modal",
  1770. })
  1771. const wrapper = addElement2(div, "div", {
  1772. class: "utags_modal_wrapper",
  1773. })
  1774. const content = addElement2(wrapper, "div", attributes)
  1775. addClass(content, "utags_modal_content")
  1776. let removed = false
  1777. return {
  1778. remove() {
  1779. if (!removed) {
  1780. removed = true
  1781. div.remove()
  1782. }
  1783. },
  1784. append(element) {
  1785. ;(element || doc.body).append(div)
  1786. },
  1787. getContentElement() {
  1788. return content
  1789. },
  1790. }
  1791. }
  1792. var pinnedTags
  1793. var mostUsedTags
  1794. var recentAddedTags
  1795. var emojiTags
  1796. var displayedTags = /* @__PURE__ */ new Set()
  1797. var currentTags = /* @__PURE__ */ new Set()
  1798. function onSelect(selected, input) {
  1799. if (selected) {
  1800. input.value = ""
  1801. const tags = splitTags(selected)
  1802. for (const tag of tags) {
  1803. currentTags.add(tag)
  1804. }
  1805. updateLists()
  1806. }
  1807. }
  1808. function removeTag(tag) {
  1809. if (tag) {
  1810. tag = tag.trim()
  1811. currentTags.delete(tag)
  1812. updateLists()
  1813. }
  1814. }
  1815. function updateLists(container) {
  1816. displayedTags = /* @__PURE__ */ new Set()
  1817. const ul1 = $(".utags_modal_content ul.utags_current_tags", container)
  1818. if (ul1) {
  1819. updateCurrentTagList(ul1)
  1820. }
  1821. const ul = $(
  1822. ".utags_modal_content ul.utags_select_list.utags_pined_list",
  1823. container
  1824. )
  1825. if (ul) {
  1826. updateCandidateTagList(ul, pinnedTags)
  1827. }
  1828. const ul4 = $(
  1829. ".utags_modal_content ul.utags_select_list.utags_emoji_list",
  1830. container
  1831. )
  1832. if (ul4) {
  1833. updateCandidateTagList(ul4, emojiTags, 1e3)
  1834. }
  1835. const ul2 = $(
  1836. ".utags_modal_content ul.utags_select_list.utags_most_used",
  1837. container
  1838. )
  1839. if (ul2) {
  1840. updateCandidateTagList(ul2, mostUsedTags)
  1841. }
  1842. const ul3 = $(
  1843. ".utags_modal_content ul.utags_select_list.utags_recent_added",
  1844. container
  1845. )
  1846. if (ul3) {
  1847. updateCandidateTagList(ul3, recentAddedTags)
  1848. }
  1849. }
  1850. function updateCandidateTagList(ul, candidateTags, limitSize) {
  1851. ul.textContent = ""
  1852. let index = 0
  1853. for (const text of candidateTags) {
  1854. if (displayedTags.has(text)) {
  1855. continue
  1856. }
  1857. displayedTags.add(text)
  1858. const li = addElement2(ul, "li", {})
  1859. addElement2(li, "span", {
  1860. textContent: text,
  1861. })
  1862. index++
  1863. if (index >= (limitSize || 50)) {
  1864. break
  1865. }
  1866. }
  1867. }
  1868. function getNextList(parentElement) {
  1869. let parentNext = parentElement.nextElementSibling
  1870. while (parentNext && parentNext.children.length === 0) {
  1871. parentNext = parentNext.nextElementSibling
  1872. }
  1873. return parentNext
  1874. }
  1875. function getPreviousList(parentElement) {
  1876. let parentPrevious = parentElement.previousElementSibling
  1877. while (parentPrevious && parentPrevious.children.length === 0) {
  1878. parentPrevious = parentPrevious.previousElementSibling
  1879. }
  1880. return parentPrevious
  1881. }
  1882. function updateCurrentTagList(ul) {
  1883. ul.textContent = ""
  1884. const sortedTags = sortTags([...currentTags], emojiTags)
  1885. for (const tag of sortedTags) {
  1886. displayedTags.add(tag)
  1887. const li = addElement2(ul, "li")
  1888. const a = createTag(tag, {
  1889. isEmoji: emojiTags.includes(tag),
  1890. noLink: true,
  1891. })
  1892. li.append(a)
  1893. }
  1894. }
  1895. function removeAllActive(type) {
  1896. if (type !== 2) {
  1897. const selector = ".utags_modal_content ul.utags_select_list .utags_active"
  1898. for (const li of $$(selector)) {
  1899. removeClass(li, "utags_active")
  1900. }
  1901. }
  1902. if (type !== 1) {
  1903. const selector =
  1904. ".utags_modal_content ul.utags_select_list .utags_active2"
  1905. for (const li of $$(selector)) {
  1906. removeClass(li, "utags_active2")
  1907. }
  1908. }
  1909. }
  1910. async function copyCurrentTags(input) {
  1911. const value = sortTags([...currentTags], emojiTags).join(", ")
  1912. await copyText(value)
  1913. input.value = value
  1914. input.focus()
  1915. input.select()
  1916. }
  1917. function stopEventPropagation(event) {
  1918. event.preventDefault()
  1919. event.stopPropagation()
  1920. event.stopImmediatePropagation()
  1921. }
  1922. function createPromptView(message, value, resolve) {
  1923. const modal = createModal({ class: "utags_prompt" })
  1924. const content = modal.getContentElement()
  1925. value = value || ""
  1926. addElement2(content, "span", {
  1927. class: "utags_title",
  1928. textContent: message,
  1929. })
  1930. const currentTagsWrapper = addElement2(content, "div", {
  1931. class: "utags_current_tags_wrapper",
  1932. })
  1933. addElement2(currentTagsWrapper, "span", {
  1934. textContent: "",
  1935. style: "display: none;",
  1936. "data-utags": "",
  1937. })
  1938. addElement2(currentTagsWrapper, "ul", {
  1939. class: "utags_current_tags utags_ul",
  1940. })
  1941. const input = addElement2(content, "input", {
  1942. type: "text",
  1943. placeholder: "foo, bar",
  1944. onblur(event) {
  1945. if (event.relatedTarget) {
  1946. input.focus()
  1947. stopEventPropagation(event)
  1948. }
  1949. setTimeout(() => {
  1950. if (doc.activeElement === doc.body) {
  1951. closeModal2()
  1952. }
  1953. }, 1)
  1954. },
  1955. })
  1956. setTimeout(() => {
  1957. input.focus()
  1958. input.select()
  1959. })
  1960. addElement2(currentTagsWrapper, "button", {
  1961. type: "button",
  1962. class: "utags_button_copy",
  1963. textContent: i2("prompt.copy"),
  1964. async onclick() {
  1965. await copyCurrentTags(input)
  1966. },
  1967. })
  1968. const listWrapper = addElement2(content, "div", {
  1969. class: "utags_list_wrapper",
  1970. })
  1971. addElement2(listWrapper, "ul", {
  1972. class: "utags_select_list utags_pined_list",
  1973. "data-utags_list_name": i2("prompt.pinnedTags"),
  1974. })
  1975. addElement2(listWrapper, "ul", {
  1976. class: "utags_select_list utags_most_used",
  1977. "data-utags_list_name": i2("prompt.mostUsedTags"),
  1978. })
  1979. addElement2(listWrapper, "ul", {
  1980. class: "utags_select_list utags_recent_added",
  1981. "data-utags_list_name": i2("prompt.recentAddedTags"),
  1982. })
  1983. addElement2(listWrapper, "ul", {
  1984. class: "utags_select_list utags_emoji_list",
  1985. "data-utags_list_name": i2("prompt.emojiTags"),
  1986. })
  1987. updateLists(content)
  1988. const buttonWrapper = addElement2(content, "div", {
  1989. class: "utags_buttons_wrapper",
  1990. })
  1991. let closed = false
  1992. const closeModal2 = (value2) => {
  1993. if (closed) {
  1994. return
  1995. }
  1996. closed = true
  1997. removeEventListener(input, "keydown", keydonwHandler, true)
  1998. removeEventListener(doc, "keydown", keydonwHandler, true)
  1999. removeEventListener(doc, "mousedown", mousedownHandler, true)
  2000. removeEventListener(doc, "click", clickHandler, true)
  2001. removeEventListener(doc, "mouseover", mouseoverHandler, true)
  2002. setTimeout(() => {
  2003. modal.remove()
  2004. })
  2005. resolve(value2 == null ? null : value2)
  2006. }
  2007. const okHandler = () => {
  2008. closeModal2(Array.from(currentTags).join(","))
  2009. }
  2010. addElement2(buttonWrapper, "button", {
  2011. type: "button",
  2012. textContent: i2("prompt.cancel"),
  2013. onclick() {
  2014. closeModal2()
  2015. },
  2016. })
  2017. addElement2(buttonWrapper, "button", {
  2018. type: "button",
  2019. class: "utags_primary",
  2020. textContent: i2("prompt.ok"),
  2021. onclick() {
  2022. onSelect(input.value.trim(), input)
  2023. okHandler()
  2024. },
  2025. })
  2026. const keydonwHandler = (event) => {
  2027. if (event.defaultPrevented || !$(".utags_modal_content")) {
  2028. return
  2029. }
  2030. let current = $(".utags_modal_content ul.utags_select_list .utags_active")
  2031. switch (event.key) {
  2032. case "Escape": {
  2033. stopEventPropagation(event)
  2034. closeModal2()
  2035. break
  2036. }
  2037. case "Enter": {
  2038. stopEventPropagation(event)
  2039. input.focus()
  2040. if (current) {
  2041. onSelect(current.textContent, input)
  2042. } else if (input.value.trim()) {
  2043. onSelect(input.value.trim(), input)
  2044. } else {
  2045. okHandler()
  2046. }
  2047. break
  2048. }
  2049. case "Tab": {
  2050. stopEventPropagation(event)
  2051. input.focus()
  2052. break
  2053. }
  2054. case "ArrowDown": {
  2055. stopEventPropagation(event)
  2056. input.focus()
  2057. current = $(
  2058. ".utags_modal_content ul.utags_select_list .utags_active,.utags_modal_content ul.utags_select_list .utags_active2"
  2059. )
  2060. if (current) {
  2061. const next = current.nextElementSibling
  2062. if (next) {
  2063. next.scrollIntoView({ block: "end" })
  2064. removeAllActive()
  2065. addClass(next, "utags_active")
  2066. }
  2067. } else {
  2068. const next = $(".utags_modal_content ul.utags_select_list li")
  2069. if (next) {
  2070. next.scrollIntoView({ block: "end" })
  2071. removeAllActive()
  2072. addClass(next, "utags_active")
  2073. }
  2074. }
  2075. break
  2076. }
  2077. case "ArrowUp": {
  2078. stopEventPropagation(event)
  2079. input.focus()
  2080. current = $(
  2081. ".utags_modal_content ul.utags_select_list .utags_active,.utags_modal_content ul.utags_select_list .utags_active2"
  2082. )
  2083. if (current) {
  2084. const previous = current.previousElementSibling
  2085. if (previous) {
  2086. previous.scrollIntoView({ block: "end" })
  2087. removeAllActive()
  2088. addClass(previous, "utags_active")
  2089. }
  2090. }
  2091. break
  2092. }
  2093. case "ArrowLeft": {
  2094. stopEventPropagation(event)
  2095. input.focus()
  2096. current = $(
  2097. ".utags_modal_content ul.utags_select_list .utags_active,.utags_modal_content ul.utags_select_list .utags_active2"
  2098. )
  2099. if (current) {
  2100. const parentElement = current.parentElement
  2101. const index = Array.prototype.indexOf.call(
  2102. parentElement.children,
  2103. current
  2104. )
  2105. const parentPrevious = getPreviousList(parentElement)
  2106. if (parentPrevious) {
  2107. removeAllActive()
  2108. const newIndex = Math.min(
  2109. parentPrevious.children.length - 1,
  2110. index
  2111. )
  2112. const next = parentPrevious.children[newIndex]
  2113. next.scrollIntoView({ block: "end" })
  2114. addClass(next, "utags_active")
  2115. }
  2116. }
  2117. break
  2118. }
  2119. case "ArrowRight": {
  2120. stopEventPropagation(event)
  2121. input.focus()
  2122. current = $(
  2123. ".utags_modal_content ul.utags_select_list .utags_active,.utags_modal_content ul.utags_select_list .utags_active2"
  2124. )
  2125. if (current) {
  2126. const parentElement = current.parentElement
  2127. const index = Array.prototype.indexOf.call(
  2128. parentElement.children,
  2129. current
  2130. )
  2131. const parentNext = getNextList(parentElement)
  2132. if (parentNext) {
  2133. removeAllActive()
  2134. const newIndex = Math.min(parentNext.children.length - 1, index)
  2135. const next = parentNext.children[newIndex]
  2136. next.scrollIntoView({ block: "end" })
  2137. addClass(next, "utags_active")
  2138. }
  2139. }
  2140. break
  2141. }
  2142. default: {
  2143. removeAllActive()
  2144. break
  2145. }
  2146. }
  2147. }
  2148. addEventListener(input, "keydown", keydonwHandler, true)
  2149. addEventListener(doc, "keydown", keydonwHandler, true)
  2150. const mousedownHandler = (event) => {
  2151. if (event.defaultPrevented || !$(".utags_modal_content")) {
  2152. return
  2153. }
  2154. const target = event.target
  2155. if (!target) {
  2156. return
  2157. }
  2158. if (target.closest(".utags_modal_content")) {
  2159. if (target === input) {
  2160. return
  2161. }
  2162. event.preventDefault()
  2163. input.focus()
  2164. } else {
  2165. event.preventDefault()
  2166. input.focus()
  2167. }
  2168. }
  2169. addEventListener(doc, "mousedown", mousedownHandler, true)
  2170. const clickHandler = (event) => {
  2171. if (event.defaultPrevented || !$(".utags_modal_content")) {
  2172. return
  2173. }
  2174. const target = event.target
  2175. if (!target) {
  2176. return
  2177. }
  2178. if (
  2179. !target.closest(".utags_modal_content button") &&
  2180. !target.closest(".utags_modal_content .utags_footer a")
  2181. ) {
  2182. stopEventPropagation(event)
  2183. }
  2184. if (target.closest(".utags_modal_content")) {
  2185. input.focus()
  2186. if (target.closest(".utags_modal_content ul.utags_select_list li")) {
  2187. onSelect(target.textContent, input)
  2188. }
  2189. if (target.closest(".utags_modal_content ul.utags_current_tags li a")) {
  2190. removeTag(target.dataset.utags_tag)
  2191. }
  2192. } else {
  2193. closeModal2()
  2194. }
  2195. }
  2196. addEventListener(doc, "click", clickHandler, true)
  2197. const mouseoverHandler = (event) => {
  2198. const target = event.target
  2199. if (!(target == null ? void 0 : target.closest(".utags_modal_content"))) {
  2200. return
  2201. }
  2202. const li = target.closest("ul.utags_select_list li")
  2203. if (li) {
  2204. removeAllActive()
  2205. addClass(li, "utags_active2")
  2206. } else {
  2207. removeAllActive(2)
  2208. }
  2209. }
  2210. addEventListener(doc, "mousemove", mouseoverHandler, true)
  2211. const footer = addElement2(content, "div", {
  2212. class: "utags_footer",
  2213. })
  2214. addElement2(footer, "a", {
  2215. class: "utags_link_settings",
  2216. textContent: i2("prompt.settings"),
  2217. async onclick() {
  2218. closeModal2()
  2219. setTimeout(showSettings, 1)
  2220. },
  2221. })
  2222. modal.append()
  2223. }
  2224. async function advancedPrompt(message, value) {
  2225. pinnedTags = await getPinnedTags()
  2226. mostUsedTags = await getMostUsedTags()
  2227. recentAddedTags = await getRecentAddedTags()
  2228. emojiTags = await getEmojiTags()
  2229. currentTags = new Set(splitTags(value))
  2230. return new Promise((resolve) => {
  2231. createPromptView(message, value, resolve)
  2232. })
  2233. }
  2234. async function simplePrompt(message, value) {
  2235. return prompt(message, value)
  2236. }
  2237. var prefix2 = location.origin + "/"
  2238. var host = location.host
  2239. var useVisitedFunction = false
  2240. var displayMark = false
  2241. var isAvailable = false
  2242. var cache = {}
  2243. function setPrefix(newPrefix) {
  2244. prefix2 = newPrefix
  2245. }
  2246. function isAvailableOnCurrentSite() {
  2247. return isAvailable
  2248. }
  2249. function setVisitedAvailable(value) {
  2250. isAvailable = value
  2251. }
  2252. function onSettingsChange() {
  2253. useVisitedFunction = getSettingsValue("useVisitedFunction_".concat(host))
  2254. displayMark =
  2255. getSettingsValue("displayEffectOfTheVisitedContent_".concat(host)) !== "0"
  2256. }
  2257. function getVisitedLinks() {
  2258. if (!useVisitedFunction) {
  2259. return []
  2260. }
  2261. return JSON.parse(localStorage.getItem("utags_visited") || "[]") || []
  2262. }
  2263. function saveVisitedLinks(newVisitedLinks) {
  2264. if (useVisitedFunction) {
  2265. localStorage.setItem("utags_visited", JSON.stringify(newVisitedLinks))
  2266. }
  2267. }
  2268. function convertKey(url) {
  2269. if (url.includes(prefix2)) {
  2270. return url.slice(prefix2.length)
  2271. }
  2272. return url
  2273. }
  2274. var TAG_VISITED = ":visited"
  2275. function addVisited(key) {
  2276. if (key && !cache[key]) {
  2277. cache[key] = 1
  2278. } else {
  2279. return
  2280. }
  2281. key = convertKey(key)
  2282. const visitedLinks = getVisitedLinks()
  2283. if (!visitedLinks.includes(key)) {
  2284. visitedLinks.push(key)
  2285. saveVisitedLinks(visitedLinks)
  2286. }
  2287. }
  2288. function removeVisited(key) {
  2289. key = convertKey(key)
  2290. const visitedLinks = getVisitedLinks()
  2291. if (visitedLinks.includes(key)) {
  2292. const newVisitedLinks = visitedLinks.filter((value) => {
  2293. return value !== key
  2294. })
  2295. saveVisitedLinks(newVisitedLinks)
  2296. }
  2297. }
  2298. function isVisited(key) {
  2299. if (!displayMark) {
  2300. return false
  2301. }
  2302. key = convertKey(key)
  2303. const visitedLinks = getVisitedLinks()
  2304. return visitedLinks.includes(key)
  2305. }
  2306. function markElementWhetherVisited(key, element) {
  2307. if (isVisited(key)) {
  2308. element.dataset.utags_visited = "1"
  2309. } else if (element.dataset.utags_visited === "1") {
  2310. delete element.dataset.utags_visited
  2311. }
  2312. }
  2313. var numberLimitOfShowAllUtagsInArea = 10
  2314. var lastShownArea
  2315. var isPromptShown = false
  2316. function hideAllUtagsInArea(target) {
  2317. const element = $(".utags_show_all")
  2318. if (!element) {
  2319. return
  2320. }
  2321. if (element === target || element.contains(target)) {
  2322. return
  2323. }
  2324. if (!target) {
  2325. lastShownArea = void 0
  2326. }
  2327. for (const element2 of $$(".utags_show_all")) {
  2328. addClass(element2, "utags_hide_all")
  2329. removeClass(element2, "utags_show_all")
  2330. setTimeout(() => {
  2331. removeClass(element2, "utags_hide_all")
  2332. })
  2333. }
  2334. }
  2335. function showAllUtagsInArea(element) {
  2336. if (!element) {
  2337. return false
  2338. }
  2339. const utags = $$(".utags_ul", element)
  2340. if (utags.length > 0 && utags.length <= numberLimitOfShowAllUtagsInArea) {
  2341. addClass(element, "utags_show_all")
  2342. return true
  2343. }
  2344. return false
  2345. }
  2346. function findElementToShowAllUtags(target) {
  2347. hideAllUtagsInArea(target)
  2348. if (!target) {
  2349. return
  2350. }
  2351. const targets = []
  2352. let width
  2353. let height
  2354. do {
  2355. targets.push(target)
  2356. const tagName = target.tagName
  2357. const style = getComputedStyle(target)
  2358. if (
  2359. style.position === "fixed" ||
  2360. style.position === "sticky" ||
  2361. /^(BODY|TABLE|UL|OL|NAV|ARTICLE|SECTION|ASIDE)$/.test(tagName)
  2362. ) {
  2363. break
  2364. }
  2365. target = target.parentElement
  2366. if (target) {
  2367. width = target.offsetWidth || target.clientWidth
  2368. height = target.offsetHeight || target.clientHeight
  2369. } else {
  2370. width = 0
  2371. height = 0
  2372. }
  2373. } while (targets.length < 8 && target && width > 20 && height > 10)
  2374. while (targets.length > 0) {
  2375. const area = targets.pop()
  2376. if (showAllUtagsInArea(area)) {
  2377. if (lastShownArea === area) {
  2378. hideAllUtagsInArea()
  2379. return
  2380. }
  2381. lastShownArea = area
  2382. return
  2383. }
  2384. }
  2385. hideAllUtagsInArea()
  2386. lastShownArea = void 0
  2387. }
  2388. function bindDocumentEvents() {
  2389. const eventType = isTouchScreen() ? "touchstart" : "click"
  2390. addEventListener(
  2391. doc,
  2392. eventType,
  2393. (event) => {
  2394. const target = event.target
  2395. if (!target) {
  2396. return
  2397. }
  2398. if (target.closest(".utags_prompt")) {
  2399. return
  2400. }
  2401. if (target.closest(".utags_ul")) {
  2402. const captainTag = target.closest(
  2403. ".utags_captain_tag,.utags_captain_tag2"
  2404. )
  2405. const textTag = target.closest(".utags_text_tag")
  2406. if (captainTag) {
  2407. event.preventDefault()
  2408. event.stopPropagation()
  2409. event.stopImmediatePropagation()
  2410. if (!captainTag.dataset.utags_key || isPromptShown) {
  2411. return
  2412. }
  2413. isPromptShown = true
  2414. setTimeout(async () => {
  2415. const key = captainTag.dataset.utags_key
  2416. const tags = captainTag.dataset.utags_tags || ""
  2417. const meta = captainTag.dataset.utags_meta
  2418. ? JSON.parse(captainTag.dataset.utags_meta)
  2419. : void 0
  2420. const myPrompt = getSettingsValue("useSimplePrompt")
  2421. ? simplePrompt
  2422. : advancedPrompt
  2423. const newTags = await myPrompt(i2("prompt.addTags"), tags)
  2424. isPromptShown = false
  2425. captainTag.focus()
  2426. if (key && newTags != void 0) {
  2427. const emojiTags3 = await getEmojiTags()
  2428. const newTagsArray = sortTags(
  2429. filterTags(splitTags(newTags), TAG_VISITED),
  2430. emojiTags3
  2431. )
  2432. if (
  2433. tags.includes(TAG_VISITED) &&
  2434. !newTags.includes(TAG_VISITED)
  2435. ) {
  2436. removeVisited(key)
  2437. } else if (
  2438. !tags.includes(TAG_VISITED) &&
  2439. newTags.includes(TAG_VISITED)
  2440. ) {
  2441. addVisited(key)
  2442. }
  2443. await saveTags(key, newTagsArray, meta)
  2444. }
  2445. })
  2446. } else if (textTag) {
  2447. event.stopPropagation()
  2448. event.stopImmediatePropagation()
  2449. }
  2450. return
  2451. }
  2452. setTimeout(() => {
  2453. findElementToShowAllUtags(target)
  2454. }, 100)
  2455. },
  2456. true
  2457. )
  2458. addEventListener(
  2459. doc,
  2460. "keydown",
  2461. (event) => {
  2462. if (event.defaultPrevented) {
  2463. return
  2464. }
  2465. if (event.key === "Escape" && $(".utags_show_all")) {
  2466. hideAllUtagsInArea()
  2467. event.preventDefault()
  2468. }
  2469. },
  2470. true
  2471. )
  2472. addEventListener(
  2473. doc,
  2474. "mousedown",
  2475. (event) => {
  2476. const target = event.target
  2477. if (target == null ? void 0 : target.closest(".utags_ul")) {
  2478. event.preventDefault()
  2479. event.stopPropagation()
  2480. event.stopImmediatePropagation()
  2481. }
  2482. },
  2483. true
  2484. )
  2485. addEventListener(
  2486. doc,
  2487. "mouseup",
  2488. (event) => {
  2489. const target = event.target
  2490. if (target == null ? void 0 : target.closest(".utags_ul")) {
  2491. event.preventDefault()
  2492. event.stopPropagation()
  2493. event.stopImmediatePropagation()
  2494. }
  2495. },
  2496. true
  2497. )
  2498. }
  2499. function extendHistoryApi2() {
  2500. let url = location.href
  2501. setInterval(() => {
  2502. const url2 = location.href
  2503. if (url !== url2) {
  2504. url = url2
  2505. globalThis.dispatchEvent(new Event("locationchange"))
  2506. }
  2507. }, 100)
  2508. }
  2509. function bindWindowEvents() {
  2510. extendHistoryApi()
  2511. extendHistoryApi2()
  2512. addEventListener(globalThis, "locationchange", function () {
  2513. hideAllUtagsInArea()
  2514. })
  2515. }
  2516. var default_default =
  2517. ":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%}"
  2518. var default_default2 = /* @__PURE__ */ (() => {
  2519. return {
  2520. matches: /.*/,
  2521. matchedNodesSelectors: ["a[href]:not(.utags_text_tag)"],
  2522. validate(element) {
  2523. return true
  2524. },
  2525. excludeSelectors: [],
  2526. getCanonicalUrl: (url) =>
  2527. deleteUrlParameters(url, ["utm_campaign", "utm_source", "utm_medium"]),
  2528. getStyle: () => default_default,
  2529. }
  2530. })()
  2531. var v2ex_default =
  2532. ':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}'
  2533. var v2ex_default2 = (() => {
  2534. function getCanonicalUrl2(url) {
  2535. if (url.startsWith("https://links.pipecraft")) {
  2536. url = url.replace("https://links.pipecraft.net/", "https://")
  2537. }
  2538. if (url.includes("v2ex.com")) {
  2539. return url
  2540. .replace(/[?#].*/, "")
  2541. .replace(/(\w+\.)?v2ex.com/, "www.v2ex.com")
  2542. }
  2543. if (url.includes("v2ex.co")) {
  2544. return url
  2545. .replace(/[?#].*/, "")
  2546. .replace(/(\w+\.)?v2ex.co/, "www.v2ex.com")
  2547. }
  2548. return url
  2549. }
  2550. function cloneWithoutCitedReplies(element) {
  2551. const newElement = element.cloneNode(true)
  2552. for (const cell of $$(".cell", newElement)) {
  2553. cell.remove()
  2554. }
  2555. return newElement
  2556. }
  2557. return {
  2558. matches: /v2ex\.com|v2hot\.|v2ex\.co/,
  2559. preProcess() {
  2560. setVisitedAvailable(true)
  2561. setPrefix("https://www.v2ex.com/")
  2562. },
  2563. listNodesSelectors: [".box .cell", ".my-box .comment"],
  2564. conditionNodesSelectors: [
  2565. ".box .cell .topic-link",
  2566. ".item_hot_topic_title a",
  2567. '.box .cell .topic_info strong:first-of-type a[href*="/member/"]',
  2568. ".box .cell .topic_info .node",
  2569. '.box .cell strong a.dark[href*="/member/"]',
  2570. ".box .cell .ago a",
  2571. ".box .cell .fade.small a",
  2572. ".comment .username",
  2573. ".comment .ago",
  2574. ],
  2575. matchedNodesSelectors: [
  2576. 'a[href*="/t/"]',
  2577. 'a[href*="/member/"]',
  2578. 'a[href*="/go/"]',
  2579. 'a[href^="https://"]:not([href*="v2ex.com"])',
  2580. 'a[href^="http://"]:not([href*="v2ex.com"])',
  2581. ".box .cell .fr .tag",
  2582. ".box .inner .tag",
  2583. ],
  2584. excludeSelectors: [
  2585. ...default_default2.excludeSelectors,
  2586. ".site-nav a",
  2587. ".cell_tabs a",
  2588. ".tab-alt-container a",
  2589. "#SecondaryTabs a",
  2590. "a.page_normal,a.page_current",
  2591. "a.count_livid",
  2592. ".post-item a.post-content",
  2593. ],
  2594. addExtraMatchedNodes(matchedNodesSet) {
  2595. if (location.pathname.includes("/member/")) {
  2596. const profile = $(".content h1")
  2597. if (profile) {
  2598. const username = profile.textContent
  2599. if (username) {
  2600. const key = "https://www.v2ex.com/member/".concat(username)
  2601. const meta = { title: username, type: "user" }
  2602. profile.utags = { key, meta }
  2603. matchedNodesSet.add(profile)
  2604. }
  2605. }
  2606. }
  2607. if (location.pathname.includes("/t/")) {
  2608. const header = $(".header h1")
  2609. if (header) {
  2610. const key = getCanonicalUrl2(
  2611. "https://www.v2ex.com" + location.pathname
  2612. )
  2613. const title = $("h1").textContent
  2614. const meta = { title, type: "topic" }
  2615. header.utags = { key, meta }
  2616. matchedNodesSet.add(header)
  2617. addVisited(key)
  2618. markElementWhetherVisited(key, header)
  2619. }
  2620. const main2 = $("#Main") || $(".content")
  2621. const replyElements = $$(
  2622. '.box .cell[id^="r_"],.box .cell[id^="related_r_"]',
  2623. main2
  2624. )
  2625. for (const reply of replyElements) {
  2626. const replyId = reply.id.replace("related_", "")
  2627. const floorNoElement = $(".no", reply)
  2628. const replyContentElement = $(".reply_content", reply)
  2629. const agoElement = $(".ago,.fade.small", reply)
  2630. if (
  2631. replyId &&
  2632. floorNoElement &&
  2633. replyContentElement &&
  2634. agoElement
  2635. ) {
  2636. let newAgoElement = $("a", agoElement)
  2637. if (!newAgoElement) {
  2638. newAgoElement = createElement("a", {
  2639. textContent: agoElement.textContent,
  2640. href: "#" + replyId,
  2641. })
  2642. agoElement.textContent = ""
  2643. agoElement.append(newAgoElement)
  2644. }
  2645. const floorNo = parseInt10(floorNoElement.textContent, 1)
  2646. const pageNo = Math.floor((floorNo - 1) / 100) + 1
  2647. const key =
  2648. getCanonicalUrl2("https://www.v2ex.com" + location.pathname) +
  2649. "?p=" +
  2650. String(pageNo) +
  2651. "#" +
  2652. replyId
  2653. const title =
  2654. cloneWithoutCitedReplies(replyContentElement).textContent
  2655. const meta = { title, type: "reply" }
  2656. newAgoElement.utags = { key, meta }
  2657. matchedNodesSet.add(newAgoElement)
  2658. }
  2659. }
  2660. }
  2661. if (location.pathname.includes("/go/")) {
  2662. const header = $(".title .node-breadcrumb")
  2663. if (header) {
  2664. const key = getCanonicalUrl2(
  2665. "https://www.v2ex.com" + location.pathname
  2666. )
  2667. const title = header.textContent.replaceAll(/\s+/g, " ").trim()
  2668. const meta = { title, type: "node" }
  2669. header.utags = { key, meta }
  2670. matchedNodesSet.add(header)
  2671. }
  2672. }
  2673. if (location.pathname.includes("/tag/")) {
  2674. const header = $(".box .header > span")
  2675. if (header) {
  2676. const key = getCanonicalUrl2(
  2677. "https://www.v2ex.com" + location.pathname
  2678. )
  2679. const title = header.textContent.replaceAll(/\s+/g, " ").trim()
  2680. const meta = { title, type: "tag" }
  2681. header.utags = { key, meta }
  2682. header.dataset.utags_flag = "tag_page"
  2683. matchedNodesSet.add(header)
  2684. }
  2685. }
  2686. },
  2687. getStyle: () => v2ex_default,
  2688. getCanonicalUrl: getCanonicalUrl2,
  2689. postProcess() {
  2690. for (const element of $$('a[href*="/t/"]')) {
  2691. const key = getCanonicalUrl2(element.href)
  2692. markElementWhetherVisited(key, element)
  2693. }
  2694. },
  2695. }
  2696. })()
  2697. var greasyfork_org_default =
  2698. ":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:hsla(0,0%,100%,.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:hsla(0,0%,100%,.8666666667) !important}"
  2699. var greasyfork_org_default2 = (() => {
  2700. function getScriptUrl(url) {
  2701. return getCanonicalUrl2(url.replace(/(scripts\/\d+)(.*)/, "$1"))
  2702. }
  2703. function getCanonicalUrl2(url) {
  2704. if (/(greasyfork|sleazyfork)\.org/.test(url)) {
  2705. url = url.replace(
  2706. /((greasyfork|sleazyfork)\.org\/)(\w{2}(-\w{2})?)(\/|$)/,
  2707. "$1"
  2708. )
  2709. if (url.includes("/scripts/")) {
  2710. return url.replace(/(scripts\/\d+)([^/]*)/, "$1")
  2711. }
  2712. if (url.includes("/users/")) {
  2713. return url.replace(/(users\/\d+)(.*)/, "$1")
  2714. }
  2715. }
  2716. return url
  2717. }
  2718. return {
  2719. matches: /(greasyfork|sleazyfork)\.org/,
  2720. listNodesSelectors: [".script-list > li", ".discussion-list-container"],
  2721. conditionNodesSelectors: [
  2722. ".script-list li .script-link",
  2723. ".script-list li .script-list-author a",
  2724. ".discussion-list-container .script-link",
  2725. ".discussion-list-container .discussion-title",
  2726. ".discussion-list-container .discussion-meta-item:nth-child(2) > a",
  2727. ],
  2728. excludeSelectors: [
  2729. ...default_default2.excludeSelectors,
  2730. ".sidebar",
  2731. ".pagination",
  2732. ".sign-out-link,.sign-in-link",
  2733. ".with-submenu",
  2734. "#script-links.tabs",
  2735. "#install-area",
  2736. ".history_versions .version-number",
  2737. 'a[href*="show_all_versions"]',
  2738. 'a[href*="/reports/new"]',
  2739. 'a[href*="/conversations/new"]',
  2740. 'a[href*="/discussions/mark_all_read"]',
  2741. 'a[href*="/discussions/new"]',
  2742. "div.sidebarred-main-content > p:nth-child(3) > a",
  2743. ],
  2744. addExtraMatchedNodes(matchedNodesSet) {
  2745. if (location.pathname.includes("/scripts/")) {
  2746. const element = $("#script-info header h2")
  2747. if (element) {
  2748. const title = element.textContent
  2749. if (title) {
  2750. const key = getScriptUrl(location.href)
  2751. const meta = { title }
  2752. element.utags = { key, meta }
  2753. matchedNodesSet.add(element)
  2754. }
  2755. }
  2756. } else if (location.pathname.includes("/users/")) {
  2757. const element = $("#about-user h2")
  2758. if (element) {
  2759. const title = element.textContent
  2760. if (title) {
  2761. const key = getCanonicalUrl2(location.href)
  2762. const meta = { title }
  2763. element.utags = { key, meta }
  2764. matchedNodesSet.add(element)
  2765. }
  2766. }
  2767. }
  2768. },
  2769. getCanonicalUrl: getCanonicalUrl2,
  2770. getStyle: () => greasyfork_org_default,
  2771. }
  2772. })()
  2773. var news_ycombinator_com_default = (() => {
  2774. function cloneComment(element) {
  2775. const newElement = element.cloneNode(true)
  2776. for (const node of $$(".reply", newElement)) {
  2777. node.remove()
  2778. }
  2779. return newElement
  2780. }
  2781. return {
  2782. matches: /news\.ycombinator\.com/,
  2783. listNodesSelectors: [".script-list li", ".discussion-list-container"],
  2784. conditionNodesSelectors: [],
  2785. excludeSelectors: [
  2786. ...default_default2.excludeSelectors,
  2787. ".pagetop",
  2788. ".morelink",
  2789. ".hnpast",
  2790. ".clicky",
  2791. ".navs > a",
  2792. 'a[href^="login"]',
  2793. 'a[href^="logout"]',
  2794. 'a[href^="forgot"]',
  2795. 'a[href^="vote"]',
  2796. 'a[href^="submit"]',
  2797. 'a[href^="hide"]',
  2798. 'a[href^="fave"]',
  2799. 'a[href^="reply"]',
  2800. 'a[href^="context"]',
  2801. 'a[href^="newcomments"]',
  2802. 'a[href^="#"]',
  2803. '.subline > a[href^="item"]',
  2804. ],
  2805. addExtraMatchedNodes(matchedNodesSet) {
  2806. if (location.pathname === "/item") {
  2807. const comments = $$(".comment-tree .comtr[id]")
  2808. for (const comment of comments) {
  2809. const commentText = $(".commtext", comment)
  2810. const target = $(".age a", comment)
  2811. if (commentText && target) {
  2812. const key = target.href
  2813. const title = cloneComment(commentText).textContent
  2814. if (key && title) {
  2815. const meta = { title, type: "comment" }
  2816. target.utags = { key, meta }
  2817. matchedNodesSet.add(target)
  2818. }
  2819. }
  2820. }
  2821. const fatitem = $(".fatitem")
  2822. if (fatitem) {
  2823. const titleElement = $(".titleline a", fatitem)
  2824. const commentText = titleElement || $(".commtext", fatitem)
  2825. const type = titleElement ? "topic" : "comment"
  2826. const target = $(".age a", fatitem)
  2827. if (commentText && target) {
  2828. const key = target.href
  2829. const title = cloneComment(commentText).textContent
  2830. if (key && title) {
  2831. const meta = { title, type }
  2832. target.utags = { key, meta }
  2833. matchedNodesSet.add(target)
  2834. }
  2835. }
  2836. }
  2837. } else if (location.pathname === "/newcomments") {
  2838. const comments = $$(".athing[id]")
  2839. for (const comment of comments) {
  2840. const commentText = $(".commtext", comment)
  2841. const target = $(".age a", comment)
  2842. if (commentText && target) {
  2843. const key = target.href
  2844. const title = cloneComment(commentText).textContent
  2845. if (key && title) {
  2846. const meta = { title, type: "comment" }
  2847. target.utags = { key, meta }
  2848. matchedNodesSet.add(target)
  2849. }
  2850. }
  2851. }
  2852. } else {
  2853. const topics = $$(".athing[id]")
  2854. for (const topic of topics) {
  2855. const titleElement = $(".titleline a", topic)
  2856. const subtext = topic.nextElementSibling
  2857. if (subtext) {
  2858. const target = $(".age a", subtext)
  2859. if (titleElement && target) {
  2860. const key = target.href
  2861. const title = titleElement.textContent
  2862. if (key && title) {
  2863. const meta = { title, type: "topic" }
  2864. target.utags = { key, meta }
  2865. matchedNodesSet.add(target)
  2866. }
  2867. }
  2868. }
  2869. }
  2870. }
  2871. },
  2872. }
  2873. })()
  2874. var lobste_rs_default = (() => {
  2875. return {
  2876. matches:
  2877. /lobste\.rs|dto\.pipecraft\.net|tilde\.news|journalduhacker\.net/,
  2878. listNodesSelectors: [],
  2879. conditionNodesSelectors: [],
  2880. excludeSelectors: [
  2881. ...default_default2.excludeSelectors,
  2882. "#nav",
  2883. "#header",
  2884. "#subnav",
  2885. ".mobile_comments",
  2886. ".description_present",
  2887. ".morelink",
  2888. ".user_tree",
  2889. ".dropdown_parent",
  2890. 'a[href^="/login"]',
  2891. 'a[href^="/logout"]',
  2892. 'a[href^="/u#"]',
  2893. 'a[href$="/save"]',
  2894. 'a[href$="/hide"]',
  2895. 'a[href$="/suggest"]',
  2896. ],
  2897. }
  2898. })()
  2899. var github_com_default =
  2900. ':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)}'
  2901. var github_com_default2 = (() => {
  2902. const noneUsers = /* @__PURE__ */ new Set([
  2903. "about",
  2904. "pricing",
  2905. "security",
  2906. "login",
  2907. "logout",
  2908. "signup",
  2909. "explore",
  2910. "topics",
  2911. "trending",
  2912. "collections",
  2913. "events",
  2914. "sponsors",
  2915. "features",
  2916. "enterprise",
  2917. "team",
  2918. "customer-stories",
  2919. "readme",
  2920. "premium-support",
  2921. "sitemap",
  2922. "git-guides",
  2923. "open-source",
  2924. "marketplace",
  2925. "codespaces",
  2926. "issues",
  2927. "pulls",
  2928. "discussions",
  2929. "dashboard",
  2930. "account",
  2931. "new",
  2932. "notifications",
  2933. "settings",
  2934. "feedback",
  2935. "organizations",
  2936. "github-copilot",
  2937. "search",
  2938. ])
  2939. const prefix3 = "https://github.com/"
  2940. function getUserProfileUrl(href) {
  2941. if (href.startsWith(prefix3)) {
  2942. const href2 = href.slice(19)
  2943. let username = ""
  2944. if (/^[\w-]+$/.test(href2)) {
  2945. username = /^([\w-]+)$/.exec(href2)[1]
  2946. }
  2947. if (/(author%3A|author=)[\w-]+/.test(href2)) {
  2948. username = /(author%3A|author=)([\w-]+)/.exec(href2)[2]
  2949. }
  2950. if (username && !noneUsers.has(username)) {
  2951. return prefix3 + username
  2952. }
  2953. }
  2954. return void 0
  2955. }
  2956. function getRepoUrl(href) {
  2957. if (href.startsWith(prefix3)) {
  2958. const href2 = href.slice(19)
  2959. if (/^[\w-]+\/[\w-.]+(\?.*)?$/.test(href2)) {
  2960. const username = /^([\w-]+)/.exec(href2)[1]
  2961. if (username && !noneUsers.has(username)) {
  2962. return prefix3 + href2.replace(/(^[\w-]+\/[\w-.]+).*/, "$1")
  2963. }
  2964. }
  2965. }
  2966. return void 0
  2967. }
  2968. function getTopicsUrl(href) {
  2969. if (href.startsWith(prefix3)) {
  2970. const href2 = href.slice(19)
  2971. if (/^topics\/[\w-.]+(\?.*)?$/.test(href2)) {
  2972. return prefix3 + href2.replace(/(^topics\/[\w-.]+).*/, "$1")
  2973. }
  2974. }
  2975. return void 0
  2976. }
  2977. function getIssuesUrl(href) {
  2978. if (href.startsWith(prefix3)) {
  2979. const href2 = href.slice(19)
  2980. if (
  2981. /^[\w-]+\/[\w-.]+\/(issues|pull|discussions)\/\d+(\?.*)?$/.test(href2)
  2982. ) {
  2983. const username = /^([\w-]+)/.exec(href2)[1]
  2984. if (username && !noneUsers.has(username)) {
  2985. return (
  2986. prefix3 +
  2987. href2.replace(
  2988. /(^[\w-]+\/[\w-.]+\/(issues|pull|discussions)\/\d+).*/,
  2989. "$1"
  2990. )
  2991. )
  2992. }
  2993. }
  2994. }
  2995. return void 0
  2996. }
  2997. return {
  2998. matches: /github\.com/,
  2999. listNodesSelectors: [],
  3000. conditionNodesSelectors: [],
  3001. validate(element) {
  3002. const href = element.href
  3003. if (href.startsWith(prefix3)) {
  3004. if (/since|until/.test(href)) {
  3005. return false
  3006. }
  3007. let key = getUserProfileUrl(href)
  3008. if (key) {
  3009. const username = /^https:\/\/github\.com\/([\w-]+)$/.exec(key)[1]
  3010. const title = username
  3011. const meta = { title, type: "user" }
  3012. element.utags = { key, meta }
  3013. return true
  3014. }
  3015. key = getRepoUrl(href)
  3016. if (key) {
  3017. const title = key.replace(prefix3, "")
  3018. const meta = { title, type: "repo" }
  3019. element.utags = { key, meta }
  3020. return true
  3021. }
  3022. key = getTopicsUrl(href)
  3023. if (key) {
  3024. const text = element.textContent.trim()
  3025. if (text === "#") {
  3026. return false
  3027. }
  3028. const title = "#" + key.replace(prefix3 + "topics/", "")
  3029. const meta = { title, type: "topic" }
  3030. element.utags = { key, meta }
  3031. return true
  3032. }
  3033. key = getIssuesUrl(href)
  3034. if (key) {
  3035. const meta = { type: "issue" }
  3036. element.utags = { key, meta }
  3037. return true
  3038. }
  3039. return false
  3040. }
  3041. return true
  3042. },
  3043. excludeSelectors: [
  3044. ...default_default2.excludeSelectors,
  3045. 'section[aria-label~="User"] .Link--secondary',
  3046. ".Popover-message .Link--secondary",
  3047. ".IssueLabel",
  3048. ".subnav-links",
  3049. ".btn",
  3050. ".filter-item",
  3051. ".js-github-dev-shortcut",
  3052. ".js-github-dev-new-tab-shortcut",
  3053. ".js-skip-to-content",
  3054. ],
  3055. validMediaSelectors: ["svg.octicon-repo"],
  3056. getStyle: () => github_com_default,
  3057. }
  3058. })()
  3059. var reddit_com_default =
  3060. '#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}'
  3061. var reddit_com_default2 = (() => {
  3062. const prefix3 = "https://www.reddit.com/"
  3063. function getCanonicalUrl2(url) {
  3064. if (url.startsWith(prefix3)) {
  3065. let href2 = getUserProfileUrl(url, true)
  3066. if (href2) {
  3067. return href2
  3068. }
  3069. href2 = getCommunityUrl(url, true)
  3070. if (href2) {
  3071. return href2
  3072. }
  3073. href2 = getCommentsUrl(url, true)
  3074. if (href2) {
  3075. return href2
  3076. }
  3077. }
  3078. return url
  3079. }
  3080. function getUserProfileUrl(url, exact = false) {
  3081. if (url.startsWith(prefix3)) {
  3082. const href2 = url.slice(prefix3.length)
  3083. if (exact) {
  3084. if (/^(user|u)\/[\w-]+\/?([?#].*)?$/.test(href2)) {
  3085. return (
  3086. prefix3 +
  3087. "user/" +
  3088. href2.replace(/^(user|u)\/([\w-]+).*/, "$2") +
  3089. "/"
  3090. )
  3091. }
  3092. } else if (/^(user|u)\/[\w-]+/.test(href2)) {
  3093. return (
  3094. prefix3 +
  3095. "user/" +
  3096. href2.replace(/^(user|u)\/([\w-]+).*/, "$2") +
  3097. "/"
  3098. )
  3099. }
  3100. }
  3101. return void 0
  3102. }
  3103. function getCommunityUrl(url, exact = false) {
  3104. if (url.startsWith(prefix3)) {
  3105. const href2 = url.slice(prefix3.length)
  3106. if (exact) {
  3107. if (/^r\/\w+\/?(#.*)?$/.test(href2)) {
  3108. return prefix3 + href2.replace(/^(r\/\w+).*/, "$1") + "/"
  3109. }
  3110. } else if (/^r\/\w+/.test(href2)) {
  3111. return prefix3 + href2.replace(/^(r\/\w+).*/, "$1") + "/"
  3112. }
  3113. }
  3114. return void 0
  3115. }
  3116. function getCommentsUrl(url, exact = false) {
  3117. if (url.startsWith(prefix3)) {
  3118. const href2 = url.slice(prefix3.length)
  3119. if (exact) {
  3120. if (/^(r\/\w+\/comments\/\w+(\/([^/]*\/?)?)?)$/.test(href2)) {
  3121. return (
  3122. prefix3 +
  3123. href2.replace(/^(r\/\w+\/comments\/\w+(\/([^/]*)?)?).*/, "$1") +
  3124. "/"
  3125. )
  3126. }
  3127. } else if (/^(r\/\w+\/comments\/\w+(\/([^/]*)?)?).*/.test(href2)) {
  3128. return (
  3129. prefix3 +
  3130. href2.replace(/^(r\/\w+\/comments\/\w+(\/([^/]*)?)?).*/, "$1") +
  3131. "/"
  3132. )
  3133. }
  3134. }
  3135. return void 0
  3136. }
  3137. return {
  3138. matches: /reddit\.com/,
  3139. listNodesSelectors: [
  3140. "shreddit-feed article",
  3141. "shreddit-feed shreddit-ad-post",
  3142. "shreddit-comment",
  3143. ],
  3144. conditionNodesSelectors: [
  3145. 'shreddit-feed article a[data-testid="subreddit-name"]',
  3146. 'shreddit-feed article a[slot="title"]',
  3147. 'shreddit-feed article [slot="authorName"] a',
  3148. "shreddit-feed shreddit-ad-post a",
  3149. "shreddit-comment faceplate-hovercard a",
  3150. ],
  3151. validate(element) {
  3152. const href = element.href
  3153. if (!href.startsWith(prefix3)) {
  3154. return true
  3155. }
  3156. if ($("time,faceplate-number", element)) {
  3157. return false
  3158. }
  3159. let key = getUserProfileUrl(href, true)
  3160. if (key) {
  3161. const title = element.textContent.trim()
  3162. if (!title) {
  3163. return false
  3164. }
  3165. const meta = { type: "user", title }
  3166. element.utags = { key, meta }
  3167. element.dataset.utags = element.dataset.utags || ""
  3168. return true
  3169. }
  3170. key = getCommunityUrl(href, true)
  3171. if (key) {
  3172. const title = element.textContent.trim()
  3173. if (!title) {
  3174. return false
  3175. }
  3176. const meta = { type: "community", title }
  3177. element.utags = { key, meta }
  3178. element.dataset.utags = element.dataset.utags || ""
  3179. return true
  3180. }
  3181. key = getCommentsUrl(href, true)
  3182. if (key) {
  3183. const title = element.textContent.trim()
  3184. if (!title) {
  3185. return false
  3186. }
  3187. const meta = { type: "comments", title }
  3188. element.utags = { key, meta }
  3189. element.dataset.utags = element.dataset.utags || ""
  3190. return true
  3191. }
  3192. return true
  3193. },
  3194. excludeSelectors: [
  3195. ...default_default2.excludeSelectors,
  3196. 'a[data-testid="comment_author_icon"]',
  3197. "#shreddit-skip-link",
  3198. 'a[slot="text-body"]',
  3199. 'a[slot="full-post-link"]',
  3200. '[slot="post-media-container"] a.inset-0',
  3201. '[bundlename="shreddit_sort_dropdown"]',
  3202. '[slot="tabs"]',
  3203. ],
  3204. addExtraMatchedNodes(matchedNodesSet) {
  3205. let element = $('[data-testid="profile-main"] .w-full p')
  3206. if (element) {
  3207. const title = element.textContent.trim()
  3208. const key = getUserProfileUrl(location.href)
  3209. if (title && key) {
  3210. const meta = { title, type: "user" }
  3211. element.utags = { key, meta }
  3212. matchedNodesSet.add(element)
  3213. }
  3214. }
  3215. element = $(".w-full h1")
  3216. if (element) {
  3217. const title = element.textContent.trim()
  3218. const key = getCommunityUrl(location.href)
  3219. if (title && key) {
  3220. const meta = { title, type: "community" }
  3221. element.utags = { key, meta }
  3222. matchedNodesSet.add(element)
  3223. }
  3224. }
  3225. element = $('h1[slot="title"]')
  3226. if (element) {
  3227. const title = element.textContent.trim()
  3228. const key = getCommentsUrl(location.href, true)
  3229. if (title && key) {
  3230. const meta = { title, type: "comments" }
  3231. element.utags = { key, meta }
  3232. matchedNodesSet.add(element)
  3233. }
  3234. }
  3235. },
  3236. getStyle: () => reddit_com_default,
  3237. postProcess() {
  3238. setTimeout(() => {
  3239. for (const element of $$(
  3240. '[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,"]'
  3241. )) {
  3242. element.setAttribute("collapsed", "")
  3243. }
  3244. }, 1e3)
  3245. },
  3246. getCanonicalUrl: getCanonicalUrl2,
  3247. }
  3248. })()
  3249. var twitter_com_default =
  3250. ":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}"
  3251. var twitter_com_default2 = /* @__PURE__ */ (() => {
  3252. const prefix3 = "https://x.com/"
  3253. const prefix22 = "https://twitter.com/"
  3254. return {
  3255. matches: /x\.com|twitter\.com/,
  3256. listNodesSelectors: ['[data-testid="cellInnerDiv"]'],
  3257. conditionNodesSelectors: [
  3258. '[data-testid="cellInnerDiv"] [data-testid="User-Name"] a',
  3259. ],
  3260. validate(element) {
  3261. const href = element.href
  3262. if (href.startsWith(prefix3) || href.startsWith(prefix22)) {
  3263. const href2 = href.startsWith(prefix22)
  3264. ? href.slice(20)
  3265. : href.slice(14)
  3266. if (/^\w+$/.test(href2)) {
  3267. if (
  3268. /^(home|explore|notifications|messages|tos|privacy)$/.test(href2)
  3269. ) {
  3270. return false
  3271. }
  3272. const textContent = element.textContent || ""
  3273. if (!textContent.startsWith("@")) {
  3274. return false
  3275. }
  3276. const parent = element.parentElement
  3277. setStyle(parent, { zIndex: "1" })
  3278. const meta = { type: "user" }
  3279. element.utags = { meta }
  3280. return true
  3281. }
  3282. }
  3283. return false
  3284. },
  3285. addExtraMatchedNodes(matchedNodesSet) {
  3286. const elements = $$('[data-testid="UserName"] span')
  3287. for (const element of elements) {
  3288. const title = element.textContent.trim()
  3289. if (!title || !title.startsWith("@")) {
  3290. continue
  3291. }
  3292. const key = prefix3 + title.slice(1)
  3293. const meta = { title, type: "user" }
  3294. element.utags = { key, meta }
  3295. matchedNodesSet.add(element)
  3296. }
  3297. },
  3298. getStyle: () => twitter_com_default,
  3299. }
  3300. })()
  3301. var mp_weixin_qq_com_default = /* @__PURE__ */ (() => {
  3302. function getCanonicalUrl2(url) {
  3303. if (url.startsWith("http://mp.weixin.qq.com")) {
  3304. url = url.replace(/^http:/, "https:")
  3305. }
  3306. if (url.startsWith("https://mp.weixin.qq.com/s/")) {
  3307. url = url.replace(/(\/s\/[\w-]+).*/, "$1")
  3308. }
  3309. if (url.startsWith("https://mp.weixin.qq.com/") && url.includes("#")) {
  3310. url = url.replace(/#.*/, "")
  3311. }
  3312. return url
  3313. }
  3314. return {
  3315. matches: /mp\.weixin\.qq\.com/,
  3316. addExtraMatchedNodes(matchedNodesSet) {
  3317. const element = $("h1.rich_media_title")
  3318. if (element) {
  3319. const title = element.textContent.trim()
  3320. if (title) {
  3321. const key = getCanonicalUrl2(location.href)
  3322. const meta = { title }
  3323. element.utags = { key, meta }
  3324. matchedNodesSet.add(element)
  3325. }
  3326. }
  3327. },
  3328. getCanonicalUrl: getCanonicalUrl2,
  3329. }
  3330. })()
  3331. var instagram_com_default =
  3332. ":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}"
  3333. var instagram_com_default2 = (() => {
  3334. return {
  3335. matches: /instagram\.com/,
  3336. validate(element) {
  3337. const href = element.href
  3338. if (href.startsWith("https://www.instagram.com/")) {
  3339. const href2 = href.slice(26)
  3340. if (/^[\w.]+\/$/.test(href2)) {
  3341. if (/^(explore|reels)\/$/.test(href2)) {
  3342. return false
  3343. }
  3344. if ($("div span", element)) {
  3345. element.dataset.utags_node_type = "notag_relative"
  3346. }
  3347. const meta = { type: "user" }
  3348. element.utags = { meta }
  3349. return true
  3350. }
  3351. }
  3352. return false
  3353. },
  3354. excludeSelectors: [...default_default2.excludeSelectors],
  3355. getStyle: () => instagram_com_default,
  3356. }
  3357. })()
  3358. var threads_net_default =
  3359. ':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)}'
  3360. var threads_net_default2 = (() => {
  3361. function getUserProfileUrl(url) {
  3362. if (url.startsWith("https://www.threads.net/")) {
  3363. const href2 = url.slice(24)
  3364. if (/^@[\w.]+/.test(href2)) {
  3365. return (
  3366. "https://www.threads.net/" +
  3367. href2.replace(/(^@[\w.]+).*/, "$1").toLowerCase()
  3368. )
  3369. }
  3370. }
  3371. return void 0
  3372. }
  3373. return {
  3374. matches: /threads\.net/,
  3375. validate(element) {
  3376. const href = element.href
  3377. if (href.startsWith("https://www.threads.net/")) {
  3378. const href2 = href.slice(24)
  3379. if (/^@[\w.]+$/.test(href2)) {
  3380. const meta = { type: "user" }
  3381. element.utags = { meta }
  3382. return true
  3383. }
  3384. }
  3385. return false
  3386. },
  3387. excludeSelectors: [
  3388. ...default_default2.excludeSelectors,
  3389. '[role="tablist"]',
  3390. ],
  3391. addExtraMatchedNodes(matchedNodesSet) {
  3392. const element = $("h1+div>div>span,h2+div>div>span")
  3393. if (element) {
  3394. const title = element.textContent.trim()
  3395. const key = getUserProfileUrl(location.href)
  3396. if (title && key && key === "https://www.threads.net/@" + title) {
  3397. const meta = { title, type: "user" }
  3398. element.utags = { key, meta }
  3399. matchedNodesSet.add(element)
  3400. }
  3401. }
  3402. },
  3403. getStyle: () => threads_net_default,
  3404. }
  3405. })()
  3406. var facebook_com_default =
  3407. ":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}"
  3408. var facebook_com_default2 = (() => {
  3409. const prefix3 = location.origin + "/"
  3410. function getUserProfileUrl(href, exact = false) {
  3411. if (href.startsWith(prefix3)) {
  3412. const href2 = href.slice(prefix3.length).toLowerCase()
  3413. if (href2.startsWith("profile.php")) {
  3414. const parameters = getUrlParameters(href, ["id", "sk"])
  3415. if (parameters.id && !parameters.sk) {
  3416. return "https://www.facebook.com/profile.php?id=" + parameters.id
  3417. }
  3418. } else if (/^\d+\/?([?#].*)?$/.test(href2)) {
  3419. return (
  3420. "https://www.facebook.com/profile.php?id=" +
  3421. href2.replace(/^(\d+).*/, "$1")
  3422. )
  3423. } else if (/^messages\/t\/\d+\/?([?#].*)?$/.test(href2)) {
  3424. return (
  3425. "https://www.facebook.com/profile.php?id=" +
  3426. href2.replace(/^messages\/t\/(\d+).*/, "$1")
  3427. )
  3428. } else if (
  3429. href2.startsWith("friends/requests/?profile_id=") ||
  3430. href2.startsWith("friends/suggestions/?profile_id=")
  3431. ) {
  3432. const parameters = getUrlParameters(href, ["profile_id"])
  3433. if (parameters.profile_id) {
  3434. return (
  3435. "https://www.facebook.com/profile.php?id=" + parameters.profile_id
  3436. )
  3437. }
  3438. } else if (
  3439. ((exact && /^[\w.]+([?#].*)?$/.test(href2)) ||
  3440. (!exact && /^[\w.]+/.test(href2))) &&
  3441. !/^(policies|events|ads|business|privacy|help|friends|messages|profile\.php|permalink\.php|photo\.php|\w+\.php)\b/.test(
  3442. href2
  3443. )
  3444. ) {
  3445. return (
  3446. "https://www.facebook.com/" + href2.replace(/(^[\w.]+).*/, "$1")
  3447. )
  3448. }
  3449. }
  3450. return void 0
  3451. }
  3452. return {
  3453. matches: /^(www|m)\.facebook\.com$/,
  3454. validate(element) {
  3455. const href = element.href
  3456. if (
  3457. !href.startsWith("https://www.facebook.com/") &&
  3458. !href.startsWith("https://m.facebook.com/") &&
  3459. !href.startsWith("https://l.facebook.com/")
  3460. ) {
  3461. return true
  3462. }
  3463. const key = getUserProfileUrl(href, true)
  3464. if (key) {
  3465. const title = element.textContent.trim()
  3466. if (!title) {
  3467. return false
  3468. }
  3469. if ($("svg,img", element)) {
  3470. element.dataset.utags_flag = "username_with_avatar"
  3471. }
  3472. const meta = { type: "user", title }
  3473. element.utags = { key, meta }
  3474. element.dataset.utags = element.dataset.utags || ""
  3475. return true
  3476. }
  3477. return false
  3478. },
  3479. excludeSelectors: [
  3480. ...default_default2.excludeSelectors,
  3481. 'div[data-pagelet="ProfileTabs"]',
  3482. ],
  3483. addExtraMatchedNodes(matchedNodesSet) {
  3484. const element = getFirstHeadElement('div[role="main"] h1')
  3485. if (element) {
  3486. const title = element.textContent.trim()
  3487. const key = getUserProfileUrl(location.href)
  3488. if (title && key) {
  3489. const meta = { title, type: "user" }
  3490. element.utags = { key, meta }
  3491. matchedNodesSet.add(element)
  3492. }
  3493. }
  3494. },
  3495. getStyle: () => facebook_com_default,
  3496. }
  3497. })()
  3498. var youtube_com_default =
  3499. ":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}"
  3500. var youtube_com_default2 = (() => {
  3501. const prefix3 = "https://www.youtube.com/"
  3502. const prefix22 = "https://m.youtube.com/"
  3503. function getUserProfileUrl(href) {
  3504. if (href.startsWith(prefix3) || href.startsWith(prefix22)) {
  3505. const href2 = href.startsWith(prefix22)
  3506. ? href.slice(22)
  3507. : href.slice(24)
  3508. if (/^@[\w-]+/.test(href2)) {
  3509. return prefix3 + href2.replace(/(^@[\w-]+).*/, "$1")
  3510. }
  3511. if (/^channel\/[\w-]+/.test(href2)) {
  3512. return prefix3 + href2.replace(/(^channel\/[\w-]+).*/, "$1")
  3513. }
  3514. }
  3515. return void 0
  3516. }
  3517. function getVideoUrl(href) {
  3518. if (href.startsWith(prefix3) || href.startsWith(prefix22)) {
  3519. const href2 = href.startsWith(prefix22)
  3520. ? href.slice(22)
  3521. : href.slice(24)
  3522. if (href2.includes("&lc=")) {
  3523. return void 0
  3524. }
  3525. if (/^watch\?v=[\w-]+/.test(href2)) {
  3526. return prefix3 + href2.replace(/(watch\?v=[\w-]+).*/, "$1")
  3527. }
  3528. if (/^shorts\/[\w-]+/.test(href2)) {
  3529. return prefix3 + href2.replace(/(^shorts\/[\w-]+).*/, "$1")
  3530. }
  3531. }
  3532. return void 0
  3533. }
  3534. return {
  3535. matches: /youtube\.com/,
  3536. validate(element) {
  3537. const hrefAttr = getAttribute(element, "href")
  3538. if (!hrefAttr || hrefAttr === "null" || hrefAttr === "#") {
  3539. return false
  3540. }
  3541. const href = element.href
  3542. if (href.startsWith(prefix3) || href.startsWith(prefix22)) {
  3543. const pathname = element.pathname
  3544. if (/^\/@[\w-]+$/.test(pathname)) {
  3545. const key2 = prefix3 + pathname.slice(1)
  3546. const meta = { type: "user" }
  3547. element.utags = { key: key2, meta }
  3548. return true
  3549. }
  3550. if (/^\/channel\/[\w-]+$/.test(pathname)) {
  3551. const key2 = prefix3 + pathname.slice(1)
  3552. const meta = { type: "channel" }
  3553. element.utags = { key: key2, meta }
  3554. return true
  3555. }
  3556. const key = getVideoUrl(href)
  3557. if (key) {
  3558. let title
  3559. const titleElement = $("#video-title", element)
  3560. if (titleElement) {
  3561. title = titleElement.textContent
  3562. }
  3563. const meta = title ? { title, type: "video" } : { type: "video" }
  3564. element.utags = { key, meta }
  3565. return true
  3566. }
  3567. }
  3568. return false
  3569. },
  3570. excludeSelectors: [...default_default2.excludeSelectors],
  3571. addExtraMatchedNodes(matchedNodesSet) {
  3572. let key = getUserProfileUrl(location.href)
  3573. if (key) {
  3574. const element = $(
  3575. "#inner-header-container #container.ytd-channel-name #text"
  3576. )
  3577. if (element) {
  3578. const title = element.textContent.trim()
  3579. if (title) {
  3580. const meta = { title }
  3581. element.utags = { key, meta }
  3582. matchedNodesSet.add(element)
  3583. }
  3584. }
  3585. }
  3586. key = getVideoUrl(location.href)
  3587. if (key) {
  3588. const element = $(
  3589. "#title h1.ytd-watch-metadata,ytd-reel-video-renderer[is-active] h2.title"
  3590. )
  3591. if (element) {
  3592. const title = element.textContent.trim()
  3593. if (title) {
  3594. const meta = { title, type: "video" }
  3595. element.utags = { key, meta }
  3596. matchedNodesSet.add(element)
  3597. }
  3598. }
  3599. }
  3600. },
  3601. getStyle: () => youtube_com_default,
  3602. }
  3603. })()
  3604. var bilibili_com_default =
  3605. ':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:hsla(0,0%,100%,.8666666667) !important}'
  3606. var bilibili_com_default2 = /* @__PURE__ */ (() => {
  3607. const prefix3 = "https://www.bilibili.com/"
  3608. const prefix22 = "https://space.bilibili.com/"
  3609. const prefix32 = "https://m.bilibili.com/"
  3610. function getUserProfileUrl(href) {
  3611. if (href.startsWith(prefix22)) {
  3612. const href2 = href.slice(27)
  3613. if (/^\d+/.test(href2)) {
  3614. return prefix22 + href2.replace(/(^\d+).*/, "$1")
  3615. }
  3616. }
  3617. if (href.startsWith(prefix32 + "space/")) {
  3618. const href2 = href.slice(29)
  3619. if (/^\d+/.test(href2)) {
  3620. return prefix22 + href2.replace(/(^\d+).*/, "$1")
  3621. }
  3622. }
  3623. return void 0
  3624. }
  3625. function getVideoUrl(href) {
  3626. if (
  3627. href.startsWith(prefix3 + "video/") ||
  3628. href.startsWith(prefix32 + "video/")
  3629. ) {
  3630. const href2 = href.startsWith(prefix32)
  3631. ? href.slice(23)
  3632. : href.slice(25)
  3633. if (/^video\/\w+/.test(href2)) {
  3634. return prefix3 + href2.replace(/^(video\/\w+).*/, "$1")
  3635. }
  3636. }
  3637. return void 0
  3638. }
  3639. return {
  3640. matches: /bilibili\.com|biligame\.com/,
  3641. excludeSelectors: ["*"],
  3642. addExtraMatchedNodes(matchedNodesSet) {
  3643. if (location.href.startsWith(prefix3 + "video/")) {
  3644. if ($(".bpx-state-loading")) {
  3645. return
  3646. }
  3647. const img = $(".bpx-player-follow-face")
  3648. const img2 = $("img.video-capture-img")
  3649. if (
  3650. !(img == null ? void 0 : img.src) ||
  3651. !(img2 == null ? void 0 : img2.src)
  3652. ) {
  3653. return
  3654. }
  3655. }
  3656. const elements = $$(
  3657. ".user-name[data-user-id],.sub-user-name[data-user-id],.jump-link.user[data-user-id]"
  3658. )
  3659. for (const element2 of elements) {
  3660. const userId = element2.dataset.userId
  3661. if (!userId) {
  3662. return false
  3663. }
  3664. const title = element2.textContent.trim()
  3665. const key = prefix22 + userId
  3666. const meta = { title, type: "user" }
  3667. element2.utags = { key, meta }
  3668. element2.dataset.utags_node_type = "link"
  3669. matchedNodesSet.add(element2)
  3670. }
  3671. const elements2 = $$(".upname a,a.bili-video-card__info--owner")
  3672. for (const element2 of elements2) {
  3673. const href = element2.href
  3674. if (href.startsWith(prefix22)) {
  3675. const key = getUserProfileUrl(href)
  3676. if (key) {
  3677. const nameElement = $(
  3678. ".name,.bili-video-card__info--author",
  3679. element2
  3680. )
  3681. if (nameElement) {
  3682. const title = nameElement.textContent
  3683. const meta = { title, type: "user" }
  3684. nameElement.utags = { key, meta }
  3685. nameElement.dataset.utags_node_type = "link"
  3686. matchedNodesSet.add(nameElement)
  3687. }
  3688. }
  3689. }
  3690. }
  3691. const elements3 = $$(
  3692. [
  3693. "a.up-name",
  3694. "a.card-user-name",
  3695. ".usercard-wrap .user .name",
  3696. ".comment-list .user .name",
  3697. ".user-card .user .name",
  3698. "a[data-usercard-mid]",
  3699. "a.user-name",
  3700. ".user-name a",
  3701. 'a[href^="https://space.bilibili.com/"]',
  3702. "a.staff-name",
  3703. ].join(",")
  3704. )
  3705. for (const element2 of elements3) {
  3706. const href = element2.href
  3707. if (href.startsWith(prefix22)) {
  3708. const key = getUserProfileUrl(href)
  3709. if (key) {
  3710. let title = element2.textContent.trim()
  3711. if (title) {
  3712. title = title.replace(/^@/, "")
  3713. const meta = { title, type: "user" }
  3714. element2.utags = { key, meta }
  3715. matchedNodesSet.add(element2)
  3716. }
  3717. }
  3718. }
  3719. }
  3720. if (
  3721. location.href.startsWith(prefix22) ||
  3722. location.href.startsWith(prefix32 + "space/")
  3723. ) {
  3724. const element2 = $("#h-name,.m-space-info .name")
  3725. if (element2) {
  3726. const title = element2.textContent.trim()
  3727. const key = getUserProfileUrl(location.href)
  3728. if (title && key) {
  3729. const meta = { title, type: "user" }
  3730. element2.utags = { key, meta }
  3731. matchedNodesSet.add(element2)
  3732. }
  3733. }
  3734. }
  3735. const element = $("h1.video-title,h1.title-text")
  3736. if (element) {
  3737. const title = element.textContent.trim()
  3738. const key = getVideoUrl(location.href)
  3739. if (title && key) {
  3740. const meta = { title, type: "video" }
  3741. element.utags = { key, meta }
  3742. matchedNodesSet.add(element)
  3743. }
  3744. }
  3745. const elements4 = $$(
  3746. ".bili-video-card__info--right a,.video-page-card-small .info a,.video-page-operator-card-small .info a"
  3747. )
  3748. for (const element2 of elements4) {
  3749. const key = getVideoUrl(element2.href)
  3750. if (key) {
  3751. const title = element2.textContent.trim()
  3752. const target =
  3753. element2.parentElement.tagName === "H3"
  3754. ? element2.parentElement
  3755. : element2
  3756. if (title) {
  3757. const meta = { title, type: "video" }
  3758. target.utags = { key, meta }
  3759. target.dataset.utags_node_type = "link"
  3760. matchedNodesSet.add(target)
  3761. }
  3762. }
  3763. }
  3764. },
  3765. getStyle: () => bilibili_com_default,
  3766. }
  3767. })()
  3768. var tiktok_com_default =
  3769. ':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}'
  3770. var tiktok_com_default2 = (() => {
  3771. const prefix3 = "https://www.tiktok.com/"
  3772. function getUserProfileUrl(url, exact = false) {
  3773. if (url.startsWith(prefix3)) {
  3774. const href2 = url.slice(23)
  3775. if (exact) {
  3776. if (/^@[\w.-]+([?#].*)?$/.test(href2)) {
  3777. return prefix3 + href2.replace(/(^@[\w.-]+).*/, "$1")
  3778. }
  3779. } else if (/^@[\w.-]+/.test(href2)) {
  3780. return prefix3 + href2.replace(/(^@[\w.-]+).*/, "$1")
  3781. }
  3782. }
  3783. return void 0
  3784. }
  3785. return {
  3786. matches: /tiktok\.com/,
  3787. listNodesSelectors: [
  3788. ".css-ulyotp-DivCommentContentContainer",
  3789. ".css-1gstnae-DivCommentItemWrapper",
  3790. ".css-x6y88p-DivItemContainerV2",
  3791. ],
  3792. conditionNodesSelectors: [
  3793. '.css-ulyotp-DivCommentContentContainer a[href^="/@"]',
  3794. '.css-1gstnae-DivCommentItemWrapper a[href^="/@"]',
  3795. '.css-x6y88p-DivItemContainerV2 a[href^="/@"]',
  3796. ],
  3797. validate(element) {
  3798. const href = element.href
  3799. if (!href.startsWith(prefix3)) {
  3800. return true
  3801. }
  3802. const key = getUserProfileUrl(href, true)
  3803. if (key) {
  3804. const titleElement = $('h3,[data-e2e="browse-username"]', element)
  3805. const title = titleElement
  3806. ? titleElement.textContent.trim()
  3807. : element.textContent.trim()
  3808. if (!title) {
  3809. return false
  3810. }
  3811. const meta = { type: "user", title }
  3812. element.utags = { key, meta }
  3813. return true
  3814. }
  3815. return false
  3816. },
  3817. excludeSelectors: [
  3818. ...default_default2.excludeSelectors,
  3819. ".avatar-anchor",
  3820. '[data-e2e*="avatar"]',
  3821. '[data-e2e="user-card-nickname"]',
  3822. ],
  3823. validMediaSelectors: [
  3824. '[data-e2e="browse-bluev"]',
  3825. '[data-e2e="recommend-card"]',
  3826. ],
  3827. addExtraMatchedNodes(matchedNodesSet) {
  3828. const element = $('h1[data-e2e="user-title"]')
  3829. if (element) {
  3830. const title = element.textContent.trim()
  3831. const key = getUserProfileUrl(location.href)
  3832. if (title && key) {
  3833. const meta = { title, type: "user" }
  3834. element.utags = { key, meta }
  3835. matchedNodesSet.add(element)
  3836. }
  3837. }
  3838. },
  3839. getStyle: () => tiktok_com_default,
  3840. }
  3841. })()
  3842. var pojie_cn_default =
  3843. ".fl cite,.tl cite{white-space:break-spaces}.favatar .pi .authi a{line-height:16px}.favatar .pi{height:auto}"
  3844. var pojie_cn_default2 = (() => {
  3845. return {
  3846. matches: /52pojie\.cn/,
  3847. matchedNodesSelectors: [
  3848. 'a[href*="home.php?mod=space&uid="]',
  3849. 'a[href*="home.php?mod=space&username="]',
  3850. ],
  3851. excludeSelectors: [
  3852. ...default_default2.excludeSelectors,
  3853. "#hd",
  3854. "#pt",
  3855. "#pgt",
  3856. "#jz52top",
  3857. ],
  3858. getStyle: () => pojie_cn_default,
  3859. }
  3860. })()
  3861. var juejin_cn_default = (() => {
  3862. const prefix3 = "https://juejin.cn/"
  3863. function getUserProfileUrl(url) {
  3864. if (url.startsWith(prefix3)) {
  3865. const href2 = url.slice(18)
  3866. if (/^user\/\d+/.test(href2)) {
  3867. return prefix3 + href2.replace(/^(user\/\d+).*/, "$1")
  3868. }
  3869. }
  3870. return void 0
  3871. }
  3872. return {
  3873. matches: /juejin\.cn/,
  3874. validate(element) {
  3875. if ($(".avatar", element)) {
  3876. return false
  3877. }
  3878. const href = element.href
  3879. if (href.startsWith(prefix3)) {
  3880. const key = getUserProfileUrl(href)
  3881. if (key) {
  3882. const titleElement = $(".name", element)
  3883. let title
  3884. if (titleElement) {
  3885. title = titleElement.textContent
  3886. }
  3887. const meta = { type: "user" }
  3888. if (title) {
  3889. meta.title = title
  3890. }
  3891. element.utags = { key, meta }
  3892. element.dataset.utags = element.dataset.utags || ""
  3893. return true
  3894. }
  3895. }
  3896. return false
  3897. },
  3898. excludeSelectors: [
  3899. ...default_default2.excludeSelectors,
  3900. ".list-header",
  3901. ".sub-header",
  3902. ".next-page",
  3903. ".follow-item",
  3904. ".more-item",
  3905. ],
  3906. addExtraMatchedNodes(matchedNodesSet) {
  3907. const key = getUserProfileUrl(location.href)
  3908. if (key) {
  3909. const element2 = $("h1.username")
  3910. if (element2) {
  3911. const title = element2.textContent.trim()
  3912. if (title) {
  3913. const meta = { title, type: "user" }
  3914. element2.utags = { key, meta }
  3915. matchedNodesSet.add(element2)
  3916. }
  3917. }
  3918. }
  3919. const element = $(".sidebar-block.author-block a .username")
  3920. if (element) {
  3921. const anchor = element.closest("a")
  3922. if (anchor) {
  3923. const key2 = getUserProfileUrl(anchor.href)
  3924. if (key2) {
  3925. const titleElement = $(".name", element)
  3926. const title = titleElement
  3927. ? titleElement.textContent
  3928. : element.textContent
  3929. if (title) {
  3930. const meta = { title, type: "user" }
  3931. element.utags = { key: key2, meta }
  3932. matchedNodesSet.add(element)
  3933. }
  3934. }
  3935. }
  3936. }
  3937. },
  3938. }
  3939. })()
  3940. var zhihu_com_default = (() => {
  3941. const prefix3 = "https://www.zhihu.com/"
  3942. function getUserProfileUrl(url, exact = false) {
  3943. if (url.startsWith(prefix3)) {
  3944. const href2 = url.slice(22)
  3945. if (exact) {
  3946. if (/^people\/[\w-]+(\?.*)?$/.test(href2)) {
  3947. return prefix3 + href2.replace(/^(people\/[\w-]+).*/, "$1")
  3948. }
  3949. } else if (/^people\/[\w-]+/.test(href2)) {
  3950. return prefix3 + href2.replace(/^(people\/[\w-]+).*/, "$1")
  3951. }
  3952. }
  3953. return void 0
  3954. }
  3955. return {
  3956. matches: /zhihu\.com/,
  3957. validate(element) {
  3958. if ($(".avatar", element)) {
  3959. return false
  3960. }
  3961. const href = element.href
  3962. if (!href.includes("zhihu.com")) {
  3963. return true
  3964. }
  3965. if (href.startsWith(prefix3 + "people/")) {
  3966. const key = getUserProfileUrl(href, true)
  3967. if (key) {
  3968. const titleElement = $(".name", element)
  3969. let title
  3970. if (titleElement) {
  3971. title = titleElement.textContent
  3972. }
  3973. const meta = { type: "user" }
  3974. if (title) {
  3975. meta.title = title
  3976. }
  3977. element.utags = { key, meta }
  3978. return true
  3979. }
  3980. }
  3981. return false
  3982. },
  3983. excludeSelectors: [
  3984. ...default_default2.excludeSelectors,
  3985. ".NumberBoard",
  3986. ".ProfileMain-tabs",
  3987. ".Profile-lightList",
  3988. ],
  3989. addExtraMatchedNodes(matchedNodesSet) {
  3990. const key = getUserProfileUrl(location.href)
  3991. if (key) {
  3992. const element = $("h1.ProfileHeader-title .ProfileHeader-name")
  3993. if (element) {
  3994. const title = element.textContent.trim()
  3995. if (title) {
  3996. const meta = { title, type: "user" }
  3997. element.utags = { key, meta }
  3998. matchedNodesSet.add(element)
  3999. }
  4000. }
  4001. }
  4002. },
  4003. }
  4004. })()
  4005. var xiaohongshu_com_default =
  4006. ":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}"
  4007. var xiaohongshu_com_default2 = (() => {
  4008. const prefix3 = "https://www.xiaohongshu.com/"
  4009. function getCanonicalUrl2(url) {
  4010. if (url.startsWith(prefix3)) {
  4011. const href2 = url.slice(prefix3.length)
  4012. if (href2.startsWith("search_result") && href2.includes("keyword")) {
  4013. return (
  4014. prefix3 +
  4015. "search_result/?" +
  4016. href2.replace(/.*?(keyword=[^&]*).*/, "$1") +
  4017. "&type=54"
  4018. )
  4019. }
  4020. }
  4021. return url
  4022. }
  4023. function getUserProfileUrl(url, exact = false) {
  4024. if (url.startsWith(prefix3)) {
  4025. const href2 = url.slice(28)
  4026. if (exact) {
  4027. if (/^user\/profile\/\w+(\?.*)?$/.test(href2)) {
  4028. return prefix3 + href2.replace(/^(user\/profile\/\w+).*/, "$1")
  4029. }
  4030. } else if (/^user\/profile\/\w+/.test(href2)) {
  4031. return prefix3 + href2.replace(/^(user\/profile\/\w+).*/, "$1")
  4032. }
  4033. }
  4034. return void 0
  4035. }
  4036. function getPostUrl(url) {
  4037. if (url.startsWith(prefix3)) {
  4038. const href2 = url.slice(28)
  4039. if (/^explore\/\w+/.test(href2)) {
  4040. return prefix3 + href2.replace(/^(explore\/\w+).*/, "$1")
  4041. }
  4042. if (/^user\/profile\/\w+\/\w+/.test(href2)) {
  4043. return (
  4044. prefix3 +
  4045. "explore/" +
  4046. href2.replace(/^user\/profile\/\w+\/(\w+).*/, "$1")
  4047. )
  4048. }
  4049. if (/^search_result\/\w+/.test(href2)) {
  4050. return (
  4051. prefix3 +
  4052. "explore/" +
  4053. href2.replace(/^search_result\/(\w+).*/, "$1")
  4054. )
  4055. }
  4056. }
  4057. return void 0
  4058. }
  4059. return {
  4060. matches: /www\.xiaohongshu\.com/,
  4061. listNodesSelectors: [".feeds-container section", ".comment-item"],
  4062. conditionNodesSelectors: [
  4063. ".feeds-container section .author-wrapper .author",
  4064. ".feeds-container section .cover",
  4065. ".comment-item .author-wrapper .author a",
  4066. ],
  4067. validate(element) {
  4068. const href = element.href
  4069. if (!href.startsWith(prefix3)) {
  4070. return true
  4071. }
  4072. let key = getUserProfileUrl(href, true)
  4073. if (key) {
  4074. const titleElement =
  4075. (hasClass(element, "name") ? element : $(".name", element)) ||
  4076. element
  4077. let title
  4078. if (titleElement) {
  4079. title = titleElement.textContent.trim()
  4080. }
  4081. if (!title) {
  4082. return false
  4083. }
  4084. const meta = { type: "user", title }
  4085. element.utags = { key, meta }
  4086. element.dataset.utags = element.dataset.utags || ""
  4087. return true
  4088. }
  4089. key = getPostUrl(href)
  4090. if (key) {
  4091. const meta = { type: "post" }
  4092. if (hasClass(element, "cover")) {
  4093. const sibling = element.nextElementSibling
  4094. if (sibling && hasClass(sibling, "footer")) {
  4095. const titleElement = $(".title span", sibling)
  4096. if (titleElement) {
  4097. const title = titleElement.textContent.trim()
  4098. if (title) {
  4099. meta.title = title
  4100. }
  4101. }
  4102. element.dataset.utags = element.dataset.utags || ""
  4103. }
  4104. }
  4105. element.utags = { key, meta }
  4106. return true
  4107. }
  4108. return true
  4109. },
  4110. excludeSelectors: [
  4111. ...default_default2.excludeSelectors,
  4112. ".side-bar",
  4113. ".dropdown-nav",
  4114. ".dropdown-container",
  4115. ".interaction-info",
  4116. ],
  4117. addExtraMatchedNodes(matchedNodesSet) {
  4118. let key = getUserProfileUrl(location.href)
  4119. if (key) {
  4120. const element = $(".user-info .user-name")
  4121. if (element) {
  4122. const title = element.textContent.trim()
  4123. if (title) {
  4124. const meta = { title, type: "user" }
  4125. element.utags = { key, meta }
  4126. element.dataset.utags_node_type = "link"
  4127. matchedNodesSet.add(element)
  4128. }
  4129. }
  4130. }
  4131. key = getPostUrl(location.href)
  4132. if (key) {
  4133. const element = $(".note-content .title")
  4134. if (element) {
  4135. const title = element.textContent.trim()
  4136. if (title) {
  4137. const meta = { title, type: "post" }
  4138. element.utags = { key, meta }
  4139. matchedNodesSet.add(element)
  4140. }
  4141. }
  4142. }
  4143. },
  4144. getCanonicalUrl: getCanonicalUrl2,
  4145. getStyle: () => xiaohongshu_com_default,
  4146. }
  4147. })()
  4148. var weibo_com_default = (() => {
  4149. const prefix3 = "https://weibo.com/"
  4150. const prefix22 = "https://m.weibo.cn/"
  4151. function getCanonicalUrl2(url) {
  4152. if (url.startsWith(prefix3) || url.startsWith(prefix22)) {
  4153. const href2 = getUserProfileUrl(url, true)
  4154. if (href2) {
  4155. return href2
  4156. }
  4157. }
  4158. return url
  4159. }
  4160. function getUserProfileUrl(url, exact = false) {
  4161. if (url.startsWith(prefix3) || url.startsWith(prefix22)) {
  4162. const href2 = url.startsWith(prefix22) ? url.slice(19) : url.slice(18)
  4163. if (exact) {
  4164. if (/^u\/\d+(\?.*)?$/.test(href2)) {
  4165. return prefix3 + href2.replace(/^(u\/\d+).*/, "$1")
  4166. }
  4167. if (/^profile\/\d+(\?.*)?$/.test(href2)) {
  4168. return prefix3 + "u/" + href2.replace(/^profile\/(\d+).*/, "$1")
  4169. }
  4170. if (/^\d+(\?.*)?$/.test(href2)) {
  4171. return prefix3 + "u/" + href2.replace(/^(\d+).*/, "$1")
  4172. }
  4173. } else {
  4174. if (/^u\/\d+/.test(href2)) {
  4175. return prefix3 + href2.replace(/^(u\/\d+).*/, "$1")
  4176. }
  4177. if (/^profile\/\d+/.test(href2)) {
  4178. return prefix3 + "u/" + href2.replace(/^profile\/(\d+).*/, "$1")
  4179. }
  4180. if (/^\d+/.test(href2)) {
  4181. return prefix3 + "u/" + href2.replace(/^(\d+).*/, "$1")
  4182. }
  4183. }
  4184. }
  4185. return void 0
  4186. }
  4187. return {
  4188. matches: /weibo\.com|weibo\.cn/,
  4189. validate(element) {
  4190. const href = element.href
  4191. if (!href.includes("weibo.com") && !href.includes("weibo.cn")) {
  4192. return true
  4193. }
  4194. const key = getUserProfileUrl(href, true)
  4195. if (key) {
  4196. const meta = { type: "user" }
  4197. element.utags = { key, meta }
  4198. if ($(".m-icon.vipicon", element)) {
  4199. element.dataset.utags = element.dataset.utags || ""
  4200. }
  4201. return true
  4202. }
  4203. return true
  4204. },
  4205. excludeSelectors: [
  4206. ...default_default2.excludeSelectors,
  4207. '[class^="Frame_side_"]',
  4208. 'a[href*="promote.biz.weibo.cn"]',
  4209. ],
  4210. addExtraMatchedNodes(matchedNodesSet) {
  4211. const key = getUserProfileUrl(location.href)
  4212. if (key) {
  4213. const element = $(
  4214. '[class^="ProfileHeader_name_"],.profile-cover .mod-fil-name .txt-shadow'
  4215. )
  4216. if (element) {
  4217. const title = element.textContent.trim()
  4218. if (title) {
  4219. const meta = { title, type: "user" }
  4220. element.utags = { key, meta }
  4221. matchedNodesSet.add(element)
  4222. }
  4223. }
  4224. }
  4225. },
  4226. getCanonicalUrl: getCanonicalUrl2,
  4227. }
  4228. })()
  4229. var sspai_com_default =
  4230. ":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}"
  4231. var sspai_com_default2 = (() => {
  4232. const prefix3 = "https://sspai.com/"
  4233. const excludeLinks = [
  4234. "https://sspai.com/prime",
  4235. "https://sspai.com/matrix",
  4236. "https://sspai.com/page/about-us",
  4237. "https://sspai.com/page/agreement",
  4238. "https://sspai.com/page/bussiness",
  4239. "https://sspai.com/post/37793",
  4240. "https://sspai.com/page/client",
  4241. "https://sspai.com/s/J71e",
  4242. "https://sspai.com/mall",
  4243. ]
  4244. function getCanonicalUrl2(url) {
  4245. if (url.startsWith(prefix3)) {
  4246. const href = url.slice(18)
  4247. if (href.startsWith("u/")) {
  4248. return prefix3 + href.replace(/^(u\/\w+).*/, "$1")
  4249. }
  4250. }
  4251. return url
  4252. }
  4253. function getUserProfileUrl(url) {
  4254. if (url.startsWith(prefix3)) {
  4255. const href2 = url.slice(18)
  4256. if (/^u\/\w+/.test(href2)) {
  4257. return prefix3 + href2.replace(/^(u\/\w+).*/, "$1")
  4258. }
  4259. }
  4260. return void 0
  4261. }
  4262. function getPostUrl(url) {
  4263. if (url.startsWith(prefix3)) {
  4264. const href2 = url.slice(18)
  4265. if (/^post\/\d+/.test(href2)) {
  4266. return prefix3 + href2.replace(/^(post\/\d+).*/, "$1")
  4267. }
  4268. }
  4269. return void 0
  4270. }
  4271. return {
  4272. matches: /sspai\.com/,
  4273. validate(element) {
  4274. const href = element.href
  4275. for (const link of excludeLinks) {
  4276. if (href.includes(link)) {
  4277. return false
  4278. }
  4279. }
  4280. if (
  4281. hasClass(element, "ss__user__nickname__wrapper") ||
  4282. element.closest('.card_bottom > a[href^="/u/"]')
  4283. ) {
  4284. element.dataset.utags = element.dataset.utags || ""
  4285. return true
  4286. }
  4287. return true
  4288. },
  4289. excludeSelectors: [
  4290. ...default_default2.excludeSelectors,
  4291. "header",
  4292. "footer",
  4293. ".pai_abstract",
  4294. ".pai_title .link",
  4295. ],
  4296. addExtraMatchedNodes(matchedNodesSet) {
  4297. let key = getPostUrl(location.href)
  4298. if (key) {
  4299. const element = $(".article-header .title")
  4300. if (element && !element.closest(".pai_title")) {
  4301. const title = element.textContent.trim()
  4302. if (title) {
  4303. const meta = { title, type: "post" }
  4304. element.utags = { key, meta }
  4305. matchedNodesSet.add(element)
  4306. }
  4307. }
  4308. }
  4309. key = getUserProfileUrl(location.href)
  4310. if (key) {
  4311. const element = $(
  4312. ".user_content .user__info__card .ss__user__card__nickname"
  4313. )
  4314. if (element) {
  4315. const title = element.textContent.trim()
  4316. if (title) {
  4317. const meta = { title, type: "user" }
  4318. element.utags = { key, meta }
  4319. matchedNodesSet.add(element)
  4320. }
  4321. }
  4322. }
  4323. },
  4324. getCanonicalUrl: getCanonicalUrl2,
  4325. getStyle: () => sspai_com_default,
  4326. }
  4327. })()
  4328. var douyin_com_default =
  4329. ':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:hsla(0,0%,100%,.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:hsla(0,0%,100%,.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:hsla(0,0%,100%,.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:hsla(0,0%,100%,.8666666667) !important}'
  4330. var douyin_com_default2 = (() => {
  4331. const prefix3 = "https://www.douyin.com/"
  4332. function getUserProfileUrl(url, exact = false) {
  4333. if (url.startsWith(prefix3)) {
  4334. const href2 = url.slice(23)
  4335. if (exact) {
  4336. if (/^user\/[\w-]+(\?.*)?$/.test(href2)) {
  4337. return prefix3 + href2.replace(/^(user\/[\w-]+).*/, "$1")
  4338. }
  4339. } else if (/^user\/[\w-]+/.test(href2)) {
  4340. return prefix3 + href2.replace(/^(user\/[\w-]+).*/, "$1")
  4341. }
  4342. }
  4343. return void 0
  4344. }
  4345. function getVideoUrl(url) {
  4346. if (url.startsWith(prefix3)) {
  4347. const href2 = url.slice(23)
  4348. if (/^video\/\w+/.test(href2)) {
  4349. return prefix3 + href2.replace(/^(video\/\w+).*/, "$1")
  4350. }
  4351. }
  4352. return void 0
  4353. }
  4354. function getNoteUrl(url) {
  4355. if (url.startsWith(prefix3)) {
  4356. const href2 = url.slice(23)
  4357. if (/^note\/\w+/.test(href2)) {
  4358. return prefix3 + href2.replace(/^(note\/\w+).*/, "$1")
  4359. }
  4360. }
  4361. return void 0
  4362. }
  4363. return {
  4364. matches: /www\.douyin\.com/,
  4365. validate(element) {
  4366. const href = element.href
  4367. if (!href.includes("www.douyin.com")) {
  4368. return true
  4369. }
  4370. let key = getUserProfileUrl(href, true)
  4371. if (key) {
  4372. const meta = { type: "user" }
  4373. element.utags = { key, meta }
  4374. return true
  4375. }
  4376. key = getVideoUrl(href)
  4377. if (key) {
  4378. const meta = { type: "video" }
  4379. element.utags = { key, meta }
  4380. return true
  4381. }
  4382. key = getNoteUrl(href)
  4383. if (key) {
  4384. const meta = { type: "post" }
  4385. element.utags = { key, meta }
  4386. return true
  4387. }
  4388. return true
  4389. },
  4390. excludeSelectors: [
  4391. ...default_default2.excludeSelectors,
  4392. '[data-e2e="douyin-navigation"]',
  4393. ],
  4394. validMediaSelectors: ['img[src*="twemoji"]'],
  4395. addExtraMatchedNodes(matchedNodesSet) {
  4396. let key = getUserProfileUrl(location.href)
  4397. if (key) {
  4398. const element = getFirstHeadElement("h1")
  4399. if (element) {
  4400. const title = element.textContent.trim()
  4401. if (title) {
  4402. const meta = { title, type: "user" }
  4403. element.utags = { key, meta }
  4404. matchedNodesSet.add(element)
  4405. }
  4406. }
  4407. }
  4408. key = getVideoUrl(location.href)
  4409. if (key) {
  4410. const element = getFirstHeadElement("h1")
  4411. if (element) {
  4412. const title = element.textContent.trim()
  4413. const target = element.parentElement.parentElement
  4414. if (title) {
  4415. const meta = { title, type: "video" }
  4416. target.utags = { key, meta }
  4417. target.dataset.utags_node_type = "link"
  4418. matchedNodesSet.add(target)
  4419. }
  4420. }
  4421. }
  4422. key = getNoteUrl(location.href)
  4423. if (key) {
  4424. const element = getFirstHeadElement("h1")
  4425. if (element) {
  4426. const title = element.textContent.trim()
  4427. if (title) {
  4428. const meta = { title, type: "post" }
  4429. element.utags = { key, meta }
  4430. matchedNodesSet.add(element)
  4431. }
  4432. }
  4433. }
  4434. },
  4435. getStyle: () => douyin_com_default,
  4436. }
  4437. })()
  4438. var podcasts_google_com_default = ""
  4439. var podcasts_google_com_default2 = (() => {
  4440. const prefix3 = "https://podcasts.google.com/"
  4441. function getEpisodeUrl(url, exact = false) {
  4442. if (url.startsWith(prefix3)) {
  4443. const href2 = url.slice(28)
  4444. if (exact) {
  4445. if (/^feed\/\w+\/episode\/\w+(\?.*)?$/.test(href2)) {
  4446. return prefix3 + href2.replace(/^(feed\/\w+\/episode\/\w+).*/, "$1")
  4447. }
  4448. } else if (/^feed\/\w+\/episode\/\w+/.test(href2)) {
  4449. return prefix3 + href2.replace(/^(feed\/\w+\/episode\/\w+).*/, "$1")
  4450. }
  4451. }
  4452. return void 0
  4453. }
  4454. function getFeedUrl(url) {
  4455. if (url.startsWith(prefix3)) {
  4456. const href2 = url.slice(28)
  4457. if (/^feed\/\w+(\?.*)?$/.test(href2)) {
  4458. return prefix3 + href2.replace(/^(feed\/\w+).*/, "$1")
  4459. }
  4460. }
  4461. return void 0
  4462. }
  4463. function getCanonicalUrl2(url) {
  4464. if (url.startsWith(prefix3)) {
  4465. let url2 = getFeedUrl(url)
  4466. if (url2) {
  4467. return url2
  4468. }
  4469. url2 = getEpisodeUrl(url)
  4470. if (url2) {
  4471. return url2
  4472. }
  4473. }
  4474. return url
  4475. }
  4476. return {
  4477. matches: /podcasts\.google\.com/,
  4478. excludeSelectors: [
  4479. ...default_default2.excludeSelectors,
  4480. "header",
  4481. "gm-coplanar-drawer",
  4482. ],
  4483. addExtraMatchedNodes(matchedNodesSet) {
  4484. let key = getEpisodeUrl(location.href)
  4485. if (key) {
  4486. const element = $("h5")
  4487. if (element) {
  4488. const title = element.textContent.trim()
  4489. if (title) {
  4490. const meta = { title, type: "episode" }
  4491. element.utags = { key, meta }
  4492. matchedNodesSet.add(element)
  4493. }
  4494. }
  4495. }
  4496. key = getFeedUrl(location.href)
  4497. if (key) {
  4498. for (const container of $$("[data-encoded-feed]")) {
  4499. if (isVisible(container)) {
  4500. const element = $(
  4501. "div:first-child > div:first-child > div:first-child > div:first-child",
  4502. container
  4503. )
  4504. if (element) {
  4505. const title = element.textContent.trim()
  4506. if (title) {
  4507. const meta = { title, type: "feed" }
  4508. element.utags = { key, meta }
  4509. matchedNodesSet.add(element)
  4510. }
  4511. }
  4512. }
  4513. }
  4514. }
  4515. for (const element of $$('a[role="listitem"]')) {
  4516. const key2 = getEpisodeUrl(element.href)
  4517. const titleElement = $(
  4518. 'div[role="navigation"] div div[role="presentation"]',
  4519. element
  4520. )
  4521. if (key2 && titleElement) {
  4522. const title = titleElement.textContent
  4523. const meta = { title, type: "episode" }
  4524. titleElement.utags = { key: key2, meta }
  4525. titleElement.dataset.utags_node_type = "link"
  4526. matchedNodesSet.add(titleElement)
  4527. }
  4528. }
  4529. for (const element of $$(
  4530. 'a[href^="./feed/"]:not(a[href*="/episode/"])'
  4531. )) {
  4532. if (!isVisible(element)) {
  4533. continue
  4534. }
  4535. const key2 = getFeedUrl(element.href)
  4536. const titleElement = $("div > div", element)
  4537. if (titleElement) {
  4538. const title = titleElement.textContent
  4539. const meta = { title, type: "feed" }
  4540. titleElement.utags = { key: key2, meta }
  4541. titleElement.dataset.utags_node_type = "link"
  4542. matchedNodesSet.add(titleElement)
  4543. }
  4544. }
  4545. },
  4546. getCanonicalUrl: getCanonicalUrl2,
  4547. getStyle: () => podcasts_google_com_default,
  4548. }
  4549. })()
  4550. var rebang_today_default =
  4551. ":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)}"
  4552. var rebang_today_default2 = (() => {
  4553. const nodeNameMap = {
  4554. 知乎: "zhihu",
  4555. 微博: "weibo",
  4556. IT之家: "ithome",
  4557. 虎扑: "hupu",
  4558. 豆瓣社区: "douban-community",
  4559. 虎嗅: "huxiu",
  4560. 少数派: "sspai",
  4561. 网易新闻: "ne-news",
  4562. 澎湃新闻: "thepaper",
  4563. 小红书: "xiaohongshu",
  4564. "36\u6C2A": "36kr",
  4565. 今日头条: "toutiao",
  4566. 爱范儿: "ifanr",
  4567. 豆瓣书影音: "douban-media",
  4568. 什么值得买: "smzdm",
  4569. 百度: "baidu",
  4570. 百度贴吧: "baidu-tieba",
  4571. 吾爱破解: "52pojie",
  4572. 观风闻: "guancha-user",
  4573. 雪球: "xueqiu",
  4574. 东方财富: "eastmoney",
  4575. 新浪财经: "sina-fin",
  4576. 蓝点网: "landian",
  4577. 小众软件: "appinn",
  4578. 反斗限免: "apprcn",
  4579. NGA社区: "nga",
  4580. 游民星空: "gamersky",
  4581. 喷嚏网: "penti",
  4582. 沙雕新闻: "shadiao-news",
  4583. 抖音: "douyin",
  4584. 哔哩哔哩: "bilibili",
  4585. 直播吧: "zhibo8",
  4586. 掘金: "juejin",
  4587. 技术期刊: "journal-tech",
  4588. 开发者头条: "toutiaoio",
  4589. GitHub: "github",
  4590. AcFun: "acfun",
  4591. 宽带山: "kds",
  4592. V2EX: "v2ex",
  4593. 格隆汇: "gelonghui",
  4594. 第一财经: "diyicaijing",
  4595. InfoQ: "infoq",
  4596. CSDN: "csdn",
  4597. }
  4598. return {
  4599. matches: /rebang\.today/,
  4600. preProcess() {
  4601. const nodes = $$(":not(a) > .arco-tag-content")
  4602. for (const node of nodes) {
  4603. const name = node.textContent
  4604. if (name && !node.closest("a")) {
  4605. const nodeId = nodeNameMap[name]
  4606. if (nodeId) {
  4607. const a = createElement("a", {
  4608. href: "https://rebang.today/home?tab=" + nodeId,
  4609. })
  4610. node.after(a)
  4611. a.append(node)
  4612. }
  4613. }
  4614. }
  4615. },
  4616. listNodesSelectors: [
  4617. ".w-screen ul:not(.utags_ul) > li",
  4618. "aside .w-full .select-none",
  4619. ],
  4620. conditionNodesSelectors: [
  4621. '[data-utags_list_node] [data-utags]:not([href^="https://www.v2ex.com/member/"])',
  4622. '[data-utags_list_node] a[href^="https://www.v2ex.com/member/"][data-utags].hidden',
  4623. ],
  4624. excludeSelectors: [
  4625. ...default_default2.excludeSelectors,
  4626. "header",
  4627. ".absolute.rounded-xl",
  4628. "ul li h1 + p a",
  4629. ],
  4630. validMediaSelectors: [
  4631. ".text-text-100",
  4632. ".items-center .rounded-full",
  4633. 'a[href^="https://github.com/"] svg',
  4634. 'a[href^="https://space.bilibili.com/"] img',
  4635. 'a[href^="https://toutiao.io/subjects/"] img',
  4636. "svg.arco-icon",
  4637. ],
  4638. getStyle: () => rebang_today_default,
  4639. }
  4640. })()
  4641. var myanimelist_net_default =
  4642. ":not(#a):not(#b):not(#c) tbody.list-item td.title{--utags-notag-captain-tag-top: -6px;--utags-notag-captain-tag-left: -24px}"
  4643. var myanimelist_net_default2 = (() => {
  4644. return {
  4645. matches: /myanimelist\.net/,
  4646. listNodesSelectors: [],
  4647. conditionNodesSelectors: [],
  4648. excludeSelectors: [
  4649. ...default_default2.excludeSelectors,
  4650. "#headerSmall",
  4651. "#menu",
  4652. "#nav",
  4653. ".header",
  4654. "#status-menu",
  4655. 'a[href^="/sns/register/"]',
  4656. 'a[href^="/logout"]',
  4657. 'a[href*="/membership?"]',
  4658. 'a[href*="/login.php"]',
  4659. 'a[href*="/register.php"]',
  4660. 'a[href*="/dbchanges.php"]',
  4661. 'a[href*="/editprofile.php"]',
  4662. 'a[href*="go=write"]',
  4663. 'a[href^="/ownlist/anime/add?"]',
  4664. '[class*="btn-"]',
  4665. '[class*="icon-"]',
  4666. '[rel*="sponsored"]',
  4667. ],
  4668. getStyle: () => myanimelist_net_default,
  4669. }
  4670. })()
  4671. var douban_com_default = (() => {
  4672. function getCanonicalUrl2(url) {
  4673. if (url.includes("douban.com")) {
  4674. return deleteUrlParameters(url, [
  4675. "ref",
  4676. "dcs",
  4677. "dcm",
  4678. "from",
  4679. "from_",
  4680. "dt_time_source",
  4681. "target_user_id",
  4682. "_dtcc",
  4683. "_i",
  4684. ])
  4685. }
  4686. return url
  4687. }
  4688. return {
  4689. matches: /douban\.com/,
  4690. listNodesSelectors: [],
  4691. conditionNodesSelectors: [],
  4692. excludeSelectors: [
  4693. ...default_default2.excludeSelectors,
  4694. ".tabs",
  4695. 'a[href*="/accounts/login?"]',
  4696. 'a[href*="/passport/login?"]',
  4697. 'a[href*="/register?"]',
  4698. ],
  4699. getCanonicalUrl: getCanonicalUrl2,
  4700. }
  4701. })()
  4702. var pixiv_net_default = ""
  4703. var pixiv_net_default2 = /* @__PURE__ */ (() => {
  4704. const prefix3 = "https://www.pixiv.net/"
  4705. function getUserProfileUrl(url, exact = false) {
  4706. if (url.startsWith(prefix3)) {
  4707. let href2 = url.slice(22)
  4708. if (href2.startsWith("en/")) {
  4709. href2 = href2.slice(3)
  4710. }
  4711. if (exact) {
  4712. if (/^users\/\d+([?#].*)?$/.test(href2)) {
  4713. return prefix3 + href2.replace(/^(users\/\d+).*/, "$1")
  4714. }
  4715. } else if (/^users\/\d+/.test(href2)) {
  4716. return prefix3 + href2.replace(/^(users\/\d+).*/, "$1")
  4717. }
  4718. }
  4719. return void 0
  4720. }
  4721. return {
  4722. matches: /pixiv\.net/,
  4723. validate(element) {
  4724. const href = element.href
  4725. if (!href.includes("www.pixiv.net")) {
  4726. return true
  4727. }
  4728. const key = getUserProfileUrl(href, true)
  4729. if (key) {
  4730. const title = element.textContent
  4731. if (
  4732. !title ||
  4733. /プロフィールを見る|View Profile|프로필 보기|查看个人资料|查看個人資料|ホーム|Home|홈|主页|首頁/.test(
  4734. title
  4735. )
  4736. ) {
  4737. return false
  4738. }
  4739. const meta = { type: "user", title }
  4740. element.utags = { key, meta }
  4741. element.dataset.utags = element.dataset.utags || ""
  4742. return true
  4743. }
  4744. return false
  4745. },
  4746. addExtraMatchedNodes(matchedNodesSet) {
  4747. const key = getUserProfileUrl(location.href)
  4748. if (key) {
  4749. const element = $("h1")
  4750. if (element) {
  4751. const title = element.textContent.trim()
  4752. if (title) {
  4753. const meta = { title, type: "user" }
  4754. element.utags = { key, meta }
  4755. matchedNodesSet.add(element)
  4756. }
  4757. }
  4758. }
  4759. },
  4760. getStyle: () => pixiv_net_default,
  4761. }
  4762. })()
  4763. var discourse_default =
  4764. ':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"],:not(#a):not(#b):not(#c) .topic-body .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),:not(#a):not(#b):not(#c) .topic-body .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,:not(#a):not(#b):not(#c) .topic-body .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}'
  4765. var discourse_default2 = (() => {
  4766. const prefix3 = location.origin + "/"
  4767. const getUserProfileUrl = (url, exact = false) => {
  4768. if (url.startsWith(prefix3)) {
  4769. const href2 = url.slice(prefix3.length).toLowerCase()
  4770. if (exact) {
  4771. if (/^u\/[\w.-]+([?#].*)?$/.test(href2)) {
  4772. return prefix3 + href2.replace(/^(u\/[\w.-]+).*/, "$1")
  4773. }
  4774. } else if (/^u\/[\w.-]+/.test(href2)) {
  4775. return prefix3 + href2.replace(/^(u\/[\w.-]+).*/, "$1")
  4776. }
  4777. }
  4778. return void 0
  4779. }
  4780. function getPostUrl(url, exact = false) {
  4781. if (url.startsWith(prefix3)) {
  4782. const href2 = url.slice(prefix3.length).toLowerCase()
  4783. if (exact) {
  4784. if (/^t\/[^/]+\/\d+(\/\d+)?([?#].*)?$/.test(href2)) {
  4785. return prefix3 + href2.replace(/^(t\/[^/]+\/\d+).*/, "$1")
  4786. }
  4787. } else if (/^t\/[^/]+\/\d+?/.test(href2)) {
  4788. return prefix3 + href2.replace(/^(t\/[^/]+\/\d+).*/, "$1")
  4789. }
  4790. }
  4791. return void 0
  4792. }
  4793. function getCategoryUrl(url, exact = false) {
  4794. if (url.startsWith(prefix3)) {
  4795. const href2 = url.slice(prefix3.length).toLowerCase()
  4796. if (exact) {
  4797. if (/^c\/[\w-]+(\/[\w-]+)?\/\d+([?#].*)?$/.test(href2)) {
  4798. return (
  4799. prefix3 + href2.replace(/^(c\/[\w-]+(\/[\w-]+)?\/\d+).*/, "$1")
  4800. )
  4801. }
  4802. } else if (/^c\/[\w-]+(\/[\w-]+)?\/\d+?/.test(href2)) {
  4803. return prefix3 + href2.replace(/^(c\/[\w-]+(\/[\w-]+)?\/\d+).*/, "$1")
  4804. }
  4805. }
  4806. return void 0
  4807. }
  4808. function getTagUrl(url, exact = false) {
  4809. if (url.startsWith(prefix3)) {
  4810. const href2 = url.slice(prefix3.length).toLowerCase()
  4811. if (exact) {
  4812. if (/^tag\/[^/?#]+([?#].*)?$/.test(href2)) {
  4813. return prefix3 + href2.replace(/^(tag\/[^/?#]+).*/, "$1")
  4814. }
  4815. } else if (/^tag\/[^/?#]+?/.test(href2)) {
  4816. return prefix3 + href2.replace(/^(tag\/[^/?#]+).*/, "$1")
  4817. }
  4818. }
  4819. return void 0
  4820. }
  4821. return {
  4822. matches:
  4823. /meta\.discourse\.org|linux\.do|meta\.appinn\.net|community\.openai\.com|community\.cloudflare\.com|community\.wanikani\.com|forum\.cursor\.com/,
  4824. preProcess() {
  4825. setVisitedAvailable(true)
  4826. },
  4827. listNodesSelectors: [
  4828. ".topic-list .topic-list-body tr",
  4829. ".topic-area .topic-post",
  4830. ".search-results .fps-result",
  4831. ".column .latest-topic-list .latest-topic-list-item",
  4832. ],
  4833. conditionNodesSelectors: [
  4834. ".topic-list .topic-list-body tr .title",
  4835. ".topic-list .topic-list-body tr .badge-category__wrapper",
  4836. ".topic-list .topic-list-body tr .discourse-tag",
  4837. ".topic-list .topic-list-body tr .posters a:first-of-type",
  4838. ".mobile-view .topic-list a[data-user-card]",
  4839. ".topic-area .topic-post:nth-of-type(n+2) .topic-meta-data:not(.embedded-reply) .names a",
  4840. ".search-results .fps-result .search-link",
  4841. ".search-results .fps-result .badge-category__wrapper",
  4842. ".search-results .fps-result .discourse-tag",
  4843. ".column .latest-topic-list .latest-topic-list-item .main-link .title",
  4844. ".column .latest-topic-list .latest-topic-list-item .main-link .badge-category__wrapper",
  4845. ".column .latest-topic-list .latest-topic-list-item .main-link .discourse-tag",
  4846. ],
  4847. validate(element) {
  4848. const href = element.href
  4849. if (!href.startsWith(prefix3)) {
  4850. return true
  4851. }
  4852. let key = getUserProfileUrl(href, true)
  4853. if (key) {
  4854. const titleElement = $("span.username", element)
  4855. const title = getTrimmedTitle(titleElement || element)
  4856. if (
  4857. !title &&
  4858. !element.closest(".topic-list tr .posters a:first-of-type") &&
  4859. !element.closest(".bookmark-list tr a.avatar") && // https://linux.do/u/neo/activity/reactions
  4860. !element.closest(
  4861. ".user-content .user-stream-item__header a.avatar-link"
  4862. ) && // https://linux.do/u/neo/activity/likes-given
  4863. !element.closest(
  4864. ".user-content .filter-1 .post-list-item .post-list-item__header a.avatar-link"
  4865. ) &&
  4866. !element.closest(".column .latest-topic-list .topic-poster a") &&
  4867. !element.closest(".search-results .author a")
  4868. ) {
  4869. return false
  4870. }
  4871. const meta = { type: "user", title }
  4872. element.utags = { key, meta }
  4873. element.dataset.utags = element.dataset.utags || ""
  4874. if (element.closest(".topic-body .names a")) {
  4875. element.dataset.utags_position_selector = ".topic-body .names"
  4876. } else if (element.closest(".user-card .names a")) {
  4877. element.dataset.utags_position_selector = ".user-card .names"
  4878. } else if ($("span.username", element)) {
  4879. element.dataset.utags_position_selector = "span.username"
  4880. }
  4881. return true
  4882. }
  4883. key = getPostUrl(href)
  4884. if (key) {
  4885. const title = element.textContent.trim()
  4886. if (
  4887. element.closest(".mobile-view .topic-list a[data-user-card]") &&
  4888. element.dataset.userCard
  4889. ) {
  4890. const title2 = element.dataset.userCard
  4891. key = prefix3 + "u/" + title2.toLowerCase()
  4892. const meta2 = { type: "user", title: title2 }
  4893. element.utags = { key, meta: meta2 }
  4894. element.dataset.utags = element.dataset.utags || ""
  4895. return true
  4896. }
  4897. if (!title) {
  4898. return false
  4899. }
  4900. if (
  4901. element.closest("header .topic-link") &&
  4902. getComputedStyle(element).display === "inline"
  4903. ) {
  4904. element.dataset.utags_flag = "inline"
  4905. }
  4906. const meta = { type: "post", title }
  4907. element.utags = { key, meta }
  4908. markElementWhetherVisited(key, element)
  4909. element.dataset.utags = element.dataset.utags || ""
  4910. return true
  4911. }
  4912. key = getCategoryUrl(href)
  4913. if (key) {
  4914. const title = element.textContent.trim()
  4915. if (!title) {
  4916. return false
  4917. }
  4918. const meta = { type: "category", title }
  4919. element.utags = { key, meta }
  4920. if (element.closest(".column .category-list .category-title-link")) {
  4921. element.dataset.utags_position_selector =
  4922. ".category-text-title .category-name"
  4923. }
  4924. return true
  4925. }
  4926. key = getTagUrl(href)
  4927. if (key) {
  4928. const title = element.textContent.trim()
  4929. if (!title) {
  4930. return false
  4931. }
  4932. const meta = { type: "tag", title }
  4933. element.utags = { key, meta }
  4934. return true
  4935. }
  4936. return true
  4937. },
  4938. excludeSelectors: [
  4939. ".topic-map",
  4940. ".names .second",
  4941. ".post-activity",
  4942. ".topic-last-activity",
  4943. ".topic-item-stats .activity",
  4944. ".topic-post-badges",
  4945. ".topic-excerpt",
  4946. ".topic-list-category-expert-tags",
  4947. ".list-vote-count",
  4948. ".post-date",
  4949. ".category__badges",
  4950. ".badge-posts",
  4951. ".topic-timeline",
  4952. ".with-timeline",
  4953. ".sidebar-wrapper",
  4954. ".topic-meta-data .post-link-arrow",
  4955. "#skip-link",
  4956. "#navigation-bar",
  4957. ".user-navigation",
  4958. ".search-menu",
  4959. "footer.category-topics-count",
  4960. '[role="tablist"]',
  4961. ".nav.nav-pills",
  4962. ".btn",
  4963. ".custom-header-links",
  4964. ".chat-time",
  4965. ],
  4966. validMediaSelectors: [
  4967. "a img.emoji",
  4968. "a svg.svg-string",
  4969. ".category-title-link",
  4970. ".topic-list tr .posters a:first-of-type",
  4971. ".search-results .author a .avatar",
  4972. ],
  4973. addExtraMatchedNodes(matchedNodesSet) {
  4974. var _a
  4975. const isDarkMode =
  4976. doc.documentElement.dataset.themeType === "dark" || // linux.do
  4977. ((_a = $("header picture > source")) == null ? void 0 : _a.media) ===
  4978. "all"
  4979. doc.documentElement.dataset.utags_darkmode = isDarkMode ? "1" : "0"
  4980. let key = getUserProfileUrl(location.href)
  4981. if (key) {
  4982. let index = 0
  4983. for (const element2 of $$(
  4984. ".user-profile-names .username,.user-profile-names .user-profile-names__primary,.user-profile-names .user-profile-names__secondary"
  4985. )) {
  4986. index++
  4987. if (key !== element2.dataset.utags_key || index === 2) {
  4988. delete element2.dataset.utags
  4989. delete element2.utags
  4990. }
  4991. }
  4992. const element =
  4993. $(".user-profile-names .username") ||
  4994. $(
  4995. ".user-profile-names .user-profile-names__primary,.user-profile-names .user-profile-names__secondary"
  4996. )
  4997. if (element) {
  4998. const title = element.textContent.trim()
  4999. if (title) {
  5000. const meta = { title, type: "user" }
  5001. element.utags = { key, meta }
  5002. element.dataset.utags_key = key
  5003. matchedNodesSet.add(element)
  5004. }
  5005. }
  5006. }
  5007. key = getPostUrl(location.href)
  5008. if (key) {
  5009. addVisited(key)
  5010. }
  5011. for (const element of $$(".leaderboard div[data-user-card]")) {
  5012. const title = element.dataset.userCard
  5013. if (title) {
  5014. key = prefix3 + "u/" + title.toLowerCase()
  5015. const meta = { type: "user", title }
  5016. element.utags = { key, meta }
  5017. element.dataset.utags = element.dataset.utags || ""
  5018. element.dataset.utags_node_type = "link"
  5019. element.dataset.utags_position_selector = element.closest(".winner")
  5020. ? ".winner"
  5021. : ".user__name"
  5022. matchedNodesSet.add(element)
  5023. }
  5024. }
  5025. for (const element of $$(".chat-message span[data-user-card]")) {
  5026. const title = element.dataset.userCard
  5027. if (title) {
  5028. key = prefix3 + "u/" + title.toLowerCase()
  5029. const meta = { type: "user", title }
  5030. element.utags = { key, meta }
  5031. element.dataset.utags = element.dataset.utags || ""
  5032. element.dataset.utags_node_type = "link"
  5033. matchedNodesSet.add(element)
  5034. }
  5035. }
  5036. },
  5037. getStyle: () => discourse_default,
  5038. }
  5039. })()
  5040. var nga_cn_default = ""
  5041. var nga_cn_default2 = (() => {
  5042. const prefix3 = location.origin + "/"
  5043. function getUserProfileUrl(url) {
  5044. if (url.startsWith(prefix3)) {
  5045. const href2 = url.slice(prefix3.length).toLowerCase()
  5046. if (/^nuke\.php\?func=ucp&uid=\d+/.test(href2)) {
  5047. return (
  5048. prefix3 + href2.replace(/^(nuke\.php\?func=ucp&uid=\d+).*/, "$1")
  5049. )
  5050. }
  5051. }
  5052. return void 0
  5053. }
  5054. return {
  5055. matches: /bbs\.nga\.cn|nga\.178\.com|ngabbs\.com/,
  5056. validate(element) {
  5057. const href = element.href
  5058. if (!href.startsWith(prefix3)) {
  5059. return true
  5060. }
  5061. const key = getUserProfileUrl(href)
  5062. if (key) {
  5063. const title = element.textContent
  5064. if (!title) {
  5065. return false
  5066. }
  5067. const meta = { type: "user", title }
  5068. element.utags = { key, meta }
  5069. element.dataset.utags = element.dataset.utags || ""
  5070. return true
  5071. }
  5072. return false
  5073. },
  5074. excludeSelectors: [
  5075. ...default_default2.excludeSelectors,
  5076. ".xxxxxxxxxx",
  5077. ".xxxxxxxxxx",
  5078. ],
  5079. addExtraMatchedNodes(matchedNodesSet) {
  5080. const key = getUserProfileUrl(location.href)
  5081. if (key) {
  5082. const label = $(
  5083. "#ucpuser_info_blockContent > div > span > div:nth-child(2) > div:nth-child(3) > label"
  5084. )
  5085. if (label) {
  5086. const title = label.textContent.trim()
  5087. if (title === "\u7528\u2002\u6237\u2002\u540D") {
  5088. const element = label.nextElementSibling
  5089. if (element) {
  5090. const title2 = element.textContent.trim()
  5091. if (title2) {
  5092. const meta = { title: title2, type: "user" }
  5093. element.utags = { key, meta }
  5094. matchedNodesSet.add(element)
  5095. }
  5096. }
  5097. }
  5098. }
  5099. }
  5100. },
  5101. getStyle: () => nga_cn_default,
  5102. }
  5103. })()
  5104. var dlsite_com_default =
  5105. ':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}'
  5106. var dlsite_com_default2 = (() => {
  5107. const prefix3 = "https://www.dlsite.com/"
  5108. function getProductUrl(url) {
  5109. if (url.startsWith(prefix3)) {
  5110. const href2 = url.slice(prefix3.length)
  5111. if (href2.includes("=/product_id/")) {
  5112. return prefix3 + href2.replace(/^(.+\.html).*/, "$1")
  5113. }
  5114. }
  5115. return void 0
  5116. }
  5117. function getMakerUrl(url) {
  5118. if (url.startsWith(prefix3)) {
  5119. const href2 = url.slice(prefix3.length)
  5120. if (href2.includes("/profile/=/maker_id/")) {
  5121. return prefix3 + href2.replace(/^(.+\.html).*/, "$1")
  5122. }
  5123. }
  5124. return void 0
  5125. }
  5126. return {
  5127. matches: /dlsite\.com/,
  5128. validate(element) {
  5129. if (element.tagName !== "A") {
  5130. return true
  5131. }
  5132. const href = element.href
  5133. if (!href.startsWith(prefix3)) {
  5134. return true
  5135. }
  5136. if (href.includes("/=/")) {
  5137. return true
  5138. }
  5139. return false
  5140. },
  5141. map(element) {
  5142. if (
  5143. element.tagName === "A" &&
  5144. element.closest(
  5145. ".n_worklist .work_name,.recommend_list dt.work_name,.genre_ranking .work_name"
  5146. )
  5147. ) {
  5148. const key = getProductUrl(element.href)
  5149. const title = element.textContent.trim()
  5150. if (!key || !title) {
  5151. return
  5152. }
  5153. const parentElement = element.parentElement
  5154. const meta = { title }
  5155. parentElement.utags = { key, meta }
  5156. parentElement.dataset.utags_node_type = "link"
  5157. return parentElement
  5158. }
  5159. },
  5160. excludeSelectors: [
  5161. ...default_default2.excludeSelectors,
  5162. "header",
  5163. "#top_header",
  5164. "#header",
  5165. ".topicpath",
  5166. ".link_dl_ch",
  5167. ".floating_cart_box",
  5168. "#work_buy_box_wrapper",
  5169. ".pagetop_block",
  5170. ".matome_btn",
  5171. ".review_all",
  5172. ".review_report",
  5173. ".work_cart",
  5174. ".work_favorite",
  5175. ".title_01",
  5176. ".search_more",
  5177. ".btn_category_sample",
  5178. ".btn_cart",
  5179. ".btn_favorite",
  5180. ".btn_follow",
  5181. ".btn_default",
  5182. ".btn_sample",
  5183. ".left_module",
  5184. ".more_work_btn",
  5185. ".heading_link",
  5186. ".work_edition",
  5187. ".work_btn_list",
  5188. ".trans_work_btn",
  5189. ".work_feature",
  5190. ".work_review",
  5191. ".work_rating",
  5192. ".work_category",
  5193. ".work_btn_link",
  5194. ".sort_box",
  5195. ".search_condition_box",
  5196. ".global_pagination",
  5197. ".page_bottom_link",
  5198. ".trial_download",
  5199. ".btn_trial",
  5200. ".work_win_only",
  5201. ".cp_overview_btn",
  5202. ".cp_overview_list",
  5203. ".option_tab_item",
  5204. ".dc_work_group_footer",
  5205. ".new_worklist_more",
  5206. "#work_win_only",
  5207. "#index2_header",
  5208. ".floor_link",
  5209. ".floor_link_creator",
  5210. ".floor_guide",
  5211. ".l-header",
  5212. ".hd_drawer",
  5213. ".index_header",
  5214. ".index_footer",
  5215. ".left_module_comipo",
  5216. "div#left",
  5217. ".footer_floor_nav",
  5218. ".prof_label_list",
  5219. ".type_btn",
  5220. ],
  5221. addExtraMatchedNodes(matchedNodesSet) {
  5222. let key = getProductUrl(location.href)
  5223. if (key) {
  5224. const element = $("h1#work_name")
  5225. if (element) {
  5226. const title = element.textContent.trim()
  5227. if (title) {
  5228. const meta = { title }
  5229. element.utags = { key, meta }
  5230. element.dataset.utags_node_type = "link"
  5231. matchedNodesSet.add(element)
  5232. }
  5233. }
  5234. }
  5235. key = getMakerUrl(location.href)
  5236. if (key) {
  5237. const element = $(".prof_maker_name")
  5238. if (element) {
  5239. const title = element.textContent.trim()
  5240. if (title) {
  5241. const meta = { title }
  5242. element.utags = { key, meta }
  5243. element.dataset.utags_node_type = "link"
  5244. matchedNodesSet.add(element)
  5245. }
  5246. }
  5247. }
  5248. },
  5249. getStyle: () => dlsite_com_default,
  5250. }
  5251. })()
  5252. var keylol_com_default =
  5253. ":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}"
  5254. var keylol_com_default2 = (() => {
  5255. const prefix3 = location.origin + "/"
  5256. function getUserProfileUrl(url, exact = false) {
  5257. if (url.startsWith(prefix3)) {
  5258. const href2 = url.slice(prefix3.length).toLowerCase()
  5259. if (exact) {
  5260. if (/^\?\d+(#.*)?$/.test(href2)) {
  5261. return (
  5262. prefix3 + href2.replace(/^\?(\d+).*/, "home.php?mod=space&uid=$1")
  5263. )
  5264. }
  5265. if (/^suid-\d+(#.*)?$/.test(href2)) {
  5266. return (
  5267. prefix3 +
  5268. href2.replace(/^suid-(\d+).*/, "home.php?mod=space&uid=$1")
  5269. )
  5270. }
  5271. if (/^home\.php\?mod=space&uid=\d+(#.*)?$/.test(href2)) {
  5272. return (
  5273. prefix3 +
  5274. href2.replace(
  5275. /^home\.php\?mod=space&uid=(\d+).*/,
  5276. "home.php?mod=space&uid=$1"
  5277. )
  5278. )
  5279. }
  5280. } else if (/^u\/[\w.-]+/.test(href2)) {
  5281. return prefix3 + href2.replace(/^(u\/[\w.-]+).*/, "$1")
  5282. }
  5283. }
  5284. return void 0
  5285. }
  5286. return {
  5287. matches: /keylol\.com/,
  5288. validate(element) {
  5289. const href = element.href
  5290. if (!href.startsWith(prefix3)) {
  5291. return true
  5292. }
  5293. const key = getUserProfileUrl(href, true)
  5294. if (key) {
  5295. const title = element.textContent
  5296. if (!title) {
  5297. return false
  5298. }
  5299. const meta = { type: "user", title }
  5300. element.utags = { key, meta }
  5301. element.dataset.utags = element.dataset.utags || ""
  5302. return true
  5303. }
  5304. return false
  5305. },
  5306. excludeSelectors: [
  5307. ...default_default2.excludeSelectors,
  5308. "nav",
  5309. "header",
  5310. "#pgt",
  5311. "#fd_page_bottom",
  5312. "#visitedforums",
  5313. "#pt",
  5314. ],
  5315. getStyle: () => keylol_com_default,
  5316. }
  5317. })()
  5318. var tampermonkey_net_cn_default =
  5319. ":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}"
  5320. var tampermonkey_net_cn_default2 = (() => {
  5321. const prefix3 = "https://bbs.tampermonkey.net.cn/"
  5322. function getCanonicalUrl2(url) {
  5323. if (url.startsWith(prefix3)) {
  5324. let href2 = getUserProfileUrl(url, true)
  5325. if (href2) {
  5326. return href2
  5327. }
  5328. href2 = getPostUrl(url, true)
  5329. if (href2) {
  5330. return href2
  5331. }
  5332. }
  5333. return url
  5334. }
  5335. function getUserProfileUrl(url, exact = false) {
  5336. if (url.startsWith(prefix3)) {
  5337. url = deleteUrlParameters(url, "do")
  5338. const href2 = url.slice(prefix3.length).toLowerCase()
  5339. if (exact) {
  5340. if (/^\?\d+(#.*)?$/.test(href2)) {
  5341. return (
  5342. prefix3 + href2.replace(/^\?(\d+).*/, "home.php?mod=space&uid=$1")
  5343. )
  5344. }
  5345. if (/^space-uid-\d+\.html([?#].*)?$/.test(href2)) {
  5346. return (
  5347. prefix3 +
  5348. href2.replace(/^space-uid-(\d+).*/, "home.php?mod=space&uid=$1")
  5349. )
  5350. }
  5351. if (/^home\.php\?mod=space&uid=\d+(#.*)?$/.test(href2)) {
  5352. return (
  5353. prefix3 +
  5354. href2.replace(
  5355. /^home\.php\?mod=space&uid=(\d+).*/,
  5356. "home.php?mod=space&uid=$1"
  5357. )
  5358. )
  5359. }
  5360. } else if (/^u\/[\w.-]+/.test(href2)) {
  5361. return prefix3 + href2.replace(/^(u\/[\w.-]+).*/, "$1")
  5362. }
  5363. }
  5364. return void 0
  5365. }
  5366. function getPostUrl(url) {
  5367. if (url.startsWith(prefix3)) {
  5368. const href2 = url.slice(prefix3.length).toLowerCase()
  5369. if (/^thread(?:-\d+){3}\.html([?#].*)?$/.test(href2)) {
  5370. return (
  5371. prefix3 +
  5372. href2.replace(/^thread-(\d+).*/, "forum.php?mod=viewthread&tid=$1")
  5373. )
  5374. }
  5375. if (/^forum\.php\?mod=redirect&tid=\d+([&#].*)?$/.test(href2)) {
  5376. return (
  5377. prefix3 +
  5378. href2.replace(
  5379. /^forum\.php\?mod=redirect&tid=(\d+).*/,
  5380. "forum.php?mod=viewthread&tid=$1"
  5381. )
  5382. )
  5383. }
  5384. if (/^forum\.php\?mod=viewthread&tid=\d+(#.*)?$/.test(href2)) {
  5385. return (
  5386. prefix3 +
  5387. href2.replace(
  5388. /^forum\.php\?mod=viewthread&tid=(\d+).*/,
  5389. "forum.php?mod=viewthread&tid=$1"
  5390. )
  5391. )
  5392. }
  5393. }
  5394. return void 0
  5395. }
  5396. return {
  5397. matches: /bbs\.tampermonkey\.net\.cn/,
  5398. preProcess() {
  5399. setVisitedAvailable(true)
  5400. },
  5401. listNodesSelectors: [
  5402. //
  5403. "#threadlist table tbody",
  5404. "#postlist .comiis_vrx",
  5405. ],
  5406. conditionNodesSelectors: [
  5407. //
  5408. "#threadlist table tbody h2 a",
  5409. "#threadlist table tbody .km_user a",
  5410. "#postlist .comiis_vrx .authi a",
  5411. ],
  5412. validate(element) {
  5413. const href = element.href
  5414. if (!href.startsWith(prefix3)) {
  5415. return true
  5416. }
  5417. let key = getUserProfileUrl(href, true)
  5418. if (key) {
  5419. let title2 = element.textContent.trim()
  5420. if (!title2) {
  5421. return false
  5422. }
  5423. if (/^https:\/\/bbs\.tampermonkey\.net\.cn\/\?\d+$/.test(title2)) {
  5424. const titleElement = $("#uhd h2")
  5425. if (titleElement) {
  5426. title2 = titleElement.textContent.trim()
  5427. }
  5428. }
  5429. if (
  5430. /^\d+$/.test(title2) &&
  5431. element.parentElement.parentElement.textContent.includes(
  5432. "\u79EF\u5206"
  5433. )
  5434. ) {
  5435. return false
  5436. }
  5437. const meta =
  5438. href === title2 ? { type: "user" } : { type: "user", title: title2 }
  5439. element.utags = { key, meta }
  5440. element.dataset.utags = element.dataset.utags || ""
  5441. return true
  5442. }
  5443. key = getPostUrl(href)
  5444. if (key) {
  5445. const title2 = element.textContent.trim()
  5446. if (!title2) {
  5447. return false
  5448. }
  5449. if (
  5450. title2 === "New" ||
  5451. title2 === "\u7F6E\u9876" ||
  5452. /^\d+$/.test(title2) ||
  5453. /^\d{4}(?:-\d{1,2}){2} \d{2}:\d{2}$/.test(title2)
  5454. ) {
  5455. return false
  5456. }
  5457. if ($('span[title^="20"]', element)) {
  5458. return false
  5459. }
  5460. if (
  5461. element.parentElement.textContent.includes(
  5462. "\u6700\u540E\u56DE\u590D\u4E8E"
  5463. )
  5464. ) {
  5465. return false
  5466. }
  5467. const meta =
  5468. href === title2 ? { type: "post" } : { type: "post", title: title2 }
  5469. element.utags = { key, meta }
  5470. markElementWhetherVisited(key, element)
  5471. return true
  5472. }
  5473. const title = element.textContent.trim()
  5474. if (!title) {
  5475. return false
  5476. }
  5477. if (
  5478. title === "New" ||
  5479. title === "\u7F6E\u9876" ||
  5480. /^\d+$/.test(title)
  5481. ) {
  5482. return false
  5483. }
  5484. return true
  5485. },
  5486. excludeSelectors: [
  5487. ...default_default2.excludeSelectors,
  5488. "#hd",
  5489. ".comiis_pgs",
  5490. "#scrolltop",
  5491. "#fd_page_bottom",
  5492. "#visitedforums",
  5493. "#pt",
  5494. ".tps",
  5495. ".pgbtn",
  5496. ".pgs",
  5497. "#f_pst",
  5498. 'a[href*="member.php?mod=logging"]',
  5499. 'a[href*="member.php?mod=register"]',
  5500. 'a[href*="login/oauth/"]',
  5501. 'a[href*="mod=spacecp&ac=usergroup"]',
  5502. 'a[href*="home.php?mod=spacecp"]',
  5503. "#gadmin_menu",
  5504. "#guser_menu",
  5505. "#gupgrade_menu",
  5506. "#gmy_menu",
  5507. ".showmenu",
  5508. "ul.tb.cl",
  5509. ".comiis_irbox_tit",
  5510. "#thread_types",
  5511. "#filter_special_menu",
  5512. 'a[title="RSS"]',
  5513. ".fa_fav",
  5514. ".p_pop",
  5515. ".comiis_topinfo",
  5516. ".bm .bm_h .kmfz",
  5517. "td.num a",
  5518. "td.plc .pi",
  5519. "td.plc .po.hin",
  5520. "td.pls .tns",
  5521. "ul.comiis_o",
  5522. 'a[onclick*="showMenu"]',
  5523. 'a[onclick*="showWindow"]',
  5524. ".toplist_7ree",
  5525. ],
  5526. addExtraMatchedNodes(matchedNodesSet) {
  5527. let key = getUserProfileUrl(location.href)
  5528. if (key) {
  5529. const element =
  5530. $(".user-profile-names .username") ||
  5531. $(
  5532. ".user-profile-names .user-profile-names__primary,.user-profile-names .user-profile-names__secondary"
  5533. )
  5534. if (element) {
  5535. const title = element.textContent.trim()
  5536. if (title) {
  5537. const meta = { title, type: "user" }
  5538. element.utags = { key, meta }
  5539. matchedNodesSet.add(element)
  5540. }
  5541. }
  5542. }
  5543. key = getPostUrl(location.href)
  5544. if (key) {
  5545. addVisited(key)
  5546. const element = $("#thread_subject")
  5547. if (element) {
  5548. const title = element.textContent.trim()
  5549. if (title) {
  5550. const meta = { title, type: "post" }
  5551. element.utags = { key, meta }
  5552. matchedNodesSet.add(element)
  5553. }
  5554. }
  5555. }
  5556. },
  5557. getStyle: () => tampermonkey_net_cn_default,
  5558. getCanonicalUrl: getCanonicalUrl2,
  5559. }
  5560. })()
  5561. var flarum_default =
  5562. ':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}'
  5563. var flarum_default2 = (() => {
  5564. const prefix3 = location.origin + "/"
  5565. function getUserProfileUrl(url, exact = false) {
  5566. if (url.startsWith(prefix3)) {
  5567. const href2 = url.slice(prefix3.length).toLowerCase()
  5568. if (exact) {
  5569. if (/^u\/[\w-]+([?#].*)?$/.test(href2)) {
  5570. return prefix3 + href2.replace(/^(u\/[\w-]+).*/, "$1")
  5571. }
  5572. } else if (/^u\/[\w-]+/.test(href2)) {
  5573. return prefix3 + href2.replace(/^(u\/[\w-]+).*/, "$1")
  5574. }
  5575. }
  5576. return void 0
  5577. }
  5578. function getPostUrl(url, exact = false) {
  5579. if (url.startsWith(prefix3)) {
  5580. const href2 = url.slice(prefix3.length).toLowerCase()
  5581. if (exact) {
  5582. if (/^d\/\d+(?:-[^/?]+)?(?:\/\d+)?([?#].*)?$/.test(href2)) {
  5583. return prefix3 + href2.replace(/^(d\/\d+).*/, "$1")
  5584. }
  5585. } else if (/^d\/\d+(?:-[^/?]+)?/.test(href2)) {
  5586. return prefix3 + href2.replace(/^(d\/\d+).*/, "$1")
  5587. }
  5588. }
  5589. return void 0
  5590. }
  5591. function getTagUrl(url, exact = false) {
  5592. if (url.startsWith(prefix3)) {
  5593. const href2 = url.slice(prefix3.length).toLowerCase()
  5594. if (exact) {
  5595. if (/^t\/[\w-]+([?#].*)?$/.test(href2)) {
  5596. return prefix3 + href2.replace(/^(t\/[\w-]+).*/, "$1")
  5597. }
  5598. } else if (/^t\/[\w-]+/.test(href2)) {
  5599. return prefix3 + href2.replace(/^(t\/[\w-]+).*/, "$1")
  5600. }
  5601. }
  5602. return void 0
  5603. }
  5604. return {
  5605. matches:
  5606. /discuss\.flarum\.org|discuss\.flarum\.org\.cn|www\.nodeloc\.com|freesmth\.net|freesmth\.uk|veryfb\.com|kater\.me|bbs\.viva-la-vita\.org/,
  5607. preProcess() {
  5608. setVisitedAvailable(true)
  5609. },
  5610. listNodesSelectors: [
  5611. "ul.DiscussionList-discussions li",
  5612. ".hotDiscussion-content ul li",
  5613. ".PostStream .PostStream-item",
  5614. ],
  5615. conditionNodesSelectors: [
  5616. "ul.DiscussionList-discussions li a",
  5617. ".hotDiscussion-content ul li a",
  5618. ".PostStream .PostStream-item .PostUser-name a",
  5619. ],
  5620. validate(element) {
  5621. const href = element.href
  5622. if (!href.startsWith(prefix3)) {
  5623. return true
  5624. }
  5625. let key = getUserProfileUrl(href, true)
  5626. if (key) {
  5627. const titleElement = $(".GroupList-UserList-user .username", element)
  5628. const title = (titleElement || element).textContent.trim()
  5629. const meta = { type: "user", title }
  5630. element.utags = { key, meta }
  5631. element.dataset.utags = element.dataset.utags || ""
  5632. if (titleElement) {
  5633. element.dataset.utags_position_selector =
  5634. ".GroupList-UserList-user .username"
  5635. } else if (element.closest(".PostUser .PostUser-name")) {
  5636. element.dataset.utags_position_selector = ".PostUser"
  5637. }
  5638. return true
  5639. }
  5640. key = getPostUrl(href, true)
  5641. if (key) {
  5642. const titleElement =
  5643. $(".DiscussionListItem-title", element) ||
  5644. $(".TagTile-lastPostedDiscussion-title", element)
  5645. const title = (titleElement || element).textContent.trim()
  5646. if (!title) {
  5647. return false
  5648. }
  5649. const meta = { type: "post", title }
  5650. element.utags = { key, meta }
  5651. element.dataset.utags = element.dataset.utags || ""
  5652. markElementWhetherVisited(key, element)
  5653. if (titleElement) {
  5654. element.dataset.utags_position_selector = hasClass(
  5655. element,
  5656. "TagTile-lastPostedDiscussion"
  5657. )
  5658. ? "time"
  5659. : ".item-terminalPost"
  5660. }
  5661. return true
  5662. }
  5663. key = getTagUrl(href)
  5664. if (key) {
  5665. const title = element.textContent.trim()
  5666. if (!title) {
  5667. return false
  5668. }
  5669. const meta = { type: "tag", title }
  5670. element.utags = { key, meta }
  5671. element.dataset.utags = element.dataset.utags || ""
  5672. return true
  5673. }
  5674. return true
  5675. },
  5676. excludeSelectors: [
  5677. ...default_default2.excludeSelectors,
  5678. "header.App-header",
  5679. ".sideNav",
  5680. ".PostMention",
  5681. ".Post-mentionedBy",
  5682. ".Post-mentionedBy-preview",
  5683. ".PostMention-preview",
  5684. ".Dropdown-menu",
  5685. ".Button",
  5686. ],
  5687. addExtraMatchedNodes(matchedNodesSet) {
  5688. var _a
  5689. const isDarkMode =
  5690. ((_a = $('meta[name="color-scheme"]')) == null
  5691. ? void 0
  5692. : _a.content) === "dark"
  5693. doc.documentElement.dataset.utags_darkmode = isDarkMode ? "1" : "0"
  5694. let key = getPostUrl(location.href)
  5695. if (key) {
  5696. addVisited(key)
  5697. const element = $(".item-title h1")
  5698. if (element) {
  5699. const title = element.textContent.trim()
  5700. if (title) {
  5701. const meta = { title, type: "post" }
  5702. element.utags = { key, meta }
  5703. element.dataset.utags_node_type = "link"
  5704. matchedNodesSet.add(element)
  5705. markElementWhetherVisited(key, element)
  5706. }
  5707. }
  5708. }
  5709. key = getTagUrl(location.href)
  5710. if (key) {
  5711. const element = $("h1.Hero-title")
  5712. if (element) {
  5713. const title = element.textContent.trim()
  5714. if (title) {
  5715. const meta = { title, type: "tag" }
  5716. element.utags = { key, meta }
  5717. element.dataset.utags_node_type = "link"
  5718. matchedNodesSet.add(element)
  5719. }
  5720. }
  5721. }
  5722. },
  5723. getStyle: () => flarum_default,
  5724. }
  5725. })()
  5726. var nodeseek_com_default =
  5727. ":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}"
  5728. var nodeseek_com_default2 = (() => {
  5729. const prefix3 = location.origin + "/"
  5730. function getUserProfileUrl(url, exact = false) {
  5731. if (url.startsWith(prefix3)) {
  5732. const href2 = url.slice(prefix3.length).toLowerCase()
  5733. if (exact) {
  5734. if (/^space\/\d+([?#].*)?$/.test(href2)) {
  5735. return prefix3 + href2.replace(/^(space\/\d+).*/, "$1")
  5736. }
  5737. } else if (/^space\/\d+/.test(href2)) {
  5738. return prefix3 + href2.replace(/^(space\/\d+).*/, "$1")
  5739. }
  5740. }
  5741. return void 0
  5742. }
  5743. function getPostUrl(url, exact = false) {
  5744. if (url.startsWith(prefix3)) {
  5745. const href2 = url.slice(prefix3.length).toLowerCase()
  5746. if (exact) {
  5747. if (/^post-\d+-\d+([?#].*)?$/.test(href2)) {
  5748. return prefix3 + href2.replace(/^(post-\d+)-.*/, "$1") + "-1"
  5749. }
  5750. } else if (/^post-\d+-\d+/.test(href2)) {
  5751. return prefix3 + href2.replace(/^(post-\d+)-.*/, "$1") + "-1"
  5752. }
  5753. }
  5754. return void 0
  5755. }
  5756. function getCategoryUrl(url, exact = false) {
  5757. if (url.startsWith(prefix3)) {
  5758. const href2 = url.slice(prefix3.length).toLowerCase()
  5759. if (exact) {
  5760. if (/^categories\/[\w-]+([?#].*)?$/.test(href2)) {
  5761. return prefix3 + href2.replace(/^(categories\/[\w-]+).*/, "$1")
  5762. }
  5763. } else if (/^categories\/[\w-]+/.test(href2)) {
  5764. return prefix3 + href2.replace(/^(categories\/[\w-]+).*/, "$1")
  5765. }
  5766. }
  5767. return void 0
  5768. }
  5769. return {
  5770. matches: /www\.nodeseek\.com/,
  5771. preProcess() {
  5772. setVisitedAvailable(true)
  5773. },
  5774. listNodesSelectors: [
  5775. "ul.post-list li.post-list-item",
  5776. "ul.comments li.content-item",
  5777. ],
  5778. conditionNodesSelectors: [
  5779. "ul.post-list li.post-list-item .post-title a",
  5780. "ul.post-list li.post-list-item .info-author a",
  5781. "ul.post-list li.post-list-item a.post-category",
  5782. "ul.comments li.content-item a.author-name",
  5783. ],
  5784. validate(element) {
  5785. const href = element.href
  5786. if (!href.startsWith(prefix3)) {
  5787. return true
  5788. }
  5789. let key = getUserProfileUrl(href, true)
  5790. if (key) {
  5791. const title = element.textContent.trim()
  5792. if (!title) {
  5793. return false
  5794. }
  5795. const meta = { type: "user", title }
  5796. element.utags = { key, meta }
  5797. return true
  5798. }
  5799. key = getPostUrl(href, true)
  5800. if (key) {
  5801. const title = element.textContent.trim()
  5802. if (!title || /^#\d+$/.test(title)) {
  5803. return false
  5804. }
  5805. const meta = { type: "post", title }
  5806. element.utags = { key, meta }
  5807. markElementWhetherVisited(key, element)
  5808. return true
  5809. }
  5810. key = getCategoryUrl(href)
  5811. if (key) {
  5812. const title = element.textContent.trim()
  5813. if (!title) {
  5814. return false
  5815. }
  5816. const meta = { type: "category", title }
  5817. element.utags = { key, meta }
  5818. return true
  5819. }
  5820. return true
  5821. },
  5822. excludeSelectors: [
  5823. ...default_default2.excludeSelectors,
  5824. "header",
  5825. '[aria-label="pagination"]',
  5826. 'a[href="/signIn.html"]',
  5827. 'a[href="/register.html"]',
  5828. 'a[href^="/notification"]',
  5829. ".info-last-comment-time",
  5830. ".floor-link",
  5831. ".avatar-wrapper",
  5832. ".select-item",
  5833. ".card-item",
  5834. ".nsk-new-member-board",
  5835. ".hover-user-card .user-stat",
  5836. ".btn",
  5837. ],
  5838. validMediaSelectors: ["svg.iconpark-icon"],
  5839. addExtraMatchedNodes(matchedNodesSet) {
  5840. const isDarkMode = hasClass(doc.body, "dark-layout")
  5841. doc.documentElement.dataset.utags_darkmode = isDarkMode ? "1" : "0"
  5842. let key = getUserProfileUrl(location.href)
  5843. if (key) {
  5844. const element = $("h1.username")
  5845. if (element) {
  5846. const title = element.textContent.trim()
  5847. if (title) {
  5848. const meta = { title, type: "user" }
  5849. element.utags = { key, meta }
  5850. matchedNodesSet.add(element)
  5851. }
  5852. }
  5853. }
  5854. key = getPostUrl(location.href)
  5855. if (key) {
  5856. addVisited(key)
  5857. }
  5858. },
  5859. getStyle: () => nodeseek_com_default,
  5860. }
  5861. })()
  5862. var inoreader_com_default =
  5863. ':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}'
  5864. var inoreader_com_default2 = (() => {
  5865. const prefix3 = location.origin + "/"
  5866. function getArticleUrl(url) {
  5867. if (url.startsWith(prefix3)) {
  5868. const href2 = url.slice(prefix3.length).toLowerCase()
  5869. if (/^article\/\w+(-[^?#]*)?([?#].*)?$/.test(href2)) {
  5870. return prefix3 + href2.replace(/^(article\/\w+)-.*/, "$1")
  5871. }
  5872. }
  5873. return void 0
  5874. }
  5875. return {
  5876. matches: /\w+\.inoreader\.com/,
  5877. listNodesSelectors: [".ar"],
  5878. conditionNodesSelectors: [
  5879. ".article_tile .article_tile_footer_feed_title a",
  5880. ".article_tile a.article_title_link",
  5881. ".article_magazine .article_magazine_feed_title a",
  5882. ".article_magazine a.article_magazine_title_link",
  5883. ".ar .column_view_title a",
  5884. ".ar .article_title_wrapper a",
  5885. ".ar.article_card .article_sub_title a",
  5886. ".ar.article_card a.article_title_link",
  5887. ],
  5888. validate(element) {
  5889. const href = element.href
  5890. if (!href.startsWith(prefix3)) {
  5891. return true
  5892. }
  5893. if (element.closest("#search_content .featured_category")) {
  5894. element.dataset.utags_position_selector = "span"
  5895. }
  5896. const key = getArticleUrl(href)
  5897. if (key) {
  5898. const title = element.textContent.trim()
  5899. if (!title) {
  5900. return false
  5901. }
  5902. const meta = { type: "article", title }
  5903. element.utags = { key, meta }
  5904. element.dataset.utags = element.dataset.utags || ""
  5905. if (element.closest(".search_feed_article")) {
  5906. element.dataset.utags_position_selector = "h6"
  5907. }
  5908. return true
  5909. }
  5910. return true
  5911. },
  5912. excludeSelectors: [
  5913. ...default_default2.excludeSelectors,
  5914. "#side-nav",
  5915. 'a[href^="/preferences"]',
  5916. 'a[href^="/upgrade"]',
  5917. 'a[href^="/login"]',
  5918. 'a[href^="/signup"]',
  5919. 'a[href^="/sign_up"]',
  5920. 'a[href^="/forgot-password"]',
  5921. "#preference-section-content",
  5922. "#preference-section-settings",
  5923. ".inno_tabs_tab",
  5924. ".profile_checklist",
  5925. ".gadget_overview_feed_title",
  5926. ".header_name",
  5927. ],
  5928. addExtraMatchedNodes(matchedNodesSet) {
  5929. const key = getArticleUrl(location.href)
  5930. if (key) {
  5931. const element = $(".article_full_contents div.article_title")
  5932. if (element) {
  5933. const title = element.textContent.trim()
  5934. if (title) {
  5935. const meta = { title, type: "article" }
  5936. element.utags = { key, meta }
  5937. matchedNodesSet.add(element)
  5938. }
  5939. }
  5940. }
  5941. },
  5942. postProcess() {
  5943. const isDarkMode = hasClass(doc.body, "theme_dark")
  5944. doc.documentElement.dataset.utags_darkmode = isDarkMode ? "1" : "0"
  5945. },
  5946. getStyle: () => inoreader_com_default,
  5947. }
  5948. })()
  5949. var zhipin_com_default =
  5950. ':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) .sub-li a.job-info+.utags_ul_1{position:absolute;top:-9999px}:not(#a):not(#b):not(#c) .sub-li .sub-li-bottom a+.utags_ul_1{position:absolute;top:-9999px;margin-top:-2px !important}:not(#a):not(#b):not(#c) .hot-company-wrapper a.company-info-top+.utags_ul_1{position:absolute;top:-9999px;margin-top:-16px !important;width:inherit}:not(#a):not(#b):not(#c) .hot-company-wrapper .company-job-item a.job-info+.utags_ul_1{position:absolute;top:-9999px;margin-top:0px !important;width:inherit}:not(#a):not(#b):not(#c) .job-recommend-result .job-info .job-title a.job-name[data-utags_fit_content="1"]{display:inline-block !important;max-width:fit-content !important}:not(#a):not(#b):not(#c) .job-recommend-result .job-info .job-title a.job-name+.utags_ul_1{position:absolute;top:-9999px;margin-top:-2px !important}:not(#a):not(#b):not(#c) .job-recommend-result .job-card-footer a.boss-info+.utags_ul_1{position:absolute;top:-9999px;margin-top:-2px !important}:not(#a):not(#b):not(#c) .search-job-result .job-card-body a.job-card-left+.utags_ul_1{position:absolute;top:-9999px;margin-top:34px !important}:not(#a):not(#b):not(#c) .search-job-result .job-card-body .job-card-right .company-name{max-width:290px;height:unset}:not(#a):not(#b):not(#c) .company-search a.company-info h4[data-utags_fit_content="1"]{display:inline-block !important;width:fit-content !important}:not(#a):not(#b):not(#c) .company-search a.company-info+.utags_ul_1{position:absolute;top:-9999px;margin-top:34px !important;width:194px}:not(#a):not(#b):not(#c) .company-search a.about-info+.utags_ul_1{position:absolute;top:-9999px;margin-top:-14px !important;width:214px}:not(#a):not(#b):not(#c) .job-banner .info-primary .name[data-utags_fit_content="1"],:not(#a):not(#b):not(#c) .smallbanner .company-info .name[data-utags_fit_content="1"]{display:inline-block !important;width:fit-content !important}:not(#a):not(#b):not(#c) .job-sider .sider-company .company-info a+.utags_ul_1{position:absolute;top:-9999px;margin-top:-2px !important;width:194px}:not(#a):not(#b):not(#c) .job-sider .sider-company [ka=job-detail-brandindustry][data-utags_fit_content="1"]{display:inline-flex !important;max-width:fit-content !important}:not(#a):not(#b):not(#c) .job-sider ul.similar-job-list li>a+.utags_ul_1{position:absolute;top:-9999px;margin-top:0px !important;width:260px}:not(#a):not(#b):not(#c) .job-sider ul.similar-job-list li>a .similar-job-attr{flex-wrap:wrap}:not(#a):not(#b):not(#c) .job-sider ul.similar-job-list li>a .similar-job-attr span.similar-job-company[data-url]+.utags_ul_1{width:100%;order:1}:not(#a):not(#b):not(#c) .job-detail .more-job-section ul.look-job-list{display:flex;flex-wrap:wrap}:not(#a):not(#b):not(#c) .job-detail .more-job-section ul.look-job-list li a{height:unset}:not(#a):not(#b):not(#c) .job-detail .more-job-section ul.look-job-list li a+.utags_ul_1{position:absolute;top:-9999px}:not(#a):not(#b):not(#c) .job-detail .more-job-section ul.look-job-list li .info-company{flex-wrap:wrap}:not(#a):not(#b):not(#c) .job-detail .more-job-section ul.look-job-list li .info-company div[data-url]+.utags_ul_1{width:100%;order:1}:not(#a):not(#b):not(#c) .company-new .company-hotjob a+.utags_ul_1{position:absolute;top:-9999px}:not(#a):not(#b):not(#c) .page-company-position ul.position-job-list .job-title{height:unset;flex-wrap:wrap}:not(#a):not(#b):not(#c) .page-company-position ul.position-job-list .job-title .job-name[data-utags_fit_content="1"]{display:inline-flex !important;max-width:fit-content !important}:not(#a):not(#b):not(#c) .page-company-position ul.position-job-list .job-title .job-name+.utags_ul_1{width:100%;order:1}:not(#a):not(#b):not(#c) .page-company-position ul.similar-job-list{display:flex;flex-wrap:wrap}:not(#a):not(#b):not(#c) .page-company-position ul.similar-job-list .company-info{flex-wrap:wrap}:not(#a):not(#b):not(#c) .page-company-position ul.similar-job-list .company-info a.company-logo+.utags_ul_1{width:100%;order:1}:not(#a):not(#b):not(#c) .job-detail-card{z-index:91}:not(#a):not(#b):not(#c) ul li .sub-li{position:relative}'
  5951. var zhipin_com_default2 = (() => {
  5952. const prefix3 = "https://www.zhipin.com/"
  5953. function getCanonicalUrl2(url) {
  5954. if (url.includes(prefix3)) {
  5955. return url.replace(/[?#].*/, "")
  5956. }
  5957. return url
  5958. }
  5959. function getCompanyUrl(url) {
  5960. if (url.startsWith(prefix3)) {
  5961. const href2 = url.slice(prefix3.length)
  5962. if (/^gongsi\/[\w-~]+\.html/.test(href2)) {
  5963. return prefix3 + href2.replace(/^(gongsi\/[\w-~]+\.html).*/, "$1")
  5964. }
  5965. }
  5966. return void 0
  5967. }
  5968. function getJobDetailUrl(url) {
  5969. if (url.startsWith(prefix3)) {
  5970. const href2 = url.slice(prefix3.length)
  5971. if (/^job_detail\/[\w-~]+\.html/.test(href2)) {
  5972. return prefix3 + href2.replace(/^(job_detail\/[\w-~]+\.html).*/, "$1")
  5973. }
  5974. }
  5975. return void 0
  5976. }
  5977. return {
  5978. matches: /www\.zhipin\.com/,
  5979. listNodesSelectors: [
  5980. ".common-tab-box ul li",
  5981. ".hot-company-wrapper ul li",
  5982. ".hot-company-wrapper ul li .company-job-list li",
  5983. ".job-recommend-result .job-card-wrap",
  5984. ".search-job-result .job-card-wrapper",
  5985. ".history-job-list li",
  5986. ".company-search ul li",
  5987. ".company-hotjob ul li",
  5988. ".page-company-position ul.position-job-list li",
  5989. "ul.similar-job-list li",
  5990. "ul.look-job-list li",
  5991. ],
  5992. conditionNodesSelectors: [
  5993. ".common-tab-box ul li .sub-li a.job-info",
  5994. ".common-tab-box ul li .sub-li-bottom a.user-info",
  5995. ".hot-company-wrapper ul li .company-info-top",
  5996. ".hot-company-wrapper ul li .company-job-list li a.job-info",
  5997. ".job-recommend-result .job-card-wrap .job-info .job-title a.job-name",
  5998. ".job-recommend-result .job-card-wrap .job-card-footer .boss-info",
  5999. ".search-job-result .job-card-wrapper a.job-card-left",
  6000. ".search-job-result .job-card-wrapper .job-card-right .company-name a",
  6001. ".history-job-list li a",
  6002. ".company-search ul li a.company-info",
  6003. ".company-hotjob ul li > a",
  6004. ".page-company-position ul.position-job-list li .job-title .job-name",
  6005. "ul.similar-job-list li a.job-info",
  6006. "ul.similar-job-list li > a",
  6007. "ul.similar-job-list li .company-info a.company-logo",
  6008. "ul.similar-job-list li .similar-job-attr span.similar-job-company[data-url]",
  6009. "ul.look-job-list li > a",
  6010. "ul.look-job-list li .info-company div[data-url]",
  6011. ],
  6012. matchedNodesSelectors: [
  6013. ...default_default2.matchedNodesSelectors,
  6014. ".info-company div[data-url]",
  6015. ".similar-job-list .similar-job-company[data-url]",
  6016. ],
  6017. preProcess() {
  6018. setVisitedAvailable(true)
  6019. for (const element of $$(
  6020. ".info-company div[data-url],.similar-job-list .similar-job-company[data-url]"
  6021. )) {
  6022. if (element.dataset.url) {
  6023. element.href =
  6024. location.origin + element.dataset.url.replace("/job/", "/")
  6025. element.dataset.utags_node_type = "link"
  6026. }
  6027. }
  6028. },
  6029. validate(element) {
  6030. const href = element.href
  6031. if (!href) {
  6032. return false
  6033. }
  6034. if (!href.startsWith(prefix3)) {
  6035. return true
  6036. }
  6037. if (element.closest(".common-tab-box")) {
  6038. element.dataset.utags_ul_type = "ol"
  6039. }
  6040. let key = getCompanyUrl(href)
  6041. if (key) {
  6042. const titleElement = $(
  6043. ".name,.company-info-top h3,.card-desc .title,h4",
  6044. element
  6045. )
  6046. const title = getTrimmedTitle(titleElement || element)
  6047. if (!title) {
  6048. return false
  6049. }
  6050. const meta = { type: "company", title }
  6051. element.utags = { key, meta }
  6052. element.dataset.utags = element.dataset.utags || ""
  6053. if (element.closest(".sub-li-bottom a.user-info")) {
  6054. element.dataset.utags_position_selector = "a > p"
  6055. } else if (element.closest(".company-search a.company-info")) {
  6056. element.dataset.utags_position_selector = "h4"
  6057. }
  6058. return true
  6059. }
  6060. key = getJobDetailUrl(href)
  6061. if (key) {
  6062. const titleElement = $(
  6063. ".job-title .job-name,.job-info-top,.info-primary .name b,.info-job,.similar-job-info,.sub-li-top,a.about-info u.h",
  6064. element
  6065. )
  6066. let title = getTrimmedTitle(titleElement || element)
  6067. if (!title) {
  6068. return false
  6069. }
  6070. title = title.replace(" \u5728\u7EBF ", "")
  6071. const meta = { type: "job-detail", title }
  6072. element.utags = { key, meta }
  6073. element.dataset.utags = element.dataset.utags || ""
  6074. element.dataset.utags_position_selector =
  6075. ".job-title .job-name,.info-primary .name b,.info-job,.similar-job-info,.sub-li-top,a.about-info u.h"
  6076. markElementWhetherVisited(key, element)
  6077. return true
  6078. }
  6079. return true
  6080. },
  6081. excludeSelectors: [
  6082. ...default_default2.excludeSelectors,
  6083. "#header",
  6084. ".look-all",
  6085. ".more-job-btn",
  6086. ".look-more",
  6087. ".all-jobs-hot",
  6088. ".view-more",
  6089. ".link-more",
  6090. "h3:not(.company-name):not(.name)",
  6091. ".compare-btn",
  6092. ".job_pk",
  6093. ".search-hot",
  6094. ".filter-box",
  6095. ".sign-form",
  6096. ".login-card-wrapper",
  6097. ".login-entry-page",
  6098. ".btn",
  6099. ".footer-icon",
  6100. ".company-tab",
  6101. ".school-type-box",
  6102. ".search-condition-wrapper",
  6103. ".filter-select-box",
  6104. 'a[href*="/web/geek/job"]',
  6105. ".page",
  6106. ],
  6107. addExtraMatchedNodes(matchedNodesSet) {
  6108. let key = getCompanyUrl(location.href)
  6109. if (key) {
  6110. const element = $(".company-banner h1")
  6111. if (element) {
  6112. const title = element.childNodes[0].textContent.trim()
  6113. if (title) {
  6114. const meta = { title, type: "company" }
  6115. element.utags = { key, meta }
  6116. matchedNodesSet.add(element)
  6117. }
  6118. }
  6119. }
  6120. key = getJobDetailUrl(location.href)
  6121. if (key) {
  6122. addVisited(key)
  6123. let element = $(".job-banner .info-primary .name")
  6124. if (element) {
  6125. const title = getTrimmedTitle(element)
  6126. if (title) {
  6127. const meta = { title, type: "job-detail" }
  6128. element.utags = { key, meta }
  6129. matchedNodesSet.add(element)
  6130. markElementWhetherVisited(key, element)
  6131. }
  6132. }
  6133. element = $(".smallbanner .company-info .name")
  6134. if (element) {
  6135. const title = getTrimmedTitle(element)
  6136. if (title) {
  6137. const meta = { title, type: "job-detail" }
  6138. element.utags = { key, meta }
  6139. matchedNodesSet.add(element)
  6140. markElementWhetherVisited(key, element)
  6141. }
  6142. }
  6143. }
  6144. },
  6145. postProcess() {
  6146. const isDarkMode = hasClass(doc.body, "theme_dark")
  6147. doc.documentElement.dataset.utags_darkmode = isDarkMode ? "1" : "0"
  6148. },
  6149. getStyle: () => zhipin_com_default,
  6150. getCanonicalUrl: getCanonicalUrl2,
  6151. }
  6152. })()
  6153. var pornhub_com_default =
  6154. ':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:hsla(0,0%,100%,.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:hsla(0,0%,100%,.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}'
  6155. var pornhub_com_default2 = (() => {
  6156. const prefix3 = "https://www.pornhub.com/"
  6157. function getUserProfileUrl(href, exact = false) {
  6158. if (href.includes("pornhub.com")) {
  6159. const index = href.indexOf("pornhub.com") + 12
  6160. const href2 = href.slice(index)
  6161. if (exact) {
  6162. if (/^(model|users)\/[\w-]+(\?.*)?$/.test(href2)) {
  6163. return prefix3 + href2.replace(/(^(model|users)\/[\w-]+).*/, "$1")
  6164. }
  6165. } else if (/^(model|users)\/[\w-]+/.test(href2)) {
  6166. return prefix3 + href2.replace(/(^(model|users)\/[\w-]+).*/, "$1")
  6167. }
  6168. }
  6169. return void 0
  6170. }
  6171. function getChannelUrl(href, exact = false) {
  6172. if (href.includes("pornhub.com")) {
  6173. const index = href.indexOf("pornhub.com") + 12
  6174. const href2 = href.slice(index)
  6175. if (exact) {
  6176. if (/^channels\/[\w-]+(\?.*)?$/.test(href2)) {
  6177. return prefix3 + href2.replace(/(^channels\/[\w-]+).*/, "$1")
  6178. }
  6179. } else if (/^channels\/[\w-]+/.test(href2)) {
  6180. return prefix3 + href2.replace(/(^channels\/[\w-]+).*/, "$1")
  6181. }
  6182. }
  6183. return void 0
  6184. }
  6185. function getVideoUrl(href) {
  6186. if (href.includes("pornhub.com")) {
  6187. const index = href.indexOf("pornhub.com") + 12
  6188. const href2 = href.slice(index)
  6189. if (/^view_video.php\?viewkey=\w+/.test(href2)) {
  6190. return (
  6191. prefix3 + href2.replace(/(view_video.php\?viewkey=\w+).*/, "$1")
  6192. )
  6193. }
  6194. }
  6195. return void 0
  6196. }
  6197. return {
  6198. matches: /pornhub\.com/,
  6199. validate(element) {
  6200. const hrefAttr = getAttribute(element, "href")
  6201. if (!hrefAttr || hrefAttr === "null" || hrefAttr === "#") {
  6202. return false
  6203. }
  6204. const href = element.href
  6205. let key = getChannelUrl(href, true)
  6206. if (key) {
  6207. const meta = { type: "channel" }
  6208. element.utags = { key, meta }
  6209. return true
  6210. }
  6211. key = getUserProfileUrl(href, true)
  6212. if (key) {
  6213. const meta = { type: "user" }
  6214. element.utags = { key, meta }
  6215. return true
  6216. }
  6217. key = getVideoUrl(href)
  6218. if (key) {
  6219. let title
  6220. const titleElement = $("#video-title", element)
  6221. if (titleElement) {
  6222. title = titleElement.textContent
  6223. }
  6224. const meta = title ? { title, type: "video" } : { type: "video" }
  6225. element.utags = { key, meta }
  6226. return true
  6227. }
  6228. return true
  6229. },
  6230. excludeSelectors: [
  6231. ...default_default2.excludeSelectors,
  6232. ".networkBarWrapper",
  6233. "#headerWrapper",
  6234. "#headerMenuContainer",
  6235. "#mainMenuProfile",
  6236. "#mainMenuAmateurModelProfile",
  6237. "#countryRedirectMessage",
  6238. "aside#leftMenu",
  6239. ".profileSubNav",
  6240. ".subFilterList",
  6241. ".greyButton",
  6242. ".orangeButton",
  6243. ],
  6244. addExtraMatchedNodes(matchedNodesSet) {
  6245. let key = getUserProfileUrl(location.href)
  6246. if (key) {
  6247. const element = $(".name h1")
  6248. if (element) {
  6249. const title = element.textContent.trim()
  6250. if (title) {
  6251. const meta = { title, type: "user" }
  6252. element.utags = { key, meta }
  6253. matchedNodesSet.add(element)
  6254. }
  6255. }
  6256. }
  6257. key = getChannelUrl(location.href)
  6258. if (key) {
  6259. const element = $(".title h1")
  6260. if (element && !$("a", element)) {
  6261. const title = element.textContent.trim()
  6262. if (title) {
  6263. const meta = { title, type: "channel" }
  6264. element.utags = { key, meta }
  6265. matchedNodesSet.add(element)
  6266. }
  6267. }
  6268. }
  6269. key = getVideoUrl(location.href)
  6270. if (key) {
  6271. const element = $("h1.title")
  6272. if (element) {
  6273. const title = element.textContent.trim()
  6274. if (title) {
  6275. const meta = { title, type: "video" }
  6276. element.utags = { key, meta }
  6277. matchedNodesSet.add(element)
  6278. }
  6279. }
  6280. }
  6281. },
  6282. getStyle: () => pornhub_com_default,
  6283. }
  6284. })()
  6285. var e_hentai_org_default =
  6286. ":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 )}"
  6287. var e_hentai_org_default2 = (() => {
  6288. const prefix3 = "https://e-hentai.org/"
  6289. const prefix22 = "https://exhentai.org/"
  6290. function getPostUrl(url) {
  6291. if (url.startsWith(prefix3)) {
  6292. const href2 = url.slice(21)
  6293. if (/^g\/\w+/.test(href2)) {
  6294. return prefix3 + href2.replace(/^(g\/\w+\/\w+\/).*/, "$1")
  6295. }
  6296. }
  6297. if (url.startsWith(prefix22)) {
  6298. const href2 = url.slice(21)
  6299. if (/^g\/\w+/.test(href2)) {
  6300. return prefix22 + href2.replace(/^(g\/\w+\/\w+\/).*/, "$1")
  6301. }
  6302. }
  6303. return void 0
  6304. }
  6305. function isImageViewUrl(url) {
  6306. if (url.startsWith(prefix3)) {
  6307. const href2 = url.slice(21)
  6308. return /^s\/\w+/.test(href2)
  6309. }
  6310. if (url.startsWith(prefix22)) {
  6311. const href2 = url.slice(21)
  6312. return /^s\/\w+/.test(href2)
  6313. }
  6314. return false
  6315. }
  6316. return {
  6317. matches: /e-hentai\.org|exhentai\.org/,
  6318. validate(element) {
  6319. if (element.tagName !== "A") {
  6320. return true
  6321. }
  6322. const href = element.href
  6323. if (href && (href.startsWith(prefix3) || href.startsWith(prefix22))) {
  6324. const key = getPostUrl(href)
  6325. if (key) {
  6326. const titleElement = $(".glink", element)
  6327. let title
  6328. if (titleElement) {
  6329. title = titleElement.textContent
  6330. }
  6331. const meta = { type: "post" }
  6332. if (title) {
  6333. meta.title = title
  6334. }
  6335. element.utags = { key, meta }
  6336. return true
  6337. }
  6338. if (isImageViewUrl(href)) {
  6339. return false
  6340. }
  6341. }
  6342. return true
  6343. },
  6344. map(element) {
  6345. const titleElement = $(".gl4e.glname .glink", element)
  6346. if (titleElement) {
  6347. titleElement.utags = element.utags
  6348. titleElement.dataset.utags = titleElement.dataset.utags || ""
  6349. titleElement.dataset.utags_node_type = "link"
  6350. return titleElement
  6351. }
  6352. return void 0
  6353. },
  6354. excludeSelectors: [
  6355. ...default_default2.excludeSelectors,
  6356. "#nb",
  6357. ".searchnav",
  6358. ".gtb",
  6359. 'a[href*="report=select"]',
  6360. 'a[href*="act=expunge"]',
  6361. ],
  6362. addExtraMatchedNodes(matchedNodesSet) {
  6363. const key = getPostUrl(location.href)
  6364. if (key) {
  6365. const element = getFirstHeadElement()
  6366. if (element) {
  6367. const title = element.textContent.trim()
  6368. if (title) {
  6369. const meta = { title, type: "post" }
  6370. element.utags = { key, meta }
  6371. matchedNodesSet.add(element)
  6372. }
  6373. }
  6374. }
  6375. },
  6376. getStyle: () => e_hentai_org_default,
  6377. }
  6378. })()
  6379. var panda_chaika_moe_default =
  6380. ":not(#a):not(#b):not(#c) h5+.utags_ul{display:block !important;margin-top:-4px !important;margin-bottom:6px !important}"
  6381. var panda_chaika_moe_default2 = (() => {
  6382. const prefix3 = "https://panda.chaika.moe/"
  6383. function getPostUrl(url, exact = false) {
  6384. if (url.startsWith(prefix3)) {
  6385. const href2 = url.slice(25)
  6386. if (exact) {
  6387. if (/^archive\/\d+\/(\?.*)?$/.test(href2)) {
  6388. return prefix3 + href2.replace(/^(archive\/\d+\/).*/, "$1")
  6389. }
  6390. } else if (/^archive\/\d+\//.test(href2)) {
  6391. return prefix3 + href2.replace(/^(archive\/\d+\/).*/, "$1")
  6392. }
  6393. }
  6394. return void 0
  6395. }
  6396. return {
  6397. matches: /panda\.chaika\.moe/,
  6398. excludeSelectors: [
  6399. ...default_default2.excludeSelectors,
  6400. ".navbar",
  6401. "th",
  6402. ".pagination",
  6403. ".btn",
  6404. ".caption",
  6405. ],
  6406. addExtraMatchedNodes(matchedNodesSet) {
  6407. const key = getPostUrl(location.href)
  6408. if (key) {
  6409. const element = $("h5")
  6410. if (element) {
  6411. const title = element.textContent.trim()
  6412. if (title) {
  6413. const meta = { title, type: "post" }
  6414. element.utags = { key, meta }
  6415. matchedNodesSet.add(element)
  6416. }
  6417. }
  6418. }
  6419. for (const element of $$(".gallery a.cover")) {
  6420. const key2 = element.href
  6421. const titleElement = $(".cover-title", element)
  6422. if (titleElement) {
  6423. const title = titleElement.textContent
  6424. const meta = { title, type: "post" }
  6425. titleElement.utags = { key: key2, meta }
  6426. titleElement.dataset.utags_node_type = "link"
  6427. matchedNodesSet.add(titleElement)
  6428. }
  6429. }
  6430. for (const element of $$('.td-extended > a[href^="/archive/"]')) {
  6431. const key2 = element.href
  6432. const titleElement = $("h5", element.parentElement.parentElement)
  6433. if (titleElement) {
  6434. const title = titleElement.textContent
  6435. const meta = { title, type: "post" }
  6436. titleElement.utags = { key: key2, meta }
  6437. titleElement.dataset.utags_node_type = "link"
  6438. matchedNodesSet.add(titleElement)
  6439. }
  6440. }
  6441. },
  6442. getStyle: () => panda_chaika_moe_default,
  6443. }
  6444. })()
  6445. var dmm_co_jp_default =
  6446. ":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%}"
  6447. var dmm_co_jp_default2 = (() => {
  6448. const prefix3 = "https://www.dmm.co.jp/"
  6449. function getCanonicalUrl2(url) {
  6450. if (url.startsWith(prefix3)) {
  6451. const href2 = url.slice(prefix3.length)
  6452. if (href2.includes("/=/")) {
  6453. return prefix3 + href2.replace(/\?.*/, "")
  6454. }
  6455. }
  6456. return url
  6457. }
  6458. function getProductUrl(url) {
  6459. if (url.startsWith(prefix3)) {
  6460. const href2 = url.slice(prefix3.length)
  6461. if (href2.includes("/detail/=/cid=")) {
  6462. return prefix3 + href2.replace(/\?.*/, "")
  6463. }
  6464. }
  6465. return void 0
  6466. }
  6467. function getMakerUrl(url) {
  6468. if (url.startsWith(prefix3)) {
  6469. const href2 = url.slice(prefix3.length)
  6470. if (href2.includes("/list/=/article=maker/id=")) {
  6471. return prefix3 + href2.replace(/\?.*/, "")
  6472. }
  6473. }
  6474. return void 0
  6475. }
  6476. return {
  6477. matches: /dmm\.co\.jp/,
  6478. validate(element) {
  6479. const href = element.href
  6480. if (!href.startsWith(prefix3)) {
  6481. return true
  6482. }
  6483. if (href.includes("/=/")) {
  6484. const key = getProductUrl(href)
  6485. if (key) {
  6486. const titleElement = $(
  6487. ".mainListLinkWork__txt,.responsive-name",
  6488. element
  6489. )
  6490. const title = titleElement
  6491. ? getTrimmedTitle(titleElement)
  6492. : getTrimmedTitle(element)
  6493. if (title) {
  6494. const meta = { title, type: "product" }
  6495. element.utags = { key, meta }
  6496. }
  6497. }
  6498. return true
  6499. }
  6500. return false
  6501. },
  6502. excludeSelectors: [
  6503. ...default_default2.excludeSelectors,
  6504. "header",
  6505. ".localNav-list",
  6506. ".m-leftNavigation",
  6507. ".l-areaSideNavColumn",
  6508. ".top-leftcolumn",
  6509. ".top-rightcolumn",
  6510. ".d-btn-xhi-st",
  6511. ".headingTitle__txt--more",
  6512. ".recommendCapt__txt",
  6513. ".circleFanButton__content",
  6514. ".displayFormat",
  6515. ".pageNationList",
  6516. ".nav-text-container",
  6517. ".sub-nav-link",
  6518. ".m-listHeader",
  6519. ".dcd-review__rating_map",
  6520. ".dcd-review_boxpagenation",
  6521. ".sampleButton",
  6522. ".right_navi_link",
  6523. ],
  6524. validMediaSelectors: [
  6525. ".mainList",
  6526. ".pickup .fn-responsiveImg",
  6527. "#l-areaRecommendProduct",
  6528. ],
  6529. addExtraMatchedNodes(matchedNodesSet) {
  6530. let key = getProductUrl(location.href)
  6531. if (key) {
  6532. const element = $("h1.productTitle__txt")
  6533. if (element) {
  6534. const title = element.textContent.trim()
  6535. if (title) {
  6536. const meta = { title }
  6537. element.utags = { key, meta }
  6538. matchedNodesSet.add(element)
  6539. }
  6540. }
  6541. }
  6542. key = getMakerUrl(location.href)
  6543. if (key) {
  6544. const element = $(".circleProfile__name span")
  6545. if (element) {
  6546. const title = element.textContent.trim()
  6547. if (title) {
  6548. const meta = { title }
  6549. element.utags = { key, meta }
  6550. matchedNodesSet.add(element)
  6551. }
  6552. }
  6553. }
  6554. },
  6555. getCanonicalUrl: getCanonicalUrl2,
  6556. getStyle: () => dmm_co_jp_default,
  6557. }
  6558. })()
  6559. var kemono_su_default =
  6560. ":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}"
  6561. var kemono_su_default2 = (() => {
  6562. const prefix3 = location.origin + "/"
  6563. function getPostUrl(url) {
  6564. if (url.startsWith(prefix3)) {
  6565. const href2 = url.slice(prefix3.length)
  6566. if (/^\w+\/user\/\w+\/post\/\w+/.test(href2)) {
  6567. return prefix3 + href2.replace(/^(\w+\/user\/\w+\/post\/\w+).*/, "$1")
  6568. }
  6569. }
  6570. return void 0
  6571. }
  6572. return {
  6573. matches: /kemono\.su|coomer\.su|nekohouse\.su/,
  6574. validate(element) {
  6575. const hrefAttr = getAttribute(element, "href")
  6576. if (hrefAttr.startsWith("#")) {
  6577. return false
  6578. }
  6579. const href = element.href
  6580. if (!href.startsWith(prefix3)) {
  6581. return true
  6582. }
  6583. if (
  6584. hasClass(element, "user-card") ||
  6585. hasClass(element, "user-header__avatar") ||
  6586. element.closest(".post-card")
  6587. ) {
  6588. element.dataset.utags = element.dataset.utags || ""
  6589. }
  6590. return true
  6591. },
  6592. validMediaSelectors: [
  6593. ".user-header .user-header__avatar",
  6594. ".user-header .user-header__profile",
  6595. ".user-card",
  6596. ".post-card__image",
  6597. ".post-card",
  6598. ],
  6599. excludeSelectors: [
  6600. ...default_default2.excludeSelectors,
  6601. ".global-sidebar",
  6602. ".paginator",
  6603. ".post__nav-links",
  6604. ".scrape__nav-links",
  6605. ".tabs",
  6606. ".user-header__actions",
  6607. ".posts-board__sidebar",
  6608. "#add-new-link",
  6609. 'a[href^="/authentication/"]',
  6610. ],
  6611. addExtraMatchedNodes(matchedNodesSet) {
  6612. const key = getPostUrl(location.href)
  6613. if (key) {
  6614. const element = $("h1.post__title,h1.scrape__title")
  6615. if (element) {
  6616. const title = element.textContent.trim()
  6617. if (title) {
  6618. const meta = { title, type: "post" }
  6619. element.utags = { key, meta }
  6620. matchedNodesSet.add(element)
  6621. }
  6622. }
  6623. }
  6624. },
  6625. getStyle: () => kemono_su_default,
  6626. }
  6627. })()
  6628. var rule34video_com_default =
  6629. ":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%}"
  6630. var rule34video_com_default2 = (() => {
  6631. const prefix3 = location.origin + "/"
  6632. function getModelUrl(url) {
  6633. if (url.startsWith(prefix3)) {
  6634. const href2 = url.slice(prefix3.length)
  6635. if (/^models\/[\w-]+/.test(href2)) {
  6636. return prefix3 + href2.replace(/^(models\/[\w-]+).*/, "$1") + "/"
  6637. }
  6638. }
  6639. return void 0
  6640. }
  6641. function getMemberUrl(url) {
  6642. if (url.startsWith(prefix3)) {
  6643. const href2 = url.slice(prefix3.length)
  6644. if (/^members\/\d+/.test(href2)) {
  6645. return prefix3 + href2.replace(/^(members\/\d+).*/, "$1") + "/"
  6646. }
  6647. }
  6648. return void 0
  6649. }
  6650. function getCategoryUrl(url) {
  6651. if (url.startsWith(prefix3)) {
  6652. const href2 = url.slice(prefix3.length)
  6653. if (/^categories\/[\w-]+/.test(href2)) {
  6654. return prefix3 + href2.replace(/^(categories\/[\w-]+).*/, "$1") + "/"
  6655. }
  6656. }
  6657. return void 0
  6658. }
  6659. function getVideoUrl(url) {
  6660. if (url.startsWith(prefix3)) {
  6661. const href2 = url.slice(prefix3.length)
  6662. if (/^video\/\d+(\/[\w-]+)?/.test(href2)) {
  6663. return (
  6664. prefix3 + href2.replace(/^(video\/\d+(\/[\w-]+)?).*/, "$1") + "/"
  6665. )
  6666. }
  6667. }
  6668. return void 0
  6669. }
  6670. return {
  6671. matches: /rule34video\.com|rule34gen\.com/,
  6672. listNodesSelectors: [
  6673. //
  6674. ".list-comments .item",
  6675. ".thumbs .item",
  6676. ],
  6677. conditionNodesSelectors: [
  6678. //
  6679. ".list-comments .item .comment-info .inner a",
  6680. ".thumbs .item a.th",
  6681. ],
  6682. validate(element) {
  6683. const href = element.href
  6684. if (!href.startsWith(prefix3)) {
  6685. if ($("header", element.parentElement)) {
  6686. const key2 = href.replace(/(https?:\/\/[^/]+\/).*/, "$1")
  6687. const meta = { type: "AD", title: "AD" }
  6688. element.utags = { key: key2, meta }
  6689. element.dataset.utags = element.dataset.utags || ""
  6690. }
  6691. return true
  6692. }
  6693. const key = getVideoUrl(href)
  6694. if (key) {
  6695. const titleElement = $(".thumb_title", element)
  6696. const title = titleElement
  6697. ? titleElement.textContent.trim()
  6698. : element.textContent.trim()
  6699. if (!title) {
  6700. return false
  6701. }
  6702. const meta = { type: "video", title }
  6703. element.utags = { key, meta }
  6704. element.dataset.utags = element.dataset.utags || ""
  6705. return true
  6706. }
  6707. element.dataset.utags = element.dataset.utags || ""
  6708. return true
  6709. },
  6710. excludeSelectors: [
  6711. ...default_default2.excludeSelectors,
  6712. ".header",
  6713. ".btn_more",
  6714. ".tabs-menu",
  6715. ".pagination",
  6716. ".headline",
  6717. ".prev",
  6718. ".next",
  6719. ".btn",
  6720. ".all",
  6721. ".tag_item_suggest",
  6722. 'a[href*="download"]',
  6723. ".list-comments .wrap_image",
  6724. ],
  6725. addExtraMatchedNodes(matchedNodesSet) {
  6726. let key = getModelUrl(location.href)
  6727. if (key) {
  6728. const element = $(".brand_inform .title")
  6729. if (element) {
  6730. const title = element.textContent.trim()
  6731. if (title) {
  6732. const meta = { title, type: "model" }
  6733. element.utags = { key, meta }
  6734. matchedNodesSet.add(element)
  6735. }
  6736. }
  6737. }
  6738. key = getMemberUrl(location.href)
  6739. if (key) {
  6740. const element = $(".channel_logo .title")
  6741. if (element) {
  6742. const title = element.textContent.trim()
  6743. if (title) {
  6744. const meta = { title, type: "user" }
  6745. element.utags = { key, meta }
  6746. matchedNodesSet.add(element)
  6747. }
  6748. }
  6749. }
  6750. key = getCategoryUrl(location.href)
  6751. if (key) {
  6752. const element = $(".brand_inform .title")
  6753. if (element) {
  6754. const title = element.textContent.trim()
  6755. if (title) {
  6756. const meta = { title, type: "category" }
  6757. element.utags = { key, meta }
  6758. matchedNodesSet.add(element)
  6759. }
  6760. }
  6761. }
  6762. key = getVideoUrl(location.href)
  6763. if (key) {
  6764. const element = $("h1.title_video")
  6765. if (element) {
  6766. const title = element.textContent.trim()
  6767. if (title) {
  6768. const meta = { title, type: "video" }
  6769. element.utags = { key, meta }
  6770. matchedNodesSet.add(element)
  6771. }
  6772. }
  6773. }
  6774. },
  6775. getStyle: () => rule34video_com_default,
  6776. }
  6777. })()
  6778. var sites = [
  6779. github_com_default2,
  6780. v2ex_default2,
  6781. twitter_com_default2,
  6782. reddit_com_default2,
  6783. greasyfork_org_default2,
  6784. news_ycombinator_com_default,
  6785. lobste_rs_default,
  6786. mp_weixin_qq_com_default,
  6787. instagram_com_default2,
  6788. threads_net_default2,
  6789. facebook_com_default2,
  6790. youtube_com_default2,
  6791. bilibili_com_default2,
  6792. tiktok_com_default2,
  6793. pojie_cn_default2,
  6794. juejin_cn_default,
  6795. zhihu_com_default,
  6796. xiaohongshu_com_default2,
  6797. weibo_com_default,
  6798. sspai_com_default2,
  6799. douyin_com_default2,
  6800. podcasts_google_com_default2,
  6801. rebang_today_default2,
  6802. myanimelist_net_default2,
  6803. douban_com_default,
  6804. pixiv_net_default2,
  6805. discourse_default2,
  6806. nga_cn_default2,
  6807. keylol_com_default2,
  6808. tampermonkey_net_cn_default2,
  6809. flarum_default2,
  6810. nodeseek_com_default2,
  6811. inoreader_com_default2,
  6812. zhipin_com_default2,
  6813. pornhub_com_default2,
  6814. e_hentai_org_default2,
  6815. panda_chaika_moe_default2,
  6816. dlsite_com_default2,
  6817. dmm_co_jp_default2,
  6818. kemono_su_default2,
  6819. rule34video_com_default2,
  6820. ]
  6821. var getCanonicalUrlFunctionList = [default_default2, ...sites]
  6822. .map((site) => site.getCanonicalUrl)
  6823. .filter((v) => typeof v === "function")
  6824. function matchedSite(hostname2) {
  6825. for (const s of sites) {
  6826. if (s.matches.test(hostname2)) {
  6827. return s
  6828. }
  6829. }
  6830. if (false) {
  6831. return siteForExtensions(hostname2)
  6832. }
  6833. return default_default2
  6834. }
  6835. function joinSelectors(selectors) {
  6836. return selectors ? selectors.join(",") : void 0
  6837. }
  6838. var hostname = location.hostname
  6839. var currentSite = matchedSite(hostname)
  6840. var listNodesSelector = joinSelectors(currentSite.listNodesSelectors)
  6841. var conditionNodesSelector = joinSelectors(
  6842. currentSite.conditionNodesSelectors
  6843. )
  6844. var matchedNodesSelector = joinSelectors(
  6845. currentSite.matchedNodesSelectors ||
  6846. (currentSite.matches ? default_default2.matchedNodesSelectors : void 0)
  6847. )
  6848. var excludeSelector = joinSelectors(currentSite.excludeSelectors)
  6849. var validMediaSelector = joinSelectors(currentSite.validMediaSelectors)
  6850. var validateFunction = currentSite.validate || default_default2.validate
  6851. var mappingFunction =
  6852. typeof currentSite.map === "function" ? currentSite.map : void 0
  6853. function getListNodes() {
  6854. if (typeof currentSite.preProcess === "function") {
  6855. currentSite.preProcess()
  6856. }
  6857. if (typeof currentSite.getStyle === "function" && !$("#utags_site_style")) {
  6858. const styleText = currentSite.getStyle()
  6859. if (styleText) {
  6860. addElement2("style", {
  6861. textContent: styleText,
  6862. id: "utags_site_style",
  6863. })
  6864. }
  6865. }
  6866. return listNodesSelector ? $$(listNodesSelector) : []
  6867. }
  6868. function getConditionNodes() {
  6869. return conditionNodesSelector ? $$(conditionNodesSelector) : []
  6870. }
  6871. function getCanonicalUrl(url) {
  6872. if (!url) {
  6873. return void 0
  6874. }
  6875. for (const getCanonicalUrlFunc of getCanonicalUrlFunctionList) {
  6876. if (getCanonicalUrlFunc) {
  6877. url = getCanonicalUrlFunc(url)
  6878. }
  6879. }
  6880. return url
  6881. }
  6882. var preValidate = (element) => {
  6883. if (!element) {
  6884. return false
  6885. }
  6886. if (element.tagName === "A") {
  6887. let href = getAttribute(element, "href")
  6888. if (!href) {
  6889. return false
  6890. }
  6891. href = href.trim()
  6892. if (href.length === 0 || href === "#") {
  6893. return false
  6894. }
  6895. const protocol = element.protocol
  6896. if (protocol !== "http:" && protocol !== "https:") {
  6897. return false
  6898. }
  6899. }
  6900. if (
  6901. element.closest(
  6902. ".utags_text_tag,.browser_extension_settings_container,a a"
  6903. )
  6904. ) {
  6905. return false
  6906. }
  6907. return true
  6908. }
  6909. var isValidUtagsElement = (element) => {
  6910. if (element.dataset.utags !== void 0) {
  6911. return true
  6912. }
  6913. if (!element.textContent) {
  6914. return false
  6915. }
  6916. if (!element.textContent.trim()) {
  6917. return false
  6918. }
  6919. const media = $(
  6920. 'img,svg,audio,video,button,.icon,[style*="background-image"]',
  6921. element
  6922. )
  6923. if (media) {
  6924. if (!validMediaSelector) {
  6925. return false
  6926. }
  6927. if (!media.closest(validMediaSelector)) {
  6928. return false
  6929. }
  6930. }
  6931. return true
  6932. }
  6933. var isExcludedUtagsElement = (element) => {
  6934. return excludeSelector ? Boolean(element.closest(excludeSelector)) : false
  6935. }
  6936. var addMatchedNodes = (matchedNodesSet) => {
  6937. if (!matchedNodesSelector) {
  6938. return
  6939. }
  6940. const elements = $$(matchedNodesSelector)
  6941. if (elements.length === 0) {
  6942. return
  6943. }
  6944. const process2 = (element) => {
  6945. var _a
  6946. if (!preValidate(element) || !validateFunction(element)) {
  6947. delete element.utags
  6948. return
  6949. }
  6950. if (mappingFunction) {
  6951. const newElement = mappingFunction(element)
  6952. if (newElement && newElement !== element) {
  6953. process2(newElement)
  6954. return
  6955. }
  6956. }
  6957. if (isExcludedUtagsElement(element) || !isValidUtagsElement(element)) {
  6958. delete element.utags
  6959. return
  6960. }
  6961. const utags = element.utags || {}
  6962. const key = utags.key || getCanonicalUrl(element.href)
  6963. if (!key) {
  6964. return
  6965. }
  6966. const title = getTrimmedTitle(element)
  6967. const meta = {}
  6968. if (title && !isUrl(title)) {
  6969. meta.title = title
  6970. }
  6971. if ((_a = utags.meta) == null ? void 0 : _a.title) {
  6972. utags.meta.title = trimTitle(utags.meta.title)
  6973. }
  6974. element.utags = {
  6975. key,
  6976. meta: utags.meta ? Object.assign(meta, utags.meta) : meta,
  6977. }
  6978. matchedNodesSet.add(element)
  6979. }
  6980. for (const element of elements) {
  6981. try {
  6982. process2(element)
  6983. } catch (error) {
  6984. console.error(error)
  6985. }
  6986. }
  6987. }
  6988. function matchedNodes() {
  6989. const matchedNodesSet = /* @__PURE__ */ new Set()
  6990. addMatchedNodes(matchedNodesSet)
  6991. if (typeof currentSite.addExtraMatchedNodes === "function") {
  6992. currentSite.addExtraMatchedNodes(matchedNodesSet)
  6993. }
  6994. if (typeof currentSite.postProcess === "function") {
  6995. currentSite.postProcess()
  6996. }
  6997. return [...matchedNodesSet]
  6998. }
  6999. var config = {
  7000. run_at: "document_start",
  7001. matches: ["https://*/*"],
  7002. all_frames: false,
  7003. }
  7004. var emojiTags2
  7005. var host2 = location.host
  7006. var isEnabledByDefault = () => {
  7007. if (host2.includes("www.bilibili.com")) {
  7008. return false
  7009. }
  7010. return true
  7011. }
  7012. var isTagManager = location.href.includes("utags.pipecraft.net/tags/")
  7013. var groupNumber = 1
  7014. var settingsTable2 = {
  7015. ["enableCurrentSite_".concat(host2)]: {
  7016. title: i2("settings.enableCurrentSite"),
  7017. defaultValue: isEnabledByDefault(),
  7018. },
  7019. showHidedItems: {
  7020. title: i2("settings.showHidedItems"),
  7021. defaultValue: false,
  7022. group: ++groupNumber,
  7023. },
  7024. noOpacityEffect: {
  7025. title: i2("settings.noOpacityEffect"),
  7026. defaultValue: false,
  7027. group: groupNumber,
  7028. },
  7029. ["useVisitedFunction_".concat(host2)]: {
  7030. title: i2("settings.useVisitedFunction"),
  7031. defaultValue: false,
  7032. group: ++groupNumber,
  7033. },
  7034. ["displayEffectOfTheVisitedContent_".concat(host2)]: {
  7035. title: i2("settings.displayEffectOfTheVisitedContent"),
  7036. type: "select",
  7037. defaultValue: "2",
  7038. options: {
  7039. [i2("settings.displayEffectOfTheVisitedContent.recordingonly")]: "0",
  7040. [i2("settings.displayEffectOfTheVisitedContent.showtagonly")]: "1",
  7041. [i2("settings.displayEffectOfTheVisitedContent.changecolor")]: "4",
  7042. [i2("settings.displayEffectOfTheVisitedContent.translucent")]: "2",
  7043. [i2("settings.displayEffectOfTheVisitedContent.hide")]: "3",
  7044. },
  7045. group: groupNumber,
  7046. },
  7047. pinnedTagsTitle: {
  7048. title: i2("settings.pinnedTags"),
  7049. type: "action",
  7050. async onclick() {
  7051. const input = $('textarea[data-key="pinnedTags"]')
  7052. if (input) {
  7053. input.scrollIntoView({ block: "start" })
  7054. input.selectionStart = input.value.length
  7055. input.selectionEnd = input.value.length
  7056. input.focus()
  7057. }
  7058. },
  7059. group: ++groupNumber,
  7060. },
  7061. pinnedTags: {
  7062. title: i2("settings.pinnedTags"),
  7063. defaultValue: i2("settings.pinnedTagsDefaultValue"),
  7064. placeholder: i2("settings.pinnedTagsPlaceholder"),
  7065. type: "textarea",
  7066. group: groupNumber,
  7067. },
  7068. emojiTagsTitle: {
  7069. title: i2("settings.emojiTags"),
  7070. type: "action",
  7071. async onclick() {
  7072. const input = $('textarea[data-key="emojiTags"]')
  7073. if (input) {
  7074. input.scrollIntoView({ block: "start" })
  7075. input.selectionStart = input.value.length
  7076. input.selectionEnd = input.value.length
  7077. input.focus()
  7078. }
  7079. },
  7080. group: groupNumber,
  7081. },
  7082. emojiTags: {
  7083. title: i2("settings.emojiTags"),
  7084. defaultValue:
  7085. "\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",
  7086. placeholder: "\u{1F44D}, \u{1F44E}",
  7087. type: "textarea",
  7088. group: groupNumber,
  7089. },
  7090. customStyle: {
  7091. title: i2("settings.customStyle"),
  7092. defaultValue: false,
  7093. group: ++groupNumber,
  7094. },
  7095. customStyleValue: {
  7096. title: "Custom style value",
  7097. defaultValue: i2("settings.customStyleDefaultValue"),
  7098. placeholder: i2("settings.customStyleDefaultValue"),
  7099. type: "textarea",
  7100. group: groupNumber,
  7101. },
  7102. customStyleTip: {
  7103. title: i2("settings.customStyleExamples"),
  7104. type: "tip",
  7105. tipContent: i2("settings.customStyleExamplesContent"),
  7106. group: groupNumber,
  7107. },
  7108. ["customStyle_".concat(host2)]: {
  7109. title: i2("settings.customStyleCurrentSite"),
  7110. defaultValue: false,
  7111. group: ++groupNumber,
  7112. },
  7113. ["customStyleValue_".concat(host2)]: {
  7114. title: "Custom style value",
  7115. defaultValue: "",
  7116. placeholder: i2("settings.customStyleDefaultValue"),
  7117. type: "textarea",
  7118. group: groupNumber,
  7119. },
  7120. useSimplePrompt: {
  7121. title: i2("settings.useSimplePrompt"),
  7122. defaultValue: false,
  7123. group: ++groupNumber,
  7124. },
  7125. openTagsPage: {
  7126. title: i2("settings.openTagsPage"),
  7127. type: "externalLink",
  7128. url: "https://utags.pipecraft.net/tags/",
  7129. group: ++groupNumber,
  7130. },
  7131. openDataPage: {
  7132. title: i2("settings.openDataPage"),
  7133. type: "externalLink",
  7134. url: "https://utags.pipecraft.net/data/",
  7135. group: groupNumber,
  7136. },
  7137. }
  7138. var addUtagsStyle = () => {
  7139. const style = addStyle(content_default)
  7140. style.id = "utags_style"
  7141. }
  7142. function updateCustomStyle() {
  7143. const customStyleValue = getSettingsValue("customStyleValue") || ""
  7144. if (getSettingsValue("customStyle") && customStyleValue) {
  7145. if ($("#utags_custom_style")) {
  7146. $("#utags_custom_style").textContent = customStyleValue
  7147. } else {
  7148. addElement2("style", {
  7149. id: "utags_custom_style",
  7150. textContent: customStyleValue,
  7151. })
  7152. if ($("#utags_custom_style_2")) {
  7153. $("#utags_custom_style_2").remove()
  7154. }
  7155. }
  7156. } else if ($("#utags_custom_style")) {
  7157. $("#utags_custom_style").remove()
  7158. }
  7159. const customStyleValue2 =
  7160. getSettingsValue("customStyleValue_".concat(host2)) || ""
  7161. if (getSettingsValue("customStyle_".concat(host2)) && customStyleValue2) {
  7162. if ($("#utags_custom_style_2")) {
  7163. $("#utags_custom_style_2").textContent = customStyleValue2
  7164. } else {
  7165. addElement2("style", {
  7166. id: "utags_custom_style_2",
  7167. textContent: customStyleValue2,
  7168. })
  7169. }
  7170. } else if ($("#utags_custom_style_2")) {
  7171. $("#utags_custom_style_2").remove()
  7172. }
  7173. }
  7174. function onSettingsChange2() {
  7175. if (getSettingsValue("showHidedItems")) {
  7176. addClass(doc.documentElement, "utags_no_hide")
  7177. } else {
  7178. removeClass(doc.documentElement, "utags_no_hide")
  7179. }
  7180. if (getSettingsValue("noOpacityEffect")) {
  7181. addClass(doc.documentElement, "utags_no_opacity_effect")
  7182. } else {
  7183. removeClass(doc.documentElement, "utags_no_opacity_effect")
  7184. }
  7185. doc.documentElement.dataset.utags_displayEffectOfTheVisitedContent =
  7186. getSettingsValue("displayEffectOfTheVisitedContent_".concat(host2))
  7187. if (getSettingsValue("enableCurrentSite_".concat(host2))) {
  7188. doc.documentElement.dataset.utags = "".concat(host2)
  7189. displayTagsThrottled()
  7190. updateCustomStyle()
  7191. } else {
  7192. doc.documentElement.dataset.utags = "off"
  7193. if ($("#utags_custom_style")) {
  7194. $("#utags_custom_style").remove()
  7195. }
  7196. if ($("#utags_custom_style_2")) {
  7197. $("#utags_custom_style_2").remove()
  7198. }
  7199. if ($("#utags_site_style")) {
  7200. $("#utags_site_style").remove()
  7201. }
  7202. }
  7203. }
  7204. var start = 0
  7205. if (start) {
  7206. start = Date.now()
  7207. }
  7208. function appendTagsToPage(element, key, tags, meta) {
  7209. const utagsUl = element.nextSibling
  7210. if (hasClass(utagsUl, "utags_ul")) {
  7211. if (
  7212. element.dataset.utags === tags.join(",") &&
  7213. key === getAttribute(utagsUl, "data-utags_key")
  7214. ) {
  7215. return
  7216. }
  7217. utagsUl.remove()
  7218. }
  7219. const tagName = element.dataset.utags_ul_type === "ol" ? "ol" : "ul"
  7220. const ul = createElement(tagName, {
  7221. class: tags.length === 0 ? "utags_ul utags_ul_0" : "utags_ul utags_ul_1",
  7222. "data-utags_key": key,
  7223. })
  7224. let li = createElement("li")
  7225. const a = createElement("button", {
  7226. type: "button",
  7227. title: "Add tags",
  7228. "data-utags_tag": "\u{1F3F7}\uFE0F",
  7229. "data-utags_key": key,
  7230. "data-utags_tags": tags.join(", "),
  7231. "data-utags_meta": meta ? JSON.stringify(meta) : "",
  7232. class:
  7233. tags.length === 0
  7234. ? "utags_text_tag utags_captain_tag"
  7235. : "utags_text_tag utags_captain_tag2",
  7236. })
  7237. const svg =
  7238. '<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'
  7239. a.innerHTML = createHTML(svg)
  7240. li.append(a)
  7241. ul.append(li)
  7242. for (const tag of tags) {
  7243. li = createElement("li")
  7244. const a2 = createTag(tag, {
  7245. isEmoji: emojiTags2.includes(tag),
  7246. noLink: isTagManager,
  7247. enableSelect: isTagManager,
  7248. })
  7249. li.append(a2)
  7250. ul.append(li)
  7251. }
  7252. element.after(ul)
  7253. element.dataset.utags = tags.join(",")
  7254. setTimeout(() => {
  7255. const style = getComputedStyle(element)
  7256. const zIndex = style.zIndex
  7257. if (zIndex && zIndex !== "auto") {
  7258. setStyle(ul, { zIndex })
  7259. }
  7260. }, 200)
  7261. }
  7262. function cleanUnusedUtags() {
  7263. const utagsUlList = $$(".utags_ul,ul[data-utags_key],ol[data-utags_key]")
  7264. for (const utagsUl of utagsUlList) {
  7265. const element = utagsUl.previousSibling
  7266. if (element && getAttribute(element, "data-utags") !== null) {
  7267. continue
  7268. }
  7269. utagsUl.remove()
  7270. }
  7271. }
  7272. async function displayTags() {
  7273. if (start) {
  7274. console.error("start of displayTags", Date.now() - start)
  7275. }
  7276. emojiTags2 = await getEmojiTags()
  7277. const listNodes = getListNodes()
  7278. for (const node of listNodes) {
  7279. node.dataset.utags_list_node = ""
  7280. }
  7281. if (start) {
  7282. console.error("before matchedNodes", Date.now() - start)
  7283. }
  7284. const nodes = matchedNodes()
  7285. if (start) {
  7286. console.error("after matchedNodes", Date.now() - start, nodes.length)
  7287. }
  7288. await getCachedUrlMap()
  7289. for (const node of nodes) {
  7290. const utags = node.utags
  7291. if (!utags) {
  7292. continue
  7293. }
  7294. const key = utags.key
  7295. if (!key) {
  7296. continue
  7297. }
  7298. const object = getTags(key)
  7299. const tags = (object.tags || []).slice()
  7300. if (node.dataset.utags_visited === "1") {
  7301. tags.push(TAG_VISITED)
  7302. }
  7303. appendTagsToPage(node, key, tags, utags.meta)
  7304. setTimeout(() => {
  7305. updateTagPosition(node)
  7306. })
  7307. }
  7308. if (start) {
  7309. console.error("after appendTagsToPage", Date.now() - start)
  7310. }
  7311. const conditionNodes = getConditionNodes()
  7312. for (const node of conditionNodes) {
  7313. if (getAttribute(node, "data-utags") !== null) {
  7314. node.dataset.utags_condition_node = ""
  7315. }
  7316. }
  7317. for (const node of listNodes) {
  7318. const conditionNodes2 = $$("[data-utags_condition_node]", node)
  7319. const tagsArray = []
  7320. for (const node2 of conditionNodes2) {
  7321. if (!node2.dataset.utags) {
  7322. continue
  7323. }
  7324. if (node2.closest("[data-utags_list_node]") !== node) {
  7325. continue
  7326. }
  7327. tagsArray.push(node2.dataset.utags)
  7328. }
  7329. if (tagsArray.length === 1) {
  7330. node.dataset.utags_list_node = "," + tagsArray[0] + ","
  7331. } else if (tagsArray.length > 1) {
  7332. node.dataset.utags_list_node =
  7333. "," + uniq(tagsArray.join(",").split(",")).join(",") + ","
  7334. }
  7335. }
  7336. cleanUnusedUtags()
  7337. if (start) {
  7338. console.error("end of displayTags", Date.now() - start)
  7339. }
  7340. }
  7341. var displayTagsThrottled = throttle(displayTags, 500)
  7342. async function initStorage() {
  7343. await migration()
  7344. addTagsValueChangeListener(() => {
  7345. if (!doc.hidden) {
  7346. setTimeout(displayTags)
  7347. }
  7348. })
  7349. }
  7350. var validNodeNames = {
  7351. A: true,
  7352. H1: true,
  7353. H2: true,
  7354. H3: true,
  7355. H4: true,
  7356. H5: true,
  7357. H6: true,
  7358. DIV: true,
  7359. SPAN: true,
  7360. P: true,
  7361. UL: true,
  7362. OL: true,
  7363. LI: true,
  7364. SECTION: true,
  7365. }
  7366. function shouldUpdateUtagsWhenNodeUpdated(nodeList) {
  7367. const length = nodeList.length
  7368. for (let i3 = 0; i3 < length; i3++) {
  7369. const node = nodeList[i3]
  7370. if (
  7371. validNodeNames[node.nodeName] &&
  7372. !hasClass(node, "utags_ul") &&
  7373. !hasClass(node, "utags_modal")
  7374. ) {
  7375. return true
  7376. }
  7377. }
  7378. return false
  7379. }
  7380. function getOutermostOffsetParent(element1, element2) {
  7381. if (
  7382. !(element1 instanceof HTMLElement) ||
  7383. !(element2 instanceof HTMLElement)
  7384. ) {
  7385. throw new TypeError("Both arguments must be valid HTMLElements.")
  7386. }
  7387. const offsetParent1 = element1.offsetParent
  7388. const offsetParent2 = element2.offsetParent
  7389. if (offsetParent1 && offsetParent2) {
  7390. if (offsetParent1.contains(offsetParent2)) {
  7391. return offsetParent1
  7392. }
  7393. if (offsetParent2.contains(offsetParent1)) {
  7394. return offsetParent2
  7395. }
  7396. return void 0
  7397. }
  7398. return offsetParent1 || offsetParent2
  7399. }
  7400. function getMaxOffsetLeft(offsetParent, utags, utagsSizeFix) {
  7401. let maxOffsetRight
  7402. if (offsetParent && offsetParent.offsetWidth > 0) {
  7403. if (offsetParent === utags.offsetParent) {
  7404. maxOffsetRight = offsetParent.offsetWidth
  7405. } else {
  7406. maxOffsetRight =
  7407. offsetParent.offsetWidth -
  7408. getOffsetPosition(utags.offsetParent, offsetParent).left
  7409. }
  7410. } else {
  7411. maxOffsetRight =
  7412. document.body.offsetWidth -
  7413. getOffsetPosition(utags.offsetParent).left -
  7414. 2
  7415. }
  7416. return maxOffsetRight - utags.clientWidth - utagsSizeFix
  7417. }
  7418. function updateTagPosition(element) {
  7419. const utags = element.nextElementSibling
  7420. if (!utags || !hasClass(utags, "utags_ul")) {
  7421. return
  7422. }
  7423. if (!utags.offsetParent && !utags.offsetHeight && !utags.offsetWidth) {
  7424. return
  7425. }
  7426. const style = getComputedStyle(utags)
  7427. if (style.position !== "absolute") {
  7428. return
  7429. }
  7430. if (element.dataset.utags_position_selector) {
  7431. element =
  7432. $(element.dataset.utags_position_selector, element) ||
  7433. element.closest(element.dataset.utags_position_selector) ||
  7434. element
  7435. }
  7436. element.dataset.utags_fit_content = "1"
  7437. const utagsSizeFix = hasClass(utags, "utags_ul_0") ? 22 : 0
  7438. const offsetParent =
  7439. element.offsetParent === utags.offsetParent
  7440. ? element.offsetParent
  7441. : getOutermostOffsetParent(element, utags)
  7442. const offset = getOffsetPosition(element, offsetParent || doc.body)
  7443. if (offsetParent !== utags.offsetParent) {
  7444. const offset2 = getOffsetPosition(
  7445. utags.offsetParent,
  7446. offsetParent || doc.body
  7447. )
  7448. offset.top -= offset2.top
  7449. offset.left -= offset2.left
  7450. }
  7451. if (!element.offsetWidth && !element.clientWidth) {
  7452. return
  7453. }
  7454. const objectPosition = style.objectPosition
  7455. switch (objectPosition) {
  7456. case "-100% 50%": {
  7457. utags.style.left =
  7458. Math.max(offset.left - utags.clientWidth - utagsSizeFix, 0) + "px"
  7459. utags.style.top =
  7460. offset.top +
  7461. ((element.clientHeight || element.offsetHeight) -
  7462. utags.clientHeight -
  7463. utagsSizeFix) /
  7464. 2 +
  7465. "px"
  7466. break
  7467. }
  7468. case "0% -100%": {
  7469. utags.style.left = offset.left + "px"
  7470. utags.style.top = offset.top - utags.clientHeight - utagsSizeFix + "px"
  7471. break
  7472. }
  7473. case "0% 0%": {
  7474. utags.style.left = offset.left + "px"
  7475. utags.style.top = offset.top + "px"
  7476. break
  7477. }
  7478. case "0% 100%": {
  7479. utags.style.left = offset.left + "px"
  7480. utags.style.top =
  7481. offset.top +
  7482. (element.clientHeight || element.offsetHeight) -
  7483. utags.clientHeight -
  7484. utagsSizeFix +
  7485. "px"
  7486. break
  7487. }
  7488. case "0% 200%": {
  7489. utags.style.left = offset.left + "px"
  7490. utags.style.top =
  7491. offset.top + (element.clientHeight || element.offsetHeight) + "px"
  7492. break
  7493. }
  7494. case "100% -100%": {
  7495. utags.style.left =
  7496. offset.left +
  7497. (element.clientWidth || element.offsetWidth) -
  7498. utags.clientWidth -
  7499. utagsSizeFix +
  7500. "px"
  7501. utags.style.top = offset.top - utags.clientHeight - utagsSizeFix + "px"
  7502. break
  7503. }
  7504. case "100% 0%": {
  7505. let offsetLeft =
  7506. (element.clientWidth || element.offsetWidth) -
  7507. utags.clientWidth -
  7508. utagsSizeFix
  7509. if (offsetLeft < 100) {
  7510. offsetLeft = element.clientWidth || element.offsetWidth
  7511. }
  7512. utags.style.left =
  7513. Math.min(
  7514. offset.left + offsetLeft,
  7515. getMaxOffsetLeft(offsetParent, utags, utagsSizeFix)
  7516. ) + "px"
  7517. utags.style.top = offset.top + "px"
  7518. break
  7519. }
  7520. case "100% 50%": {
  7521. let offsetLeft =
  7522. (element.clientWidth || element.offsetWidth) -
  7523. utags.clientWidth -
  7524. utagsSizeFix
  7525. if (offsetLeft < 100) {
  7526. offsetLeft = element.clientWidth || element.offsetWidth
  7527. }
  7528. utags.style.left =
  7529. Math.min(
  7530. offset.left + offsetLeft,
  7531. getMaxOffsetLeft(offsetParent, utags, utagsSizeFix)
  7532. ) + "px"
  7533. utags.style.top =
  7534. offset.top +
  7535. ((element.clientHeight || element.offsetHeight) -
  7536. utags.clientHeight -
  7537. utagsSizeFix) /
  7538. 2 +
  7539. "px"
  7540. break
  7541. }
  7542. case "100% 100%": {
  7543. let offsetLeft =
  7544. (element.clientWidth || element.offsetWidth) -
  7545. utags.clientWidth -
  7546. utagsSizeFix
  7547. if (offsetLeft < 100) {
  7548. offsetLeft = element.clientWidth || element.offsetWidth
  7549. }
  7550. utags.style.left =
  7551. Math.min(
  7552. offset.left + offsetLeft,
  7553. getMaxOffsetLeft(offsetParent, utags, utagsSizeFix)
  7554. ) + "px"
  7555. utags.style.top =
  7556. offset.top +
  7557. (element.clientHeight || element.offsetHeight) -
  7558. utags.clientHeight -
  7559. utagsSizeFix +
  7560. "px"
  7561. break
  7562. }
  7563. case "100% 200%": {
  7564. utags.style.left =
  7565. offset.left +
  7566. (element.clientWidth || element.offsetWidth) -
  7567. utags.clientWidth -
  7568. utagsSizeFix +
  7569. "px"
  7570. utags.style.top =
  7571. offset.top + (element.clientHeight || element.offsetHeight) + "px"
  7572. break
  7573. }
  7574. case "200% 0%": {
  7575. utags.style.left =
  7576. Math.min(
  7577. offset.left + (element.clientWidth || element.offsetWidth),
  7578. getMaxOffsetLeft(offsetParent, utags, utagsSizeFix)
  7579. ) + "px"
  7580. utags.style.top = offset.top + "px"
  7581. break
  7582. }
  7583. case "200% 50%": {
  7584. utags.style.left =
  7585. Math.min(
  7586. offset.left + (element.clientWidth || element.offsetWidth),
  7587. getMaxOffsetLeft(offsetParent, utags, utagsSizeFix)
  7588. ) + "px"
  7589. utags.style.top =
  7590. offset.top +
  7591. ((element.clientHeight || element.offsetHeight) -
  7592. utags.clientHeight -
  7593. utagsSizeFix) /
  7594. 2 +
  7595. "px"
  7596. break
  7597. }
  7598. case "200% 100%": {
  7599. utags.style.left =
  7600. Math.min(
  7601. offset.left + (element.clientWidth || element.offsetWidth),
  7602. getMaxOffsetLeft(offsetParent, utags, utagsSizeFix)
  7603. ) + "px"
  7604. utags.style.top =
  7605. offset.top +
  7606. (element.clientHeight || element.offsetHeight) -
  7607. utags.clientHeight -
  7608. utagsSizeFix +
  7609. "px"
  7610. break
  7611. }
  7612. default: {
  7613. break
  7614. }
  7615. }
  7616. element.dataset.utags_fit_content = "0"
  7617. }
  7618. async function main() {
  7619. addUtagsStyle()
  7620. await initSettings({
  7621. id: "utags",
  7622. title: i2("settings.title"),
  7623. footer: "\n <p>"
  7624. .concat(
  7625. i2("settings.information"),
  7626. '</p>\n <p>\n <a href="https://github.com/utags/utags/issues" target="_blank">\n '
  7627. )
  7628. .concat(
  7629. i2("settings.report"),
  7630. '\n </a></p>\n <p>Made with \u2764\uFE0F by\n <a href="https://www.pipecraft.net/" target="_blank">\n Pipecraft\n </a></p>'
  7631. ),
  7632. settingsTable: settingsTable2,
  7633. async onValueChange() {
  7634. onSettingsChange()
  7635. onSettingsChange2()
  7636. },
  7637. onViewUpdate(settingsMainView) {
  7638. let item = $(
  7639. '[data-key="useVisitedFunction_'.concat(host2, '"]'),
  7640. settingsMainView
  7641. )
  7642. if (!isAvailableOnCurrentSite() && item) {
  7643. item.style.display = "none"
  7644. item.parentElement.style.display = "none"
  7645. }
  7646. item = $(
  7647. '[data-key="displayEffectOfTheVisitedContent_'.concat(host2, '"]'),
  7648. settingsMainView
  7649. )
  7650. if (item) {
  7651. item.style.display = getSettingsValue(
  7652. "useVisitedFunction_".concat(host2)
  7653. )
  7654. ? "flex"
  7655. : "none"
  7656. }
  7657. item = $('[data-key="customStyleValue"]', settingsMainView)
  7658. if (item) {
  7659. item.parentElement.style.display = getSettingsValue("customStyle")
  7660. ? "block"
  7661. : "none"
  7662. }
  7663. item = $(".bes_tip", settingsMainView)
  7664. if (item) {
  7665. item.style.display = getSettingsValue("customStyle")
  7666. ? "block"
  7667. : "none"
  7668. }
  7669. item = $(
  7670. '[data-key="customStyleValue_'.concat(host2, '"]'),
  7671. settingsMainView
  7672. )
  7673. if (item) {
  7674. item.parentElement.style.display = getSettingsValue(
  7675. "customStyle_".concat(host2)
  7676. )
  7677. ? "block"
  7678. : "none"
  7679. }
  7680. },
  7681. })
  7682. if (!getSettingsValue("enableCurrentSite_".concat(host2))) {
  7683. return
  7684. }
  7685. await initStorage()
  7686. setTimeout(outputData, 1)
  7687. onSettingsChange()
  7688. onSettingsChange2()
  7689. await displayTags()
  7690. addEventListener(doc, "visibilitychange", async () => {
  7691. if (!doc.hidden) {
  7692. await displayTags()
  7693. }
  7694. })
  7695. bindDocumentEvents()
  7696. bindWindowEvents()
  7697. const observer = new MutationObserver(async (mutationsList) => {
  7698. let shouldUpdate = false
  7699. for (const mutationRecord of mutationsList) {
  7700. if (shouldUpdateUtagsWhenNodeUpdated(mutationRecord.addedNodes)) {
  7701. shouldUpdate = true
  7702. break
  7703. }
  7704. if (shouldUpdateUtagsWhenNodeUpdated(mutationRecord.removedNodes)) {
  7705. shouldUpdate = true
  7706. break
  7707. }
  7708. }
  7709. if (shouldUpdate) {
  7710. cleanUnusedUtags()
  7711. displayTagsThrottled()
  7712. }
  7713. if ($("#vimiumHintMarkerContainer")) {
  7714. addClass(doc.body, "utags_show_all")
  7715. addClass(doc.documentElement, "utags_vimium_hint")
  7716. } else if (hasClass(doc.documentElement, "utags_vimium_hint")) {
  7717. removeClass(doc.documentElement, "utags_vimium_hint")
  7718. hideAllUtagsInArea()
  7719. }
  7720. })
  7721. observer.observe(doc, {
  7722. childList: true,
  7723. subtree: true,
  7724. })
  7725. addEventListener(doc, "mouseover", (event) => {
  7726. const target = event.target
  7727. if (
  7728. target &&
  7729. (target.tagName === "A" || target.dataset.utags !== void 0)
  7730. ) {
  7731. displayTagsThrottled()
  7732. }
  7733. })
  7734. }
  7735. runWhenHeadExists(async () => {
  7736. if (doc.documentElement.dataset.utags === void 0) {
  7737. doc.documentElement.dataset.utags = "".concat(host2)
  7738. await main()
  7739. }
  7740. })
  7741. })()