Back2source

Redirecting to source sites from sites with machine translation, etc.

  1. // ==UserScript==
  2. // @name Back2source
  3. // @version 0.1.159
  4. // @description Redirecting to source sites from sites with machine translation, etc.
  5. // @namespace vladgba
  6. // @author vladgba@gmail.com
  7. // @run-at document-end
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=stackoverflow.com
  9. // @homepageURL https://github.com/vladgba/Back2source
  10. // @supportURL https://github.com/vladgba/Back2source/issues
  11. // @grant GM_xmlhttpRequest
  12. // @grant GM_registerMenuCommand
  13. // @grant GM_setValue
  14. // @grant GM_getValue
  15. // @connect api.browser.yandex.ru
  16. // @connect api.github.com
  17. // @connect api.stackexchange.com
  18. // @noframes
  19. // @match *://*.16892.net/qa/*
  20. // @match *://*.1r1g.com/sf/ask/*
  21. // @match *://*.360wiki.ru/wiki/*
  22. // @match *://*.55276.net/qa/*
  23. // @match *://*.5axxw.com/*/*/*
  24. // @match *://*.955yes.com/ask/1*.html
  25. // @match *://*.9ishenzhen.com/?qa=*
  26. // @match *://*.abcdef.wiki/*
  27. // @match *://*.amuddycup.com/*
  28. // @match *://*.androidalle.com/pregunta/*
  29. // @match *://*.androiderrors.com/*
  30. // @match *://*.androidrepo.com/repo/*
  31. // @match *://*.answacode.com/*
  32. // @match *://*.answeright.com/*
  33. // @match *://*.answerlib.com/question/*
  34. // @match *://*.answerspoint.com/questions/*/*
  35. // @match *://*.antwortenhier.me/*
  36. // @match *://*.anycodings.com/*
  37. // @match *://*.ape-ask.com/read-*.html
  38. // @match *://*.appsloveworld.com/*/*
  39. // @match *://*.arip-photo.org/*
  40. // @match *://*.ask-dev.ru/info/*
  41. // @match *://*.ask-ubuntu.ru/questions/*
  42. // @match *://*.ask.roboflow.ai/question/*
  43. // @match *://*.askcodez.com/*
  44. // @match *://*.askdev.info/questions/*
  45. // @match *://*.askdev.ru/q*
  46. // @match *://*.askdevz.com/question/*
  47. // @match *://*.askentire.net/q/*-*
  48. // @match *://*.askfrance.me/*
  49. // @match *://*.askubuntu.ru/questions/*
  50. // @match *://*.askvoprosy.com/voprosy/*
  51. // @match *://*.astrophel.org/*
  52. // @match *://*.athabasca-foto.com/*
  53. // @match *://*.awesomeopensource.com/project/*
  54. // @match *://*.bcqaw.com/*.html
  55. // @match *://*.bestofcpp.com/repo/*
  56. // @match *://*.bestofphp.com/repo/*
  57. // @match *://*.bestofreactjs.com/repo/*
  58. // @match *://*.bestofvue.com/repo/*
  59. // @match *://*.bildiredi.com/*
  60. // @match *://*.bilee.com/*.html
  61. // @match *://*.binarydevelop.com/article/*
  62. // @match *://*.bleepcoder.com/*/*
  63. // @match *://*.bootpanic.com/*
  64. // @match *://*.buildwiki.ru/wiki/*
  65. // @match *://*.bytemeta.vip/*
  66. // @match *://*.cache.one/read/*
  67. // @match *://*.cainiaojiaocheng.com/questions/*
  68. // @match *://*.catchconsole.com/code-example/*
  69. // @match *://*.catwolf.org/qs*
  70. // @match *://*.cepe-eua.org/*/*
  71. // @match *://*.cfadnc.org/*
  72. // @match *://*.chowdera.com/*.html
  73. // @match *://*.ciupacabra.com/*
  74. // @match *://*.cloud.tencent.com/developer/ask/*
  75. // @match *://*.cmsdk.com/*/*.html
  76. // @match *://*.cndgn.com/question/*
  77. // @match *://*.code-error.com/*
  78. // @match *://*.code-examples.net/*/q/*
  79. // @match *://*.code-hint.com/en/*
  80. // @match *://*.code.i-harness.com/*/q/*
  81. // @match *://*.codebug.zone/*
  82. // @match *://*.codefactor.io/repository/*
  83. // @match *://*.codefaq.info/*
  84. // @match *://*.codefaq.ru/*
  85. // @match *://*.codefordev.com/discuss/*/*
  86. // @match *://*.codegear.dev/*/questions/*
  87. // @match *://*.codegrepper.com/code-examples/*
  88. // @match *://*.codegrepr.com/question/*
  89. // @match *://*.codeguides.site/questions/*
  90. // @match *://*.codehunter.cc/*
  91. // @match *://*.codengineering.net/q/*
  92. // @match *://*.codengineering.ru/q/*
  93. // @match *://*.codenong.com/*
  94. // @match *://*.codepudding.com/*/*.html
  95. // @match *://*.coder-question-ko.com/cq-ko-blog/*
  96. // @match *://*.coder-question.com/cq-blog/*
  97. // @match *://*.coder.social/*
  98. // @match *://*.coder.work/article/*
  99. // @match *://*.coderoad.in/questions/*
  100. // @match *://*.coderoad.ru/*
  101. // @match *://*.coderquestion.ru/q/*
  102. // @match *://*.codespots.com/library/item/*
  103. // @match *://*.codetd.com/article/*
  104. // @match *://*.codeutility.org/*
  105. // @match *://*.coredump.biz/questions/*
  106. // @match *://*.culinarydegree.info/*
  107. // @match *://*.curatedgo.com/r/*/index.html
  108. // @match *://*.dailydevsblog.com/troubleshoot/*
  109. // @match *://*.daplus.net/*
  110. // @match *://*.datewiki.ru/wiki/*
  111. // @match *://*.de-vraag.com/*
  112. // @match *://*.debugcn.com/*article/*
  113. // @match *://*.debugko.com/article/*
  114. // @match *://*.dev-answers.com/solutions/*
  115. // @match *://*.devasking.com/issue/*
  116. // @match *://*.devdreamz.com/question/*
  117. // @match *://*.devebee.com/answer/*
  118. // @match *://*.develop-bugs.com/article/*
  119. // @match *://*.developreference.com/article/*
  120. // @match *://*.devfaq.fr/question/*
  121. // @match *://*.devtip.in/*/*
  122. // @match *://*.digitrain.ru/questions/*
  123. // @match *://*.dir.md/*
  124. // @match *://*.dokry.com/*
  125. // @match *://*.domainelespailles.net/*
  126. // @match *://*.donolik.com/*
  127. // @match *://*.doraprojects.net/questions/*
  128. // @match *://*.dtuto.com/questions/*/*
  129. // @match *://*.duhoctrungquoc.vn/wiki/*/*
  130. // @match *://*.duoduokou.com/*/*.html
  131. // @match *://*.e-learn.cn/topic/*
  132. // @match *://*.ec-europe.org/*
  133. // @match *://*.ecnf2016.org/*
  134. // @match *://*.editcode.net/article-*
  135. // @match *://*.edupro.id/questions/*
  136. // @match *://*.edureka.co/community/*/*
  137. // @match *://*.elfishgene.com/*
  138. // @match *://*.encyclopaedia.bid/*
  139. // @match *://*.encyclopedia.thefreedictionary.com/*
  140. // @match *://*.errorsandanswers.com/*
  141. // @match *://*.errorsfixing.com/*
  142. // @match *://*.exchangetuts.com/*-*
  143. // @match *://*.explained.today/*
  144. // @match *://*.extutorial.com/ask/*
  145. // @match *://*.faithcov.org/*
  146. // @match *://*.fantashit.com/*
  147. // @match *://*.findatwiki.com/*
  148. // @match *://*.findbestopensource.com/product/*
  149. // @match *://*.firstlightsalon.in/*/questions/*
  150. // @match *://*.fitforlearning.org/*
  151. // @match *://*.fixes.pub/*/*.html
  152. // @match *://*.fluffyfables.com/*
  153. // @match *://*.flutterhq.com/questions-and-answers/*
  154. // @match *://*.flutterrepos.com/lib/*
  155. // @match *://*.frwiki.wiki/wiki/*
  156. // @match *://*.fullstackuser.com/questions/*
  157. // @match *://*.gaz.wiki/wiki/*
  158. // @match *://*.geek-tips.imtqy.com/articles/*/*.html
  159. // @match *://*.geeksrepos.com/*
  160. // @match *://*.generacodice.com/*
  161. // @match *://*.getridbug.com/*/*
  162. // @match *://*.ghcc.net/*
  163. // @match *://*.gitanswer.net/*
  164. // @match *://*.gitcode.net/*
  165. // @match *://*.gitdetail.com/repositories/*
  166. // @match *://*.giters.com/*
  167. // @match *://*.gitfreak.com/*
  168. // @match *://*.githubhelp.com/*
  169. // @match *://*.githubhot.com/*
  170. // @match *://*.githublab.com/*/*
  171. // @match *://*.githubmemory.com/*
  172. // @match *://*.githubplus.com/*
  173. // @match *://*.gitrush.ru/*/*/*
  174. // @match *://*.globalwikionline.com/detial/*/*
  175. // @match *://*.golangd.com/g/*
  176. // @match *://*.golangexample.com/*
  177. // @match *://*.golangrepo.com/repo/*
  178. // @match *://*.gupgallery.com/*
  179. // @match *://*.helpex.vn/question/*
  180. // @match *://*.higithub.com/*/*
  181. // @match *://*.hmong.ru/wiki/*
  182. // @match *://*.hmong.wiki/wiki/*
  183. // @match *://*.howtobuildsoftware.com/index.php/how-do/*
  184. // @match *://*.howtosolves.com/q/*
  185. // @match *://*.html-agility-pack.net/knowledge-base/*
  186. // @match *://*.husl.ru/questions/*
  187. // @match *://*.ichi.pro/*
  188. // @match *://*.icode9.com/*
  189. // @match *://*.icopy.site/questions/*
  190. // @match *://*.idqna.com/question/*
  191. // @match *://*.im-coder.com/*.html
  192. // @match *://*.intellipaat.com/community/*
  193. // @match *://*.intrepidgeeks.com/tutorial/*
  194. // @match *://*.ipgirl.com/*
  195. // @match *://*.iquestion.pro/q/*
  196. // @match *://*.isolution.pro/q/*
  197. // @match *://*.issue.life/questions/*
  198. // @match *://*.issueantenna.com/*/*
  199. // @match *://*.issuehint.com/issue/*/*/*
  200. // @match *://*.it-brain.online/question/*
  201. // @match *://*.it1352.com/*.html
  202. // @match *://*.itbaoku.cn/post/*.html
  203. // @match *://*.itdaan.com/*
  204. // @match *://*.itecnote.com/tecnote/*
  205. // @match *://*.itectec.com/*/*
  206. // @match *://*.itnan.ru/post.php*
  207. // @match *://*.itranslater.com/qa/details/*
  208. // @match *://*.jablogs.com/detail/*
  209. // @match *://*.javacodexamples.com/examples/*
  210. // @match *://*.javaer101.com/*/*
  211. // @match *://*.javafixing.com/*/*/*.html
  212. // @match *://*.javarepos.com/lib/*
  213. // @match *://*.jejakjabar.com/wiki/*
  214. // @match *://*.jike.in/*-1.html
  215. // @match *://*.jike.in/qa/*
  216. // @match *://*.jonic.cn/qa/*
  217. // @match *://*.jpdebug.com/p/*
  218. // @match *://*.jscodetips.com/examples/*
  219. // @match *://*.jsrepos.com/*/*
  220. // @match *://*.juejin.cn/post/*
  221. // @match *://*.knews.vip/q/*
  222. // @match *://*.kompsekret.ru/q/*
  223. // @match *://*.kotaeta.com/*
  224. // @match *://*.kutombawewe.net/*/*
  225. // @match *://*.learn-codes.net/*/*
  226. // @match *://*.learnfk.com/*question/*
  227. // @match *://*.legkovopros.ru/questions/*
  228. // @match *://*.libraries.io/*/*
  229. // @match *://*.lifesaver.codes/answer/*
  230. // @match *://*.lightrun.com/answers/*
  231. // @match *://*.linuxfixes.com/*/*/*
  232. // @match *://*.livepcwiki.ru/wiki/*
  233. // @match *://*.living-sun.com/*/*
  234. // @match *://*.localcoder.org/*
  235. // @match *://*.macosrepo.com/software/*
  236. // @match *://*.manongdao.com/*.html
  237. // @match *://*.mediatagtw.com/*/*
  238. // @match *://*.mediawiki.feverous.co.uk/index.php/*
  239. // @match *://*.messiahlebanon.org/*
  240. // @match *://*.microeducate.tech/*
  241. // @match *://*.mlink.in/qa/*
  242. // @match *://*.mlog.club/article/*
  243. // @match *://*.narkive.jp/*
  244. // @match *://*.newbedev.com/*
  245. // @match *://*.newdevzone.com/posts/*
  246. // @match *://*.nina.az/wiki/*
  247. // @match *://*.noblenaz.org/*
  248. // @match *://*.npm.io/package/*
  249. // @match *://*.npmmirror.com/package/*
  250. // @match *://*.ntcdoon.org/*
  251. // @match *://*.nuomiphp.com/*/*
  252. // @match *://*.nwikiit.cyou/wiki/*
  253. // @match *://*.ogeek.cn/*-1.html
  254. // @match *://*.ogeek.cn/qa/*
  255. // @match *://*.opensourcelibs.com/lib/*
  256. // @match *://*.ostack.cn/*-1.html
  257. // @match *://*.ostack.cn/qa/*
  258. // @match *://*.ounapuu.ee/*/*
  259. // @match *://*.ourladylakes.org/*
  260. // @match *://*.overcoder.net/q/*
  261. // @match *://*.overcoder.ru/q/*
  262. // @match *://*.overstack.in/*-1.html
  263. // @match *://*.overstack.in/qa/*
  264. // @match *://*.pakostnici.com/*
  265. // @match *://*.panaindustrial.com/*
  266. // @match *://*.pcbconline.org/*
  267. // @match *://*.pengembangan-web-mp-pd.com/id/*
  268. // @match *://*.phptime.ru/questions/*
  269. // @match *://*.poweruser.guru/*
  270. // @match *://*.prog-help.ru/*
  271. // @match *://*.progi.pro/*
  272. // @match *://*.programmierfrage.com/items/*
  273. // @match *://*.programming-articles.com/*
  274. // @match *://*.projectbackpack.org/*
  275. // @match *://*.proubuntu.ru/*/*
  276. // @match *://*.pyquestions.com/*
  277. // @match *://*.python2.net/questions-*.htm
  278. // @match *://*.pythonawesome.com/*
  279. // @match *://*.pythonfixing.com/*.html
  280. // @match *://*.pythonlang.dev/repo/*
  281. // @match *://*.pythonrepo.com/repo/*
  282. // @match *://*.qa-stack.pl/*
  283. // @match *://*.qandeelacademy.com/questions/*
  284. // @match *://*.qapicks.com/question/*
  285. // @match *://*.qarchive.ru/*
  286. // @match *://*.qaru.tech/questions/*
  287. // @match *://*.qarus.ru/*
  288. // @match *://*.qastack.in.th/*
  289. // @match *://*.qastack.info.tr/*
  290. // @match *://*.qastack.net.bd/*
  291. // @match *://*.qi-u.com/*-1.html
  292. // @match *://*.qi-u.com/qa/*
  293. // @match *://*.quabr.com/*
  294. // @match *://*.querythreads.com/*
  295. // @match *://*.question-it.com/questions/*
  296. // @match *://*.questu.ru/questions/*
  297. // @match *://*.reddit.fun/*/*
  298. // @match *://*.reposhub.com/*/*
  299. // @match *://*.respuestas.me/*
  300. // @match *://*.rotadev.com/*
  301. // @match *://*.routinepanic.com/questions/*
  302. // @match *://*.ru.encyclopedia.kz/index.php/*
  303. // @match *://*.rudata.ru/wiki/*
  304. // @match *://*.runebook.dev/*/docs/*
  305. // @match *://*.ruphp.com/*.html
  306. // @match *://*.rustrepo.com/repo/*
  307. // @match *://*.safehavenpetrescue.org/*
  308. // @match *://*.savepearlharbor.com/?p=*
  309. // @match *://*.sbup.com/wiki/*
  310. // @match *://*.sch22.org/*
  311. // @match *://*.secret-bases.co.uk/wiki/*
  312. // @match *://*.semicolonworld.com/question/*
  313. // @match *://*.serveanswer.com/issue/*
  314. // @match *://*.server-fault.ru/questions/*
  315. // @match *://*.shenghuobao.net/qa/*
  316. // @match *://*.shenzhenjia.cn/qa/*
  317. // @match *://*.shenzhenjia.net/qa/*
  318. // @match *://*.sierrasummit2005.org/*
  319. // @match *://*.siwib.org/*
  320. // @match *://*.smnggeophysics.com/*
  321. // @match *://*.snyk.io/advisor/npm-package/*
  322. // @match *://*.sobrelinux.info/questions/*
  323. // @match *://*.socket.dev/npm/package/*
  324. // @match *://*.softbranchdevelopers.com/*
  325. // @match *://*.softwareuser.asklobster.com/posts/*
  326. // @match *://*.soinside.com/question/*
  327. // @match *://*.solusi.cyou/*/*
  328. // @match *://*.solveforum.com/forums/threads/*
  329. // @match *://*.sprosi.pro/questions/*
  330. // @match *://*.sqlite.in/*-1.html
  331. // @match *://*.sqlite.in/qa/*
  332. // @match *://*.stackanswers.net/questions/*
  333. // @match *://*.stackfinder.jp.net/questions/*
  334. // @match *://*.stackfinder.ru/questions/*
  335. // @match *://*.stackguides.com/questions/*
  336. // @match *://*.stackify.dev/*
  337. // @match *://*.stackoom.com/*question/*
  338. // @match *://*.stackoverflood.com/*
  339. // @match *://*.stackoverflowpoint.com/question/*
  340. // @match *://*.stackovergo.com/*q/*
  341. // @match *://*.stackru.com/questions/*
  342. // @match *://*.string.quest/read/*
  343. // @match *://*.sunflowercreations.org/*
  344. // @match *://*.super-unix.com/*/*
  345. // @match *://*.swiftobc.com/repo/*
  346. // @match *://*.switch-case.com/*
  347. // @match *://*.syntaxfix.com/question/*
  348. // @match *://*.sysadminde.com/questions/*
  349. // @match *://*.techarks.ru/qa/*
  350. // @match *://*.techfeed.net/*
  351. // @match *://*.techhelpnotes.com/*
  352. // @match *://*.techinplanet.com/*
  353. // @match *://*.territorioscuola.it/*
  354. // @match *://*.thecodeteacher.com/question/*
  355. // @match *://*.theshuggahpies.com/*
  356. // @match *://*.thinbug.com/q/*
  357. // @match *://*.tipsfordev.com/*
  358. // @match *://*.tistory.com/*
  359. // @match *://*.tousu.in/qa/*
  360. // @match *://*.tracholar.top/*/*/*/*
  361. // @match *://*.try2explore.com/*
  362. // @match *://*.tutorialguruji.com/*/*
  363. // @match *://*.tutorialink.com/*
  364. // @match *://*.tutorialmeta.com/question/*
  365. // @match *://*.tutorialmore.com/questions-*
  366. // @match *://*.twblogs.net/a/*
  367. // @match *://*.ubuntuaa.com/*q/*
  368. // @match *://*.ubuntuplace.info/questions/*
  369. // @match *://*.utyatnishna.ru/info/*
  370. // @match *://*.uwenku.com/question/*
  371. // @match *://*.v-resheno.ru/*
  372. // @match *://*.vigge.cn/qa/*
  373. // @match *://*.vigge.net/qa/*
  374. // @match *://*.vigges.net/qa/*
  375. // @match *://*.voidcc.com/question/*
  376. // @match *://*.vuejscode.com/*
  377. // @match *://*.vvikipedla.com/wiki/*
  378. // @match *://*.w3coded.com/questions/*/*
  379. // @match *://*.w3toppers.com/*
  380. // @match *://*.wake-up-neo.net/*/*
  381. // @match *://*.waymanamechurch.org/*
  382. // @match *://*.web-answers.ru/*/*
  383. // @match *://*.web-dev-qa-db-fra.com/fr/*
  384. // @match *://*.web-dev-qa-db-ja.com/ja/*
  385. // @match *://*.web-gelistirme-sc.com/tr/*
  386. // @match *://*.webdevdesigner.com/q*
  387. // @match *://*.webentwicklung-frage-antwort-db.com.de/de/*
  388. // @match *://*.wekeepcoding.com/article/*/*
  389. // @match *://*.wenyanet.com/opensource/*
  390. // @match *://*.while-do.com/*
  391. // @match *://*.wiki-org.ru/*
  392. // @match *://*.wiki-wiki.ru/wp/*
  393. // @match *://*.wiki.cologne/*
  394. // @match *://*.wiki2.info/*
  395. // @match *://*.wiki2.net/*
  396. // @match *://*.wiki2.org/*
  397. // @match *://*.wiki2.wiki/wiki/*
  398. // @match *://*.wiki5.ru/wiki/*
  399. // @match *://*.wikibrief.org/wiki/*
  400. // @match *://*.wikichi.ru/wiki/*
  401. // @match *://*.wikidark.ru/wiki/*
  402. // @match *://*.wikidea.ru/wiki/*
  403. // @match *://*.wikies.wiki/wiki/*
  404. // @match *://*.wikimho.com/*/q/*/*
  405. // @match *://*.wikipe.wiki/wiki/*
  406. // @match *://*.wikipedia-on-ipfs.org/wiki/*
  407. // @match *://*.wikipedia.tel/*
  408. // @match *://*.wikipedia24.ru/*
  409. // @match *://*.wikiredia.ru/*
  410. // @match *://*.wikiroot.ru/question/*
  411. // @match *://*.wikit.wiki/article/*/*
  412. // @match *://*.wikivisually.com/wiki/*
  413. // @match *://*.wikiwand.com/*/*
  414. // @match *://*.wikizero.com/*/*
  415. // @match *://*.wp-qa.com/*
  416. // @match *://*.wujigu.com/qa/*
  417. // @match *://*.xcv.wiki/*
  418. // @match *://*.xiu2.net/it/details/*
  419. // @match *://*.xsprogram.com/content/*
  420. // @match *://*.xstack.ru/qa/*
  421. // @match *://*.xstack.us/*-1.html
  422. // @match *://*.xstack.us/qa/*
  423. // @match *://*.xszz.org/*/question-*
  424. // @match *://*.yaoply.com/items/*
  425. // @match *://*.yingqusp.com/so/*
  426. // @match *://*.ylhow.com/*
  427. // @match *://*.younggeeks.in/questions/*
  428. // @match *://*.yuanmacha.com/*.html
  429. // @match *://*.zahn-info-portal.de/wiki/*
  430. // @match *://*.zaizhele.cn/qa/*
  431. // @match *://*.zaizhele.net/qa/*
  432. // @match *://*.zapytay.com/*
  433. // @match *://*.zsharp.org/*
  434. // @match *://*.zxc.wiki/wiki/*
  435. // @match *://*.zzun.app/repo/*
  436. // @include *://qastack.tld/*
  437. // ==/UserScript==
  438. /* jshint esversion: 10 */
  439. /* eslint quotes: ['warn', 'single'] */
  440. /* eslint userscripts/better-use-match: 'off' */
  441. /* eslint no-fallthrough: 'off' */
  442. (async () => {
  443. 'use strict';
  444.  
  445. var sitecolor = '#333';
  446. var lang = 'ru';
  447. var badCode = false;
  448. var badImgs = false;
  449. var _ = undefined;
  450. var ll, tt;
  451. const _p = location.pathname;
  452. const _ps = _p.split('/');
  453. const _h = location.href;
  454. const _se = ['stackoverflow.com','superuser.com','serverfault.com','stackapps.com','mathoverflow.net','askubuntu.com','stackexchange.com'];
  455. /** Checks if a given object is a string */
  456. var _$s = (s) => typeof s === 'string' || s instanceof String;
  457. /** Gets the subdomain (host part) of the site */
  458. var _hp = (p = 3) => (ll = location.hostname.split('.')) && ll[ll.length-p];
  459. /** Gets the element by a given selector */
  460. var _t = (s) => document.querySelector(s);
  461. /** Tests if the path of the site matches the given regex */
  462. var _c = (r) => r.test(_p);
  463. /** Redirects to a link, if it exists; checks for validity of the source site are bypassed */
  464. var _go = (s) => s && window.location.replace(s);
  465. /** Checks if a string is part of the hostname */
  466. var _hst = (s) => location.hostname.includes(s);
  467. /** Sets the color for the bottom bar, if it's not set */
  468. var clr = (c, f) => (sitecolor = (f || sitecolor == '#333') ? c : sitecolor);
  469. /** Sets the language for translating and searching, if it's not set */
  470. var lng = (c, f) => (lang = (f || lang == 'ru') ? c : lang);
  471. /** Gets the last part of a path */
  472. var lastPathPart = () => _ps.filter(Boolean).slice(-1)[0];
  473. /** Gets the href attribute (or any other attribute) of a selected element, if it exists */
  474. var bySel = (s, a = 'href') => _t(s)?.getAttribute(a);
  475. /** Removes the auxiliary words of the textcontent of: the header if no parameter is given; a element matching the given selector; the first element, if the parameter is an array*/
  476. var getHeader = (h) => removeAuxiliary(h ? (Array.isArray(h) ? h[0] : textContent(h)) : textContent('h1'));
  477. /** Get an array of the textcontent of: elements with the tag-class if no parameter is given; elements matching the given selector; or the first element, if the parameter is an array*/
  478. var getTags = (t) => t ? (Array.isArray(t) ? [t[0]] : allTexts(t)) : allTexts('.tag');
  479. /** Replaces in a string all occurrences of the first element of an arraygroup with the second */
  480. var mulReplace = (str, a) => a.forEach((v) => (str = str.replace(v[0], v[1]))) || str;
  481. /** Creates a Wikipedia link with language and article text or the number of the part in the website url, optionally adding the /wiki/ part */
  482. var wiki = (l = 0, p = 2, w = true) => 'https://' + (_$s(l) ? l : _ps[l]) + '.wikipedia.org' + (w ? '/wiki/' : '') + (_$s(p) ? p : _ps[p]);
  483. /** Creates a Github link with the project and repository */
  484. var github = (l) => l ? 'https://github.com' + l : null;
  485. /** Creates the bottom bar with the text, the code parts and images to search for */
  486. var prepareSearch = (h, t, s) => promptRedirect(sitecolor, toSearch(h + (t ? ' ' + getTags(t).join(' ').replace(/\s+/g, ' ') : ''), s), !badCode && allTexts('pre code'), !badImgs && [...new Set([...allAttr('img[src*="://i.stack.imgur.com/"]', 'src'), ...allAttr('a[href*="://i.stack.imgur.com/"]', 'href')])], s);
  487. /** Translates all tags given as an array */
  488. var transTags = async (t) => (await yaTranslate(allTexts(t).join(' '), lang)).split(' ');
  489. /** Creates the Google search link with the slightly aligned text to search for, the sites to search on, optionally searching for images */
  490. var toSearch = (s, site, i) => (s = dropMarks(s) && s && (ll = s.split(' ').filter(i => !i.match(/^(and|an|are|for|how|in|is|it|i|of|or|the|to)$/i)).length) ? 'https://google.com/search?q=' + (ll <= 32 ? encodeURIComponent(s) + '+' : '') + ((site && Array.isArray(site)) ? (site.length < 1 ? '' : 'site%3A' + site.join('+OR+site%3A')) : 'site%3Astackexchange.com+OR+site%3Astackoverflow.com') + (ll <= 32 ? '' : '+' + encodeURIComponent(s)) + (i ? '&tbm=isch' : '') : null);
  491. /** Gets the textcontent of a selected element, if it exists */
  492. var textContent = (s) => _t(s)?.textContent.trim();
  493. /** Creates StackOverflow link by article id, optionally mofifying it before */
  494. var byNumber = (s, radix) => (s = parseInt(s, radix)) && s > 0 ? 'https://stackoverflow.com/questions/' + s : null;
  495. /** Adds surrounding spaces and make the string lowercase, if it exists */
  496. var normalize = (s) => s && ' ' + s.toLowerCase() + ' ';
  497. /** Pipes multiple functions after each other */
  498. var pipe = (...fns) => x => fns.reduce((v, f) => f(v), x);
  499. /** Creates an array of the elements matched by given selector */
  500. var all = (s) => [...document.querySelectorAll(s)];
  501. /** Creates an array of the textcontent of all elements matched by given selector */
  502. var allTexts = (s) => all(s).map(a => a.textContent.trim());
  503. /** Creates an array of the attributes of all elements matched by given selector */
  504. var allAttr = (s, t) => all(s).map(a => a[t].trim());
  505. /** Gets the attribute of a given element, if it exists, and get a specific text part by regex or replace it with anoter text */
  506. var getAttr = (t, a, r, s = '$1') => (t.hasAttribute(a)) && t.getAttribute(a).replace(r, s);
  507. /** Removes marks of a string, if it exists */
  508. var dropMarks = (s) => s && s.replace(/\[(на удержании|on hold|duplikować|duplicado|duplicar|duplikat|dublicate|duplicate|дубликат|закрыто|закрытый|closed|geschlossen|zamknięte|cerrado|重复|repeat)\]\s*$/i, '').trim();
  509. /** Removes the beginning of a text that precedes a given part */
  510. var removePartBefore = (t, p) => textContent(t).replace(new RegExp('.*?'+ p), '');
  511. /** Returns text in parentheses **/
  512. var fromParentheses = (t) => (ll = t.split('(')) && (ll.length == 1 ? ll[0] : (ll.length == 2 ? ll[1] : ll.slice((ll.length - 2) / 2 + 1).join('(')).slice(0, -1));
  513.  
  514. /** Gets the first link by a given selector, that links to a stack exchange site */
  515. function _tc(s) {
  516. var allw = _se.flatMap(i => [i+'/q', i+'/a/'])
  517. var nods = all(s);
  518. for (var nod in nods) for (var pt in allw) if(nods[nod]?.href?.indexOf(allw[pt])>=0) return nods[nod].href;
  519. }
  520.  
  521. /** Gets the image url with the site where the image is from, optionally with by selector and cutting the path */
  522. function urlByImg(v, s = 'img[src*="/images/content/"]', n = 3) {
  523. var p = _t(s)?.src;
  524. if (!p) return;
  525. var l = (new URL(p)).pathname.split('/')[n];
  526. return l && (v + l);
  527. }
  528.  
  529. var db = JSON.parse(GM_getValue('b2s') || '{}');
  530. for (var y in db) if (location.href == db[y][0]) return _go(db[y][1]);
  531.  
  532. /** Adds the given JavaScript code as inline code to the opened site */
  533. function addJS(code) {
  534. var scriptElm = document.createElement('script');
  535. var inlineCode = document.createTextNode(code);
  536. scriptElm.appendChild(inlineCode);
  537. document.body.appendChild(scriptElm);
  538. }
  539.  
  540. /** Replaces different quote variants, optionally removes them, replaces various control characters */
  541. function filterText(text, rmquotes) {
  542. var out = text.replace(/(\u02B9|\u0374|\u2018|\u201A|\u2039|\u203A|\u201B|\u2019)+/g, '\'').replace(/(\u00AB|\u00BB|\u201E|\u201C|\u201F|\u201D|\u2E42)+/g, '"');
  543. return (rmquotes ? out.replace(/(\'|")+/g, ' ') : out).replace(/ /g, ' ').replace(/(\r|\n)+/g, ' ').replace(/\s\s+/g, ' ').trim().replace(/\.$/, '').trim();
  544. }
  545.  
  546. /** Creates the bottom bar to search for a question */
  547. async function promptRedirect(bgcolor, link, codef, imgf, site) {
  548. const dialog = document.createElement('div');
  549. try {
  550. document.body.appendChild(dialog);
  551. const shadowRoot = dialog.attachShadow ?
  552. dialog.attachShadow({ mode: 'open' }) :
  553. //@ts-ignore
  554. dialog.createShadowRoot && dialog.createShadowRoot();
  555. if (!shadowRoot) throw 'Shadow dom required!';
  556. shadowRoot.innerHTML = `
  557. <style>
  558. :host{
  559. position: fixed;
  560. bottom: 0;
  561. z-index: 16777271;
  562. width: 100%;
  563. color: white;
  564. background-color: ${bgcolor}!important;
  565. }
  566. .m{
  567. padding: 14px;
  568. font-family: Ubuntu,Segoe UI,Optima,Trebuchet MS,-apple-system,BlinkMacSystemFont,sans-serif;
  569. font-size: 14px;
  570. }
  571. #close-btn{
  572. float: right;
  573. cursor: pointer;
  574. }
  575. a{
  576. color: white;
  577. }
  578. .search-icon{
  579. font-size: 24px;
  580. line-height: 0;
  581. text-decoration: none;
  582. }
  583. </style>
  584. <div class="m">[ Back2Source ]
  585. <a id="ok-btn" href="#">Try to find the original question? <span class="search-icon">&#8981;<span></a> ` +
  586. (codef && codef.length > 0 ? '<a href="' + toSearch(codef.join(' '), site) + '">[ByCode]</a>' : '') +
  587. (imgf && imgf.length > 0 ? '<a href="' + toSearch(imgf.join(' '), site, true) + '">[ByImgs]</a>' : '') +
  588. `<span id="close-btn">&#10006;</span>
  589. </div>`;
  590. shadowRoot.querySelector('#ok-btn').href = link;
  591. await new Promise((_, reject) => {
  592. shadowRoot.querySelector('#close-btn').addEventListener('click', reject);
  593. });
  594. } finally {
  595. document.body.removeChild(dialog);
  596. }
  597. }
  598.  
  599. //https://yandex.com/dev/translate/doc/dg/concepts/api-overview.html
  600. /** Translates a slightly aligned text with Yandex from one language to english or any other given language */
  601. async function yaTranslate(q, sourceLang, targetLang) {
  602. q = dropMarks(q);
  603. if (!q) return null;
  604. q = 'https://api.browser.yandex.ru/dictionary/translate?statLang=en&targetLang=' + (targetLang ? targetLang : 'en') + '&text=' + encodeURIComponent(q) + (sourceLang ? '&fromLang=' + sourceLang : '')
  605. try {
  606. //doesn't work in chrome
  607. return await fetch(q, {
  608. mode: 'no-cors',
  609. credentials: 'omit'
  610. })
  611. .then(r => r.json())
  612. .then(r => r.text);
  613. } catch (e) {
  614. //works only in tampermonkey
  615. return new Promise((resolve, reject) => {
  616. //@ts-ignore
  617. GM_xmlhttpRequest({
  618. url: q,
  619. responseType: 'json',
  620. anonymous: true,
  621. onload: (xhr) => {
  622. xhr.status === 200 ? resolve(xhr.response.text) : reject(xhr);
  623. },
  624. onerror: reject
  625. })
  626. })
  627. }
  628. }
  629.  
  630. var auxiliaryRe = null;
  631.  
  632. /** Removes auxiliary words of a given string */
  633. function removeAuxiliary(s) {
  634. return s && s.replace(auxiliaryRe || (auxiliaryRe = new RegExp([
  635. 'a', 'an', 'the',
  636. //Conjunctions http://englishgu.ru/soyuzyi-v-angliyskom-yazyike-tablitsa-spisok/
  637. //https://7esl.com/english-conjunctions/
  638. 'according to', 'after', 'against', 'also', 'although', 'and', 'as far as', 'as if', 'as long as', 'as much as', 'as soon as', 'as though', 'as well as', 'as', 'assuming that', 'at last', 'at least', 'because of', 'because', 'before', 'beyond', 'both', 'but', 'by the time', 'either', 'even if', 'even though', 'for', 'from now on', 'from time to time', 'how', 'however', 'if', 'in case', 'in order', 'in spite of', 'in terms of', 'lest', 'like', 'meanwhile', 'moreover', 'neither', 'nevertheless', 'no matter how', 'no matter what', 'no matter when', 'no matter where', 'no matter who', 'no matter why', 'nor', 'not so as', 'not yet', 'now that', 'on behalf of', 'on condition', 'on the contrary', 'on the other hand', 'once', 'only if', 'or', 'otherwise', 'owing to', 'provided that', 'rather than', 'since', 'so that', 'so', 'still', 'than', 'that is why', 'that', 'therefore', 'though', 'thus', 'till', 'unless', 'unlike', 'until', 'what', 'whatever', 'when', 'whenever', 'where', 'whereas', 'wherever', 'whether', 'which', 'whichever', 'while', 'who', 'whoever', 'whom', 'whomever', 'whose', 'with', 'within', 'without', 'yet',
  639. //some of Preposition https://www.englishclub.com/grammar/prepositions-list.htm
  640. //https://www.talkenglish.com/vocabulary/top-50-prepositions.aspx
  641. 'aboard', 'about', 'above', 'across', 'after', 'against', 'along', 'amid', 'among', 'anti', 'around', 'at', 'behind', 'below', 'beneath', 'beside', 'besides', 'beyond', 'but', 'by', 'concerning', 'considering', 'despite', 'down', 'during', 'excepting', 'excluding', 'following', 'for', 'from', 'in', 'including', 'inside', 'into', 'of', 'off', 'on', 'onto', 'opposite', 'out', 'outside', 'over', 'past', 'per', 'regarding', 'since', 'than', 'through', 'throughout', 'to', 'toward', 'towards', 'under', 'underneath', 'unlike', 'until', 'up', 'upon', 'versus', 'via', 'within', 'without',
  642. //some of https://7esl.com/interjections-exclamations/
  643. 'aah', 'ah', 'aha', 'ahem', 'alas', 'argh', 'aw', 'aww', 'bah', 'behold', 'bingo', 'boo', 'bravo', 'brr', 'dear', 'duh', 'eek', 'eh', 'er', 'eww', 'gah', 'gee', 'grr', 'hah', 'hello', 'hey', 'hi', 'hmm', 'huh', 'hullo', 'humph', 'hurrah', 'meh', 'mhm', 'muahaha', 'nuh-uh', 'oh', 'ooh', 'ooh-la-la', 'oomph', 'oops', 'ouch', 'oww', 'oy', 'pew', 'pff', 'phew', 'psst', 'sheesh', 'shh', 'shoo', 'tsk-tsk', 'uh-hu', 'uh-oh', 'uh-uh', 'uhh', 'um', 'umm', 'wee', 'well', 'whoa', 'wow', 'yahoo', 'yay', 'yeah', 'yikes', 'yippee', 'yoo-hoo', 'yuck', 'yuh-uh', 'zing',
  644. //modals
  645. 'can', 'could', 'be able to', 'may', 'might', 'shall', 'should', 'must', 'have to', 'will', 'would',
  646. ].sort((a, b) => b.length - a.length).map(w => `\\W${w}(?!\\w)`).join('|'), 'g')), ' ');
  647. }
  648.  
  649. /**
  650. * Searches a text with the Stack Exchange API, optionally with a timeframe and the tags
  651. * @param {string} q
  652. * @param {Date} [before]
  653. * @param {Date} [after]
  654. * @param {string[]} [tags]
  655. * @param {string} [site]
  656. */
  657. async function findByApi(q, before, after, tags, site='stackoverflow.com') {
  658. var dfgdr = (q = dropMarks(q)) && q && fetch(
  659. `https://api.stackexchange.com/2.3/search?page=1&pagesize=1&order=desc&sort=relevance&intitle=${encodeURIComponent(q)}&site=${site.split('.')[0]}` +
  660. (after ? '&fromdate=' + (after.getTime() / 1000 - 120 | 0) : '') +
  661. (before ? '&todate=' + (before.getTime() / 1000 + 120 | 0) : '') +
  662. (Array.isArray(tags) && tags.length > 0 ? '&tagged=' + encodeURIComponent(Array.from(new Set(tags)).join(';')) : ''), {
  663. credentials: 'omit'
  664. })
  665. .then(r => r.json())
  666. .then(r => r?.items[0]?.link);
  667. return dfgdr;
  668. }
  669.  
  670. /** Searches an issue text with the Github API, optionally with the user */
  671. async function findByGitHubApi(q, user) {
  672. var dfgdr = q && fetch(
  673. `https://api.github.com/search/issues?q=${encodeURIComponent(q)}` +
  674. (user && user != 'ghost' ? ' author:' + encodeURIComponent(user) : ''), {
  675. credentials: 'omit'
  676. })
  677. .then(r => r.json())
  678. .then(r => r?.items[0]?.html_url);
  679. return dfgdr;
  680. }
  681.  
  682. /**
  683. * Takes the slightly aligned text of the header or a given selector, optionally translates it, tries to find it per API and otherwise creates the bottom bar to search for
  684. * @param {string|array} [h] - header selector (def: 'h1')
  685. * @param {string|array} [t] - tags selector (def: '.tag')
  686. * @param {string} [l] - lang (def: none)
  687. * @param {string} [s] - target site(s) (def: ['stackoverflow.com'])
  688. */
  689. async function byHeader(h, t, l, s) {
  690. var sbh = (l == 'en') ? (Array.isArray(h) ? h[0] : textContent(h ? h : 'h1')) : filterText(await yaTranslate(getHeader(h), l), 1);
  691. return sbh && (await findByApi(sbh, _, _, getTags(t), Array.isArray(s) ? s[0] : _) || prepareSearch(sbh, t, s));
  692. }
  693.  
  694. /** Gets the text to search for from a part of the path, tries to find it per API and otherwise creates the bottom bar to search for */
  695. async function byPath(pos, s) {
  696. ll = _ps[pos].replace(/(-closed|-duplicate)?(\.html)?$/, '').replace(/^\d+-/, '').replace(/[-+]/g, ' ');
  697. ll = ll.replace(/\b(are|ca|could|did|does|do|has|have|is|must|were|wo)n ?t\b/g,'$1n\'t').replace(/\b(they|you) ?(re|ve)\b/g,'$1\'$2').replace(/\bi ?(m|ve)\b/g,'i\'$1').replace(/\b(what|there) ?s\b/g,'$1\'s');
  698. return (await findByApi(ll)) || prepareSearch(ll, '', s);
  699. }
  700.  
  701. /** Matches elements by a given selector, searches for elements whose inner text starts with a given search text and returns the link of an element matched by a second given selector or the inner text that follows the search text */
  702. function startsByText(selector, text, href = false) {
  703. const e = all(selector);
  704. for (var i = 0; i < e.length; i++) {
  705. var t = e[i].innerText.trim();
  706. var f = t.indexOf(text);
  707. if (f == 0) return (href ? e[i].querySelector(href)?.href : t.substr(text.length).trim());
  708. }
  709. }
  710.  
  711. /** Matches elements by a given selector, searches for elements whose inner text includes a given search text and returns their link */
  712. function byInner(selector, text) {
  713. const e = all(selector);
  714. for (var i = 0; i < e.length; i++) {
  715. if (e[i].innerText.trim().indexOf(text) >= 0) return e[i].href;
  716. }
  717. }
  718.  
  719. var link;
  720. const host = location.hostname.split('.').slice(-2).join('.');
  721. console.log('Checking site: ' + location.hostname + (location.hostname != host ? ' as ' + host : ''));
  722.  
  723. switch (host) {
  724. case '16892.net':
  725. case '55276.net':
  726. case 'jike.in':
  727. case 'jonic.cn':
  728. case 'mlink.in':
  729. case 'ogeek.cn':
  730. case 'ostack.cn':
  731. case 'overstack.in':
  732. case 'qi-u.com':
  733. case 'shenghuobao.net':
  734. case 'shenzhenjia.cn':
  735. case 'shenzhenjia.net':
  736. case 'sqlite.in':
  737. case 'tousu.in':
  738. case 'vigge.cn':
  739. case 'vigge.net':
  740. case 'vigges.net':
  741. case 'wujigu.com':
  742. case 'xstack.ru':
  743. case 'xstack.us':
  744. case 'zaizhele.cn':
  745. case 'zaizhele.net':
  746. if (_c(/^\/thread-.*.html$/) && textContent('#pt a:nth-child(5)') == '知识问答') return byHeader([removePartBefore('h1',' - ')], _, 'en');
  747. if (_c(/^\/article-.*.html$/) && textContent('#pt a:nth-child(5)') == '开源') return bySel('.deanedit > a');
  748. if (_ps[1] == 'qa' && _t('h1 a')){
  749. if (textContent('h1').match(/[\u4e00-\u9fa5]/)) return byHeader('h1', _, 'zh');
  750. return byHeader([removePartBefore('h1',' - ')], _, 'en');
  751. }
  752. return;
  753. case '1r1g.com':
  754. return clr('#343a40') && byHeader('h1', 'a.badge', 'en');
  755. case '5axxw.com':
  756. return byHeader('h1','.badge-tag','zh') && byHeader('h2',_,'zh');
  757. case '955yes.com':
  758. return byNumber(_ps[2].match(/1(\d*)\.html/)[1]);
  759. case '9ishenzhen.com':
  760. return !_c(/[\u4e00-\u9fa5]/) && _t('h1 a') && byHeader([removePartBefore('h1',' - ')], _, 'en');
  761. case 'amuddycup.com':
  762. case 'arip-photo.org':
  763. case 'athabasca-foto.com':
  764. case 'cfadnc.org':
  765. case 'culinarydegree.info':
  766. case 'domainelespailles.net':
  767. case 'ec-europe.org':
  768. case 'ecnf2016.org':
  769. case 'elfishgene.com':
  770. case 'faithcov.org':
  771. case 'fitforlearning.org':
  772. case 'fluffyfables.com':
  773. case 'gupgallery.com':
  774. case 'messiahlebanon.org':
  775. case 'noblenaz.org':
  776. case 'ntcdoon.org':
  777. case 'ourladylakes.org':
  778. case 'pakostnici.com':
  779. case 'panaindustrial.com':
  780. case 'pcbconline.org':
  781. case 'projectbackpack.org':
  782. case 'safehavenpetrescue.org':
  783. case 'sch22.org':
  784. case 'sierrasummit2005.org':
  785. case 'siwib.org':
  786. case 'smnggeophysics.com':
  787. case 'sunflowercreations.org':
  788. case 'theshuggahpies.com':
  789. case 'waymanamechurch.org':
  790. case 'zsharp.org':
  791. return (tt = _t('meta[property="og:image"]').content.split('/').pop().split('.')[0].replace(/-/g,' ')) && byHeader([tt], _, 'en', ['stackoverflow.com','superuser.com','askubuntu.com','stackexchange.com']);
  792. case 'androiderrors.com':
  793. case 'w3toppers.com':
  794. return byHeader('h1', 'span.tags-links > a', 'en');
  795. case 'answerlib.com':
  796. case 'answerspoint.com':
  797. case 'ask-dev.ru':
  798. case 'coderoad.in':
  799. case 'younggeeks.in':
  800. return byPath(3);
  801. case 'antwortenhier.me':
  802. case 'askfrance.me':
  803. case 'respuestas.me':
  804. case 'askentire.net':
  805. return clr('#2c3e50') && byHeader('h1', [await transTags('ul.x-tags li a[href*="/t/"]')], document.documentElement.lang);
  806. case 'anycodings.com':
  807. return byHeader([removePartBefore('h2',': ')], '.no-gutters > a', 'en');
  808. case 'appsloveworld.com':{
  809. let title = textContent('h1#posttitle');
  810. let crop_start = title.match(/^((?:\w+[\-\s]*)?\[?(?:SOLVED|SOLUTION)\]?\s*-\s*)/i);
  811. let matches = title.match(/\s?(?:\s*-\s*([\w+#]+(?:[\-\s.]\w+)?))?$/i);
  812. if (crop_start != null) title = title.replace(crop_start, '');
  813.  
  814. let tag = false;
  815. if (matches != null) {
  816. title = title.replace(matches[0], '');
  817. tag = matches[1];
  818. }
  819. return byHeader([title], tag ? [tag] : [], 'en');
  820. }
  821. case 'askdev.ru':
  822. return clr('#970f1b') && urlByImg('https://superuser.com/questions/') || byHeader('h1', [await transTags('.block_taxonomies a')], 'ru');
  823. case 'askdevz.com':
  824. case 'askvoprosy.com':
  825. case 'living-sun.com':
  826. case 'qandeelacademy.com':
  827. case 'yaoply.com':
  828. return byPath(2);
  829. case 'asklobster.com':
  830. case 'cainiaojiaocheng.com':
  831. case 'coderquestion.ru':
  832. case 'coredump.biz':
  833. case 'digitrain.ru':
  834. case 'gitrush.ru':
  835. case 'html-agility-pack.net':
  836. case 'icopy.site':
  837. case 'issue.life':
  838. case 'qaru.tech':
  839. case 'stackfinder.ru':
  840. case 'thinbug.com':
  841. return byNumber(_ps[2]);
  842. case 'askubuntu.ru':
  843. return byHeader('h1', 'nav .col-tag', 'ru', ['askubuntu.com']);
  844. case 'bcqaw.com':
  845. return byHeader('h1.article-title', _, 'zh');
  846. case 'bildiredi.com':
  847. case 'ciupacabra.com':
  848. case 'de-vraag.com':
  849. case 'donolik.com':
  850. case 'kotaeta.com':
  851. case 'switch-case.com':
  852. case 'while-do.com':
  853. case 'zapytay.com':
  854. return bySel('a.link.block');
  855. case 'bilee.com':
  856. clr('#178acc');
  857. case 'techarks.ru':
  858. clr('#20a169');
  859. case 'question-it.com':
  860. clr('#2c3e50');
  861. case 'legkovopros.ru':
  862. lng('ru') && clr('#55b252');
  863. case 'edupro.id':
  864. lng('id') && clr('#2c3e50');
  865. return byHeader('h1', '.tag', lang);
  866. case 'binarydevelop.com':
  867. return bySel('div.cc', 'data-href');
  868. case 'catchconsole.com':
  869. return byHeader([dropMarks(textContent('h1'))], _, 'en');
  870. case 'cmsdk.com':
  871. case 'code-error.com':
  872. case 'idqna.com':
  873. case 'learn-codes.net':
  874. case 'newdevzone.com':
  875. case 'programming-articles.com':
  876. case 'thecodeteacher.com':
  877. case 'w3coded.com':
  878. return byHeader('h1', _, 'en');
  879. case 'cndgn.com':
  880. return 'https://' + _ps[2].replace(/(.+)stack/,'$1.stackexchange').replace(/^(stack)$/,'$1overflow') + '.com/questions/' + _ps[3];
  881. case 'code-examples.net':
  882. case 'i-harness.com':
  883. return byNumber(lastPathPart(), 16);
  884. case 'codebug.zone':
  885. return byHeader([removePartBefore('h1', ' – ')], _, 'es');
  886. case 'codefordev.com':
  887. return byHeader('h1', '.ui.small.label', 'en');
  888. case 'codeguides.site':
  889. return byNumber(_ps[3]);
  890. case 'codehunter.cc':
  891. return byHeader('h1', '.badge', 'en');
  892. case 'codengineering.net':
  893. return (!allTexts('.tags > div > a').join().match(/[\u0400-\u04ff]/)) && byHeader('h1', '.tags > div > a', 'ru');
  894. case 'codengineering.ru':
  895. return toSearch(lastPathPart().replace(/(-closed|-duplicate)?(-\d+)?(\.html)?$/, ''), true);
  896. case 'codenong.com':
  897. case 'coderoad.ru':
  898. case 'quabr.com':
  899. return byNumber(_ps[1]);
  900. case 'codepudding.com':
  901. return byHeader('div.detail_title', '.hot-tags a', 'en');
  902. case 'coder.work':
  903. return bySel('div>p>a[rel="noreferrer noopener nofollow"]') || startsByText('p', 'stackoverflow链接', 'a[href*="stackoverflow.com"]') || startsByText('p', 'stackoverflow原址', 'a[href*="stackoverflow.com"]') || byHeader('h1', _, 'zh');
  904. case 'codeutility.org':
  905. return byHeader('h1', '.tags-links > a', 'en');
  906. case 'dailydevsblog.com':
  907. return byHeader([removePartBefore('h1', 'Resolved: ')], '.tags > a', 'en');
  908. case 'daplus.net':
  909. return byHeader([removePartBefore('h1','\\] ')], _, 'ko');
  910. case 'debugcn.com':
  911. lng(_ps[1] == 'article' ? 'zh' : _ps[1]);
  912. case 'debugko.com':
  913. case 'jablogs.com':
  914. lng('ja');
  915. case 'xsprogram.com':
  916. case 'devasking.com':
  917. lng('en');
  918. return byHeader('h1', _, lang);
  919. case 'devdreamz.com':
  920. return byHeader('h1','[class^="ButtonTags_tags_container"] a', 'en');
  921. case 'devebee.com':
  922. return byHeader('h1', '.content > .tagcloud > a', 'en');
  923. case 'develop-bugs.com':
  924. tt = _t('blockquote > h2 > a').innerHTML.split(' - ');
  925. return byHeader([tt[0]], tt[1], 'en');
  926. case 'developreference.com':
  927. var parts = document.title.split(' - ');
  928. var devpref = _ps[3].replace(/[-+]/g, ' ').replace(/(%ef|%bc|%9f)+$/i, '');
  929. return (await findByApi(devpref)) || (await findByApi(parts[0], _, _, [parts.pop()])) || promptRedirect(sitecolor, toSearch(devpref));
  930. case 'devfaq.fr':
  931. return byHeader('h1', '.badge-info', 'fr');
  932. case 'devtip.in':
  933. return byHeader('h1', '.tag-list div', 'en');
  934. case 'dokry.com':
  935. return byHeader('h1', '.badge a', 'es');
  936. case 'doraprojects.net':
  937. return byInner('a.text-muted', 'Source');
  938. case 'dtuto.com':
  939. return byHeader('h5', '.tag-link', 'en');
  940. case 'duoduokou.com':
  941. return byHeader('p.post-title', 'span.category > a', 'zh');
  942. case 'e-learn.cn':
  943. return startsByText('div.content p:last-child', '来源:');
  944. case 'editcode.net':
  945. return byHeader([removePartBefore('h1', ':')], _,'en');
  946. case 'edureka.co':
  947. return byHeader([JSON.parse(textContent('[type="application/ld+json"]')).name], _,'en');
  948. case 'errorsfixing.com':
  949. return bySel('div.entry-content.boxed > p:nth-last-of-type(3) > a');
  950. case 'exchangetuts.com':
  951. return byHeader('h1', '.item-tag > a', 'en');
  952. case 'extutorial.com':
  953. return byHeader('h1', 'a[href*="/tags/"]', 'en');
  954. case 'firstlightsalon.in':
  955. return 'https://' + _ps[1].replace('_threads','.stackexchange.com/questions/') + _ps[3];
  956. case 'fixes.pub':
  957. return byHeader('h1', 'aside li a[href*="fixes.pub/topics"]', 'ja');
  958. case 'flutterhq.com':
  959. return byInner('a', 'Stackoverflow.com');
  960. case 'fullstackuser.com':
  961. return byHeader('h1', '.custom-head .post-tag', 'en');
  962. case 'getridbug.com':
  963. return byHeader('h1', 'div.post-tags > a', 'en');
  964. case 'ghcc.net':
  965. return byHeader('h1', '.field__item > a', 'en');
  966. case 'helpex.vn':
  967. return _t('#viewSource>span')?.innerText.replace(/^: /,'');
  968. case 'howtobuildsoftware.com':
  969. return byHeader([removePartBefore('title',' - ')], '#list .email-content-subtitle a', 'en');
  970. case 'imtqy.com':
  971. return byHeader('.question-header>h1', _, 'en');
  972. case 'intellipaat.com':
  973. return byHeader('h1', '.qa-q-view-tag-item', 'en');
  974. case 'ipgirl.com':
  975. return byHeader('h1', '.breadcrumb-item > span > a', 'fr');
  976. case 'it1352.com':
  977. return byHeader([removePartBefore('h1 > em','\\] ')], 'div.arc-meta > span > a', 'en');
  978. case 'itbaoku.cn':
  979. return byHeader([removePartBefore('h1 > em','\\] ')], '.article-tags > a', 'en');
  980. case 'itecnote.com':
  981. return byHeader([removePartBefore('h1',' – ').replace(/How to/, '')], _, 'en');
  982. case 'itectec.com':
  983. return byHeader([removePartBefore('h1', ' – ')], '.badge','en', _se);
  984. case 'javacodexamples.com':
  985. return byHeader('h1', '.titleBox > p > a', 'en');
  986. case 'javaer101.com':
  987. return byHeader('h1', 'nav .col-tag', _ps[1] == 'article' ? 'ja' : _ps[1]);
  988. case 'jscodetips.com':
  989. return byHeader('h1', '.contentBox > div:nth-child(3) > a', 'en');
  990. case 'kompsekret.ru':
  991. return clr('#292d2f') && (urlByImg('https://superuser.com/questions/') || byHeader([lastPathPart().replace(/(-closed|-duplicate)?(\d+)?(\.html)?$/, '').replace(/-/g, ' ')], '.tags a', 'en', ['superuser.com']));
  992. case 'kutombawewe.net':
  993. case 'pengembangan-web-mp-pd.com':
  994. case 'wake-up-neo.net':
  995. case 'web-dev-qa-db-fra.com':
  996. case 'web-dev-qa-db-ja.com':
  997. case 'web-gelistirme-sc.com':
  998. return bySel('.q-source > a');
  999. case 'learnfk.com':
  1000. if (_ps[1] == 'en') return byHeader('h1', '.entry-info > .badge-tag', 'en');
  1001. return byHeader([removePartBefore('h2.h11','\\] ')], '.entry-info > .badge-tag', 'en');
  1002. case 'localcoder.org':
  1003. return byHeader('h1', '.categories a', 'en');
  1004. case 'manongdao.com':
  1005. return byHeader('h2', 'a.notebook > span', 'en');
  1006. case 'microeducate.tech':
  1007. case 'programmierfrage.com':
  1008. case 'routinepanic.com':
  1009. return _tc('a');
  1010. case 'mlog.club':
  1011. addJS('var redir = window.__NUXT__.data[0].article.sourceUrl; redir && window.location.replace(redir);');
  1012. return lng('zh') && byHeader('h1', [await transTags('.article-tag')], 'zh');
  1013. case 'newbedev.com':
  1014. return _t('article') && byHeader('h1', 'h4.tags a.item-tag', 'en', _se);
  1015. case 'poweruser.guru':
  1016. return _t('div.post-menu a.suggest-edit-post[href*="superuser.com/questions/"]');
  1017. case 'progi.pro':
  1018. return clr('#4e82c2') && byHeader('h1[itemprop="name"]', '.tag-list a', 'ru');
  1019. case 'proubuntu.ru':
  1020. return byHeader('h1>a>span[itemprop="name"]', [await transTags('a[rel="tag"]')], 'ru', ['askubuntu.com']);
  1021. case 'pyquestions.com':
  1022. return (tt = '(' + getTags('.btn.btn-secondary').join('|') + ')') && byHeader([textContent('h1').replace(new RegExp('(^' + tt + ': | in ' + tt + '$)', 'i'),'')], '.btn.btn-secondary', 'en');
  1023. case 'qapicks.com':
  1024. return byNumber(_ps[2].split('-')[0]);
  1025. case 'querythreads.com':
  1026. return JSON.parse(textContent('script#__NEXT_DATA__')).props.pageProps.data.url;
  1027. case 'questu.ru':
  1028. return byInner('a', 'источник');
  1029. case 'reddit.fun':
  1030. return byHeader('h1', '.qa-q-view-tags .qa-tag-link', 'en');
  1031. case 'roboflow.ai':
  1032. return byNumber(_ps[2]);
  1033. case 'rotadev.com':
  1034. return (tt = textContent('h1').split(/ – (Dev|Super User|Server Fault)$/)) && byHeader(tt, _, 'en', [mulReplace(tt[1], [['Dev', 'stackoverflow.com'], ['Super User', 'superuser.com'], ['Server Fault', 'serverfault.com']])]);
  1035. case 'ruphp.com':
  1036. return byHeader('h1', '.breadcrumb-item .badge a', 'ru');
  1037. case 'semicolonworld.com':
  1038. return byHeader('h1', '.post__category', 'en');
  1039. case 'server-fault.ru':
  1040. return byHeader('h1', 'div.question-text > div.tags > a.tag', 'ru', ['serverfault.com']);
  1041. case 'sobrelinux.info':
  1042. return byHeader('h1', '.tags .tag a', 'pt', _se);
  1043. case 'soinside.com':
  1044. return clr('#333') && byHeader('h1', '.q-tag', 'zh');
  1045. case 'solveforum.com':
  1046. return byHeader([removePartBefore('h1', '\\[Solved\\] ')], _, 'en');
  1047. case 'stackanswers.net':
  1048. clr('#999') && lng('en');
  1049. return location.hostname.startsWith('publish.') && all('.panel-body a')[1].href;
  1050. case 'stackify.dev':
  1051. return byHeader('h1', '.tags-container span.front', 'en');
  1052. case 'stackoom.com':
  1053. return byNumber(_t('[id^=question_content_]').id.split('_')[2]);
  1054. case 'stackoverflood.com':
  1055. return (tt = _h.match(/^https?:\/\/stackoverflood\.com\/([a-zA-Z]{2})\/q\/(.+)/)) && byNumber(tt[2]);
  1056. case 'stackoverflowpoint.com':
  1057. return byHeader([removePartBefore('h1', ' – ')], '.post-cat > a', 'en');
  1058. case 'string.quest':
  1059. return byHeader([removePartBefore('h1', ' - ')], '.tag-links a', 'zh');
  1060. case 'super-unix.com':
  1061. return byHeader([removePartBefore('h1', ' – ')], '.badge', 'en', [mulReplace(_ps[1], [['superuser', 'superuser.com'], ['askdifferent', 'apple'], ['database', 'dba'], ['ubuntu', 'askubuntu.com'], ['unixlinux', 'unix']])]);
  1062. case 'syntaxfix.com':
  1063. return byHeader('h1', '.tag_askd>p>span>code', 'en');
  1064. case 'sysadminde.com':
  1065. return 'https://serverfault.com/questions/' + _ps[2];
  1066. case 'techfeed.net':
  1067. return byHeader('main h1', '.tag', 'ru');
  1068. case 'techhelpnotes.com':
  1069. return byHeader([removePartBefore('h1', ' – ')], _, 'en');
  1070. case 'techinplanet.com':
  1071. return byHeader('h1', '.entry-tags > a', 'en');
  1072. case 'tencent.com':
  1073. return byHeader('.ask-title h2', _, 'zh');
  1074. case 'tipsfordev.com':
  1075. return byHeader('h1', '.blog-pagination > a', 'en');
  1076. case 'tistory.com':
  1077. return all('.article-view p > a').pop().href;
  1078. case 'tracholar.top':
  1079. return byPath(4);
  1080. case 'tutorialguruji.com':
  1081. return byHeader([textContent('h1').replace(/ *Code Answer *$/, '')], _, 'en');
  1082. case 'tutorialink.com':
  1083. return byHeader('h1', 'a.tag-link', 'en');
  1084. case 'tutorialmeta.com':
  1085. if (textContent('.tt-right:nth-last-of-type(3)') != 'source: stackoverflow.com') return;
  1086. return byHeader('h1', _, 'en');
  1087. case 'tutorialmore.com':
  1088. return byHeader([removePartBefore('h1',' - ')], '.tags a', 'ja', ['superuser.com', 'stackoverflow.com', 'stackexchange.com']);
  1089. case 'utyatnishna.ru':
  1090. return byHeader('h1.entry-title', '.tag', 'ru');
  1091. case 'v-resheno.ru':
  1092. return textContent('.linkurl > b');
  1093. case 'vuejscode.com':
  1094. return bySel('article .mt-4 a') || byHeader('h1', _, 'en');
  1095. case 'webdevdesigner.com':
  1096. return (tt = (_ps[1] == 'q' ? _ps[2] : _ps[1].replace(/^q-/, '')).replace(/-\d+$/, '').replace(/-/g, ' ')) && byHeader([tt], '.tags a', 'en', ['stackoverflow.com', 'superuser.com', 'stackexchange.com']);
  1097. case 'wekeepcoding.com':
  1098. return byHeader('h4', _, 'en');
  1099. case 'wenyanet.com':
  1100. return bySel('.question-date a');
  1101. case 'wikiroot.ru':
  1102. tt = _t('section section div.footer-post div.d-inline-block button');
  1103. tt = tt && (getAttr(tt, 'data-url', /https?:\/\/wikiroot\.ru\/comment\/new\/([0-9]+)/) || getAttr(tt, 'data-target', /#buttoncollapse-([0-9]+)/));
  1104. return tt ? 'https://superuser.com/questions/' + tt : byHeader('h1', 'ul.tags-list li a', 'ru');
  1105. case 'wp-qa.com':
  1106. return byHeader('h1', '#content > .tags > a', 'en');
  1107. case 'xiu2.net': // redirects to site with 502 / 2022-07-06
  1108. addJS('var redir = window.__NUXT__.data[0].info.sourceUrl; redir && window.location.replace(redir);');
  1109. return lng('zh') && byHeader('h1', '.contents .tag-time a[href*="/it/tag/"]', 'zh');
  1110. case 'xszz.org':
  1111. return clr('#ff6f06') && byHeader('.post-h1title h1', 0, 'en');
  1112. case 'ylhow.com':
  1113. return (tt = _t('.entry-content > p > a[href*="stackoverflow.com/"]')) && tt.innerText.includes('原文') && tt.href;
  1114. case 'yuanmacha.com':
  1115. return (tt = _t('h1')?.innerHTML.match(/\((.+)\)/)) && byHeader([tt[1]], '.tag a', 'en', ['stackoverflow.com']);
  1116. /* Wikipedia */
  1117. case '360wiki.ru':
  1118. case 'buildwiki.ru':
  1119. case 'datewiki.ru':
  1120. case 'hmong.ru':
  1121. case 'hmong.wiki':
  1122. case 'livepcwiki.ru':
  1123. case 'nwikiit.cyou':
  1124. case 'vvikipedla.com':
  1125. case 'wiki2.wiki':
  1126. case 'wiki5.ru':
  1127. case 'wikibrief.org':
  1128. case 'wikichi.ru':
  1129. case 'wikidea.ru':
  1130. case 'wikivisually.com':
  1131. case 'zahn-info-portal.de':
  1132. return wiki('en');
  1133. case 'abcdef.wiki':
  1134. return wiki('en', _p, false);
  1135. case 'duhoctrungquoc.vn':
  1136. case 'globalwikionline.com':
  1137. case 'wikies.wiki':
  1138. case 'wikipe.wiki':
  1139. case 'wikit.wiki':
  1140. return wiki(2, 3);
  1141. case 'encyclopaedia.bid':
  1142. return wiki('ru', _p.replace(/^\/%D0%B2%D0%B8%D0%BA%D0%B8%D0%BF%D0%B5%D0%B4%D0%B8%D1%8F/, '/wiki'), false);
  1143. case 'encyclopedia.kz':
  1144. return _hst('ru.encyclopedia.kz') && wiki('ru', 2);
  1145. case 'explained.today':
  1146. case 'findatwiki.com':
  1147. return wiki('en', 1);
  1148. case 'frwiki.wiki':
  1149. return wiki('fr', 2);
  1150. case 'gaz.wiki':
  1151. return wiki('en', 3);
  1152. case 'jejakjabar.com': // redirects to zahn-info-portal.de / 2022-07-06
  1153. return (tt = _h.match(/https?:\/\/([a-zA-z]+\.)?jejakjabar\.com\/wiki\/(.+)/)) && wiki('en', tt[2]);
  1154. case 'nina.az':
  1155. return (tt = _h.match(/https?:\/\/wikipedia\.(([a-z]{2})\.)?nina\.az\/wiki\/(.+)/)) && wiki(mulReplace(tt[2], [ ['ua', 'uk'], ['us', 'en'] ]), tt[3]);
  1156. case 'rudata.ru':
  1157. return bySel('a.external[href*="ru.wikipedia.org"]');
  1158. case 'sbup.com':
  1159. case 'wiki-org.ru':
  1160. case 'wikiredia.ru':
  1161. return wiki('ru', _p, false);
  1162. case 'territorioscuola.it':
  1163. return (tt = _h.match(/https?:\/\/enhancedwiki\.territorioscuola\.it\/\?title=(.+)/)) && wiki('it', tt[1]);
  1164. case 'thefreedictionary.com':
  1165. return wiki('en', textContent('h1'));
  1166. case 'wiki-wiki.ru':
  1167. return wiki('ru', 3);
  1168. case 'wiki.cologne':
  1169. case 'wiki2.info':
  1170. case 'wikipedia24.ru':
  1171. return _t('.mw-parser-output') && wiki('ru', 1);
  1172. case 'wiki2.net':
  1173. case 'wikipedia.tel':
  1174. return wiki('ru', _p.substr(1));
  1175. case 'wiki2.org':
  1176. if (/\?search=/.test(location.search)) return;
  1177. return ((tt = _h.match(/https?:\/\/wiki2\.org\/([a-zA-z]{2})\/(.+)/)) || (tt = _h.match(/https?:\/\/([a-z]{2})\.wiki2\.org\/wiki\/(.+)/))) && wiki(tt[1], tt[2]);
  1178. case 'wikidark.ru':
  1179. return wiki('ru', _p, false);
  1180. case 'wikipedia-on-ipfs.org':
  1181. return wiki(_hp(3), 2);
  1182. case 'wikiwand.com':
  1183. return !(/(\?|&)fullSearch=(true|false)/.test(location.search)) && wiki(1, 2);
  1184. case 'wikizero.com':
  1185. return wiki(1, 2);
  1186. case 'xcv.wiki':
  1187. return (tt = _h.match(/https?:\/\/([a-zA-z]{2,4})\.xcv\.wiki\/wiki\/(.+)/)) && wiki('de', tt[2]);
  1188. case 'zxc.wiki':
  1189. return wiki('de', 2);
  1190. /* GitHub */
  1191. case 'androidrepo.com':
  1192. case 'bestofphp.com':
  1193. case 'bestofvue.com':
  1194. case 'bestofreactjs.com':
  1195. case 'javarepos.com':
  1196. case 'jsrepos.com':
  1197. case 'flutterrepos.com':
  1198. case 'rustrepo.com':
  1199. case 'swiftobc.com':
  1200. return bySel('#description > article > a:last-of-type') || bySel('#description ~ a:last-of-type');
  1201. case 'astrophel.org':
  1202. case 'gitcode.net':
  1203. case 'giters.com':
  1204. case 'gitfreak.com':
  1205. case 'githubhelp.com':
  1206. case 'githubplus.com':
  1207. return github(_p);
  1208. case 'awesomeopensource.com':
  1209. return github(_p.replace(/^\/project/,''));
  1210. case 'bestofcpp.com':
  1211. case 'golangrepo.com':
  1212. case 'pythonrepo.com':
  1213. return byInner('#basic a.btn','GitHub Repository');
  1214. case 'bleepcoder.com':
  1215. return bySel('.float-right .text-muted');
  1216. case 'bytemeta.vip':
  1217. case 'githubhot.com':
  1218. case 'githubmemory.com':
  1219. return _c(/^\/(repo\/|@)/) && github(_p.replace(/^\/(repo\/|@)/,'/'));
  1220. case 'coder.social':
  1221. return bySel('h1.h1 > a.btn-git');
  1222. case 'codespots.com':
  1223. return bySel('a.repo');
  1224. case 'curatedgo.com':
  1225. return bySel('.mt-4 .text-xs a');
  1226. case 'fantashit.com':
  1227. return findByGitHubApi(textContent('h1'));
  1228. case 'geeksrepos.com':
  1229. return github(_p + location.search);
  1230. case 'gitanswer.net':
  1231. tt = '(\\b'+allTexts('.post-tags a.button').join('\\b|\\b')+'\\b)';
  1232. return findByGitHubApi(textContent('h1').replace(/ - .*$/, '').replace(new RegExp('(^' + tt + ' ?| ?' + tt + '$)', 'g'), ''), _t('.avatar').parentElement.querySelector('span').innerText);
  1233. case 'gitdetail.com':
  1234. return bySel('#right-sidebar a:last-of-type');
  1235. case 'githublab.com':
  1236. return github(_p.replace(/^\/(repository|profile)/,'').replace(/^(\/issues)(\/.*\/.*)(\/.*)/,'$2$1$3').replace(/^(\/issues)(\/.*\/.*)/,'$2$1'));
  1237. case 'golangd.com':
  1238. return bySel('.box-body > a');
  1239. case 'golangexample.com':
  1240. return bySel('#github ~ p > a');
  1241. case 'higithub.com':
  1242. return github(_p.replace(/\/(repo\/|user$)/,'/').replace(/^(\/.*)(\/issue)(\/.*)(\/.*)/,'$1$3$2s$4').replace(/^(\/.*)\/repo_(issues)(\/.*)/,'$1$3/$2'));
  1243. case 'issueantenna.com':
  1244. return github(_p.replace(/^\/(repo|author)/,''));
  1245. case 'issuehint.com':
  1246. return findByGitHubApi(textContent('h1'));
  1247. case 'lifesaver.codes':
  1248. return byInner('a[role="link"]','Original');
  1249. case 'lightrun.com':
  1250. return bySel('article > small > a');
  1251. case 'opensourcelibs.com':
  1252. return byInner('.repo-stats a','github.com');
  1253. case 'pythonawesome.com':
  1254. case 'softbranchdevelopers.com':
  1255. return bySel('.github-view');
  1256. case 'pythonlang.dev':
  1257. return bySel('.widget-profile > p > a');
  1258. case 'reposhub.com':
  1259. return bySel('#githome');
  1260. case 'zzun.app':
  1261. return _go(byInner('#basic a.btn','GitHub Repository'));
  1262. /* NPM */
  1263. case 'npm.io':
  1264. case 'npmmirror.com':
  1265. return 'https://www.npmjs.com'+_p;
  1266. case 'snyk.io':
  1267. return 'https://www.npmjs.com/package/'+_ps[3];
  1268. case 'socket.dev':
  1269. return 'https://www.npmjs.com'+_p.replace(/^\/npm/,'');
  1270. /* Other */
  1271. case 'ape-ask.com':
  1272. return _go(all('script').filter(i => i.innerText.indexOf('originfo') != -1)[0].innerText.match(/\.text\("(.*)"\)/)[1]);
  1273. case 'cache.one':
  1274. return _go(startsByText('.entry-tags p', '来源:'));
  1275. case 'cepe-eua.org':
  1276. return byHeader('h5', _, _ps[1], ['quora.com']);
  1277. case 'chowdera.com':
  1278. return _go(textContent('.nextinfo > p').split('\n')[2]);
  1279. case 'codefactor.io':
  1280. window.addEventListener('DOMContentLoaded', (e)=>{
  1281. if (_ps[2]=='github' && _ps[5]=='source') _go(bySel('a[title^="View on"]') + '/blob/' + _ps.splice(6).join('/'));
  1282. _go(bySel('a.page-title-link') || bySel('a[analytics-event^="View file on"]') || bySel('a[title^="View on"]'));
  1283. });
  1284. return;
  1285. case 'codegrepper.com':
  1286. window.addEventListener('DOMContentLoaded', (e)=>{
  1287. _go(bySel('.answer_source > a')) || promptRedirect(sitecolor, toSearch(textContent('h1').replace(/“(.*)” Code Answer(’s)?/,'$1'),[]), allTexts('.TaysCodeMirror-code .TaysCodeMirror-line'), _, [])
  1288. });
  1289. return;
  1290. case 'coder-question-ko.com':
  1291. case 'coder-question.com':
  1292. return _go(bySel('article a.bg-success-soft'));
  1293. case 'codetd.com':
  1294. return _go('https://' + _t('.article-refer span:nth-child(2)').innerText);
  1295. case 'dir.md':
  1296. return (tt = _h.match(/^https?:\/\/dir.md\/(.+)(&|\?)host=([a-zA-Z\.-]+)$/)) && _go('https://' + tt[3] + '/' + tt[1]);
  1297. case 'findbestopensource.com':
  1298. return _go(bySel('.row > .more-link:last-of-type'));
  1299. case 'ichi.pro':
  1300. return byHeader('h1', _, 'ja', []);
  1301. case 'icode9.com':
  1302. return _go(textContent('#paragraph > p:last-child').split('来源:', 2)[1].trim());
  1303. case 'intrepidgeeks.com':
  1304. return _go(bySel('.source-div a.h5'));
  1305. case 'it-brain.online':
  1306. return _go('https://tutorialspoint.com/' + _ps[2]);
  1307. case 'itdaan.com':
  1308. return _go(bySel('input[name="url"]', 'value'));
  1309. case 'itnan.ru':
  1310. return _h.match(/https?:\/\/([a-zA-Z]{2})?\.?itnan\.ru\/post\.php\?(.+)?p=([0-9]+)/) && _go(bySel('article.entry .entry-meta a[title="Оригинальная публикация"]'));
  1311. case 'juejin.cn':
  1312. window.addEventListener('DOMContentLoaded', (e)=>{
  1313. return byHeader('h1', _, 'zh', []);
  1314. });
  1315. return;
  1316. case 'libraries.io':
  1317. return (tt = all('p.project-links > span > a')) && _go(tt.filter(t => t.innerText.toLowerCase() == _ps[1])[0]);
  1318. case 'macosrepo.com':
  1319. return _go(bySel('.user-info > .seller-link'));
  1320. case 'mediatagtw.com':
  1321. if (_ps[1] == 'article') _go(bySel('#social_only > h3 > a'));
  1322. if (_ps[1] == 'exit') _go(bySel('.h5 > a'));
  1323. return;
  1324. case 'ounapuu.ee':
  1325. tt = _ps[1].split('_')[0];
  1326. if (tt == 'stackoverflow.com') return byNumber(_ps[3]);
  1327. if (_se.some(i => tt.includes(i))) return 'https://' + tt + '/questions/' + _ps[4].replace('.html','');
  1328. if (tt == 'wikipedia') return wiki(_ps[1].split('_')[1], _h.split('/A/')[1]);
  1329. if (tt == 'developer.mozilla.org' || tt == 'lowtechmagazine.com') return _go('https://' + _h.split('/A/')[1]);
  1330. if (tt == 'explainxkcd') return _go('https://www.explainxkcd.com/wiki/index.php/' + _h.split('/A/')[1]);
  1331. if (tt == 'proofwiki') return _go('https://proofwiki.org/wiki/' + _h.split('/A/')[1]);
  1332. if (tt == 'archlinux') return _go('https://wiki.archlinux.org/title/' + _h.split('/A/')[1]);
  1333. if (tt == 'openstreetmap') return _go('https://wiki.openstreetmap.org/wiki/' + _h.split('/A/')[1]);
  1334. return;
  1335. case 'runebook.dev':
  1336. return _go(bySel('div.row > div:first-Child > div > p > a'));
  1337. case 'savepearlharbor.com':
  1338. return _go(bySel('article.post > div.entry-content > p > a[href*="://habr.com/"]'));
  1339. case 'solusi.cyou':
  1340. if (tt = _t('article > .media-body .text-right a:nth-child(3)')) return tt.href.replace('https://solusi.cyou/read-https-','https://');
  1341. if (_c(/^\/read-https?-/)) return _go(_h.replace(/https:\/\/solusi\.cyou\/read-(https?)-/,'$1://'));
  1342. return;
  1343. case 'twblogs.net':
  1344. return _go(textContent('#OSC_h3_2 ~ a'));
  1345. default:
  1346. if (_hst('mediawiki.feverous.co.uk')){
  1347. return wiki('en', 2);
  1348. } else if (_hst('qastack') || _hst('qa-stack')) {
  1349. return bySel('span.text-muted.fake_url a, span.text-muted.fake_url', 'src') ||
  1350. bySel('.text-muted a:last-child[href*="stackoverflow.com/"],.text-muted a:last-child[href*="stackexchange.com/"],.text-muted a:last-child[href*="serverfault.com/"],.text-muted a:last-child[href*="superuser.com/"],.text-muted a:last-child[href*="mathoverflow.net/"]') ||
  1351. ((tt = _h.match(/https?:\/\/qa-?stack\.([a-z\.]+)\/([a-z]+)\/([0-9]+)\/(.+)/)) && 'https://' + tt[2] + '.stackexchange.com/questions/' + tt[3] + '/' + tt[4]);
  1352. } else if (_hst('secret-bases.co.uk')){
  1353. return wiki('en', 2);
  1354. } else if (_hst('stackfinder.jp.net')) {
  1355. return byNumber(_ps[2]);
  1356. } else if (_hst('webentwicklung-frage-antwort-db.com.de')) {
  1357. return bySel('.q-source > a');
  1358. } else {
  1359. console.log('check by selectors');
  1360. const cssSelectors = {
  1361. 'androidalle.com': '.item-content > a.track',
  1362. 'answacode.com': '.post__source',
  1363. 'answeright.com': 'a.link',
  1364. 'ask-ubuntu.ru': '.q-source',
  1365. 'askcodez.com': '.orli a',
  1366. 'askdev.info': '.question-text > .a-link',
  1367. 'bootpanic.com': '.entry-content > p > i > a',
  1368. 'catwolf.org': '.text-left.small > a',
  1369. 'code-hint.com': '.fw-bold .link-light',
  1370. 'codefaq.info': '.aa-link',
  1371. 'codefaq.ru': '.aa-link',
  1372. 'codegear.dev': 'p.text-right > a',
  1373. 'codegrepr.com': 'div.content-text > p > a',
  1374. 'dev-answers.com': 'div.post-info > span > a',
  1375. 'errorsandanswers.com': '#source > a',
  1376. 'generacodice.com': '#fontePrincipale > a.link', // site offline / site not found / 2022-07-06
  1377. 'howtosolves.com': '#question .question .source a',
  1378. 'husl.ru': '.source-link',
  1379. 'im-coder.com': '.origlink > a',
  1380. 'iquestion.pro': '.box-body div:nth-child(3) .pull-right',
  1381. 'isolution.pro': '.box-body div:nth-child(3) .pull-right',
  1382. 'itranslater.com': '.body > div:last-child > a',
  1383. 'javafixing.com': '.entry-content > a:last-of-type',
  1384. 'jpdebug.com': '.text-warning',
  1385. 'knews.vip': '.box-body div:nth-child(3) .pull-right',
  1386. 'linuxfixes.com': '.entry-content > a:nth-last-of-type(2)',
  1387. 'narkive.jp': '#postq > div > div > a',
  1388. 'nuomiphp.com': '.alert-warning a',
  1389. 'overcoder.net': '.info_outlink',
  1390. 'overcoder.ru': '.info_outlink',
  1391. 'phptime.ru': '.float-right>small>a.text-muted',
  1392. 'prog-help.ru': '.eclip > a',
  1393. 'python2.net': 'div.user-box > span.fr > a',
  1394. 'pythonfixing.com': 'article > div.post-body > a:last-of-type',
  1395. 'qarchive.ru': 'cite > a',
  1396. 'qarus.ru': 'em > a',
  1397. 'serveanswer.com': 'a[title="Source"]',
  1398. 'sprosi.pro': '#qsource > a',
  1399. 'stackguides.com': 'a[title="Go to Source post"]',
  1400. 'stackovergo.com': '.qeditacti a:nth-child(2)',
  1401. 'stackru.com': '.q-source',
  1402. 'try2explore.com': 'div.tagsandsource span.source a[target="_blank"]',
  1403. 'ubuntuaa.com': '.post-info a',
  1404. 'ubuntuplace.info': 'div.question-text > a.a-link',
  1405. 'uwenku.com': '.post-info a',
  1406. 'voidcc.com': '.source > a',
  1407. 'web-answers.ru': '.source > a',
  1408. 'wikimho.com': '.page-footer .float-right a',
  1409. 'yingqusp.com': '.container > div > div > div > p > a',
  1410. };
  1411. link = cssSelectors[host] && _tc(cssSelectors[host]);
  1412. console.log(link);
  1413. }
  1414. }
  1415. return link;
  1416. })().then(link => {
  1417. /** Saves the clone url and the source url in a local db */
  1418. function cbufw(u, s) {
  1419. var count = 10;
  1420. var pos = GM_getValue('b2s-pos') || 0;
  1421. var db = JSON.parse(GM_getValue('b2s') || '{}');
  1422. pos = pos > count ? 0 : ++pos;
  1423. GM_setValue('b2s-pos', pos);
  1424. db[pos] = [u, s];
  1425. GM_setValue('b2s', JSON.stringify(db));
  1426. }
  1427.  
  1428. /** Saves the redirect online and local, redirects to source */
  1429. function run(u) {
  1430. console.log('Redirect link: ' + u);
  1431. cbufw(location.href, u) || window.location.replace(u);
  1432. }
  1433.  
  1434. /** Fixes incorrect link parts, redirects to source */
  1435. var fix = (a, b) => (link.match(a)) ? (run(link.replace(a, b)) || true) : false;
  1436.  
  1437. link = link?.href ?? link;
  1438. console.log('Result link: ' + link);
  1439. if (!link || typeof link !== 'string') return;
  1440.  
  1441. //valid links
  1442. if (/^https?:\/\/((pt|ja|ru|es)\.)?stackoverflow\.com\/questions\/([0-9]{1,12})/.test(link) ||
  1443. /^https?:\/\/([a-zA-z\-]+\.)?stackexchange\.com\/questions\/([0-9]{1,12})/.test(link) ||
  1444. /^https?:\/\/(superuser\.com|askubuntu\.com|mathoverflow\.net|serverfault\.com|stackapps\.com)\/questions\/([0-9]{1,12})/.test(link) ||
  1445. /^https?:\/\/[a-zA-z\-]+\.wikipedia\.org\/wiki\/(?!wiki\/)(.+)/.test(link) ||
  1446. /^https?:\/\/github\.com\/(.+)/.test(link) ||
  1447. /^https?:\/\/www\.npmjs\.com\/package\/(.+)/.test(link)) {
  1448. return run(link);
  1449. }
  1450.  
  1451. fix(/^https?:\/\/((pt|ja|ru|es)\.)?stackoverflow\.com\/([a-z]+)\/([0-9]{1,12})/, 'https://$1stackoverflow.com/questions/$4') ||
  1452. fix(/^https?:\/\/([a-z]+\.)?stackexchange\.com\/[qa]\/([0-9]{1,12})/, 'https://$1stackexchange.com/questions/$2') ||
  1453. fix(/^https?:\/\/([a-z]+\.)?stackexchange\.com\/([a-z]+)\/([0-9]{1,12})/, 'https://$2.stackexchange.com/questions/$3') ||
  1454. fix(/^https?:\/\/([a-z]+\.)?(superuser\.com|askubuntu\.com|mathoverflow\.net|serverfault\.com|stackapps\.com)\/([a-z]+)\/([0-9]{1,12})/, 'https://$1$2/questions/$4') ||
  1455. fix(/^https?:\/\/([a-zA-z\-]+\.)wikipedia\.org\/w\/index\.php\?title=(.+)&oldid=([0-9]{1,12})/, 'https://$1wikipedia.org/wiki/$2') ||
  1456. fix(/^https?:\/\/([a-zA-z\-]+\.)wikipedia\.org\/wiki\/wiki\/(.+)/, 'https://$1wikipedia.org/wiki/$2') ||
  1457. fix(/^https?:\/\/www\.github\.com\/(.+)/, 'https://github.com/$1');
  1458.  
  1459. }).catch(console.error.bind(console));