Enhancement Userscript for LIHKG

An Enhancement Userscript for LIHKG

当前为 2021-06-10 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Enhancement Userscript for LIHKG
  3. // @version 0.3
  4. // @description An Enhancement Userscript for LIHKG
  5. // @include /https?\:\/\/lihkg\.com/
  6. // @icon https://www.google.com/s2/favicons?domain=lihkg.com
  7. // @grant GM_addStyle
  8. // @namespace https://gf.qytechs.cn/users/371179
  9. // ==/UserScript==
  10. (function() {
  11. 'use strict';
  12. GM_addStyle(`
  13. .EGBBkGyEbfIEpHMLTW84H:not([dragmode]),.EGBBkGyEbfIEpHMLTW84H[dragmode="text"]{position:fixed;left:-9999px;top:-9999px;width:2px;height:2px;}
  14. div[contenteditable] p>img~br:last-child,div[contenteditable] p>a~br:last-child,div[contenteditable] p>div~br:last-child{content:'';}
  15. `)
  16. //fix copy editing
  17.  
  18. var testBlockElm = function(elm) {
  19. if (elm && elm.nodeType == 1) {
  20. switch (elm.tagName) {
  21. case 'DIV':
  22. case 'P':
  23. case 'BLOCKQUOTE':
  24. return true;
  25.  
  26. default:
  27. return false;
  28.  
  29. }
  30.  
  31. }
  32. }
  33.  
  34. var getElementText = function(el) {
  35. var text = '';
  36. // Text node (3) or CDATA node (4) - return its text
  37. if ((el.nodeType === 3) || (el.nodeType === 4)) {
  38. text = el.nodeValue;
  39. // If node is an element (1) and an img, input[type=image], or area element, return its alt text
  40. } else if ((el.nodeType === 1) && (
  41. (el.tagName.toLowerCase() == 'img') ||
  42. (el.tagName.toLowerCase() == 'area') ||
  43. ((el.tagName.toLowerCase() == 'input') && el.getAttribute('type') && (el.getAttribute('type').toLowerCase() == 'image'))
  44. )) {
  45. text = el.getAttribute('alt') || '';
  46. if (el.tagName.toLowerCase() == 'img' && text == '' && el.getAttribute('data-original')) {
  47. text = '[img]' + el.getAttribute('data-original') + '[/img]';
  48. } else if (el.tagName.toLowerCase() == 'img' && text == '' && el.getAttribute('src')) {
  49. text = '[img]' + el.getAttribute('src') + '[/img]';
  50. }
  51. // Traverse children unless this is a script or style element
  52. } else if ((el.nodeType === 1) && (
  53. (el.tagName.toLowerCase() == 'br')
  54. )) {
  55. text = '\n';
  56. // Traverse children unless this is a script or style element
  57. } else if ((el.nodeType === 1) && !el.tagName.match(/^(script|style)$/i)) {
  58. var children = el.childNodes;
  59.  
  60. if (el && testBlockElm(el) && el.previousSibling ? testBlockElm(el.previousSibling) : false) {
  61. text += '\n'
  62. }
  63. if (el.tagName.toLowerCase() == 'blockquote') {
  64. text += '[quote]'
  65. }
  66. for (var i = 0, l = children.length; i < l; i++) {
  67. text += getElementText(children[i]);
  68. }
  69. if (el.tagName.toLowerCase() == 'blockquote') {
  70. text += '[/quote]'
  71. }
  72.  
  73. }
  74. return text;
  75. };
  76.  
  77.  
  78. document.cssAll = function() {
  79.  
  80. var s = document.querySelectorAll.apply(this, arguments)
  81.  
  82. s = Array.prototype.slice.call(s, 0)
  83. return s
  84. }
  85.  
  86. function urlConvert(url) {
  87. var src = url.replace(/\w+\:\/\//, '')
  88. var replacements = [...src.matchAll(/[\w\.]+/g)].filter((t) => /\./.test(t))
  89. if (replacements.length > 1) {
  90. replacements.length--;
  91.  
  92. }
  93. replacements.forEach((s) => {
  94. src = src.replace(s, '')
  95. })
  96.  
  97. src = src.replace(/\/+/g, '/')
  98.  
  99. return src;
  100.  
  101. }
  102.  
  103. var emoji = {};
  104. setTimeout(function() {
  105. console.log(emoji)
  106. }, 1500)
  107.  
  108. setInterval(() => {
  109.  
  110. document.cssAll('img[src*="lihkg.com"][alt]:not([title])').forEach(function(imgElm) {
  111. var src = imgElm.getAttribute('src');
  112. var erc = urlConvert(src)
  113. var imgAlt = imgElm.getAttribute('alt') || "";
  114. if (/^[\x20-\x7E]+$/.test(imgAlt) && /\W/.test(imgAlt)) {
  115. emoji[erc] = imgAlt.trim()
  116. }
  117.  
  118. imgElm.setAttribute('title', imgAlt)
  119.  
  120. })
  121.  
  122.  
  123. document.cssAll('a[href*="profile/"]:not([href*="//"]):not([title])').forEach(function(aElm) {
  124. aElm.setAttribute('title', aElm.getAttribute('href'))
  125. })
  126.  
  127. document.cssAll('[data-ic~="hkgmoji"]:not([title])>img[src*="lihkg.com"]:not([alt])').forEach(function(imgElm) {
  128. var src = imgElm.getAttribute('src');
  129. var erc = urlConvert(src)
  130. var text = emoji[erc] ? emoji[erc] : "[img]" + erc + "[/img]"
  131. imgElm.parentNode.setAttribute('title', text)
  132. imgElm.setAttribute('alt', text)
  133.  
  134.  
  135. })
  136.  
  137. document.cssAll('a[href*="local.lihkg.com"]>img:not([anchored])').forEach(function(img) {
  138. img.setAttribute('anchored', 'true')
  139.  
  140.  
  141. var originalSrc = img.getAttribute('src') || img.getAttribute('data-original') || ""
  142. var newSrc = originalSrc.replace('local.lihkg.com', 'cdn.lihkg.com');
  143.  
  144. if (newSrc && originalSrc != newSrc) {
  145.  
  146. // console.log(originalSrc, newSrc)
  147.  
  148. var fx = function() {
  149. if (img.complete == false) return setTimeout(fx, 33);
  150.  
  151. if (img.currentSrc == "") {
  152.  
  153. var b = img.cloneNode(false);
  154. b.removeAttribute('data-original');
  155. b.removeAttribute('data-src');
  156.  
  157. if (b.getAttribute('alt') == "") b.removeAttribute('alt')
  158. if (b.getAttribute('title') == "") b.removeAttribute('title')
  159.  
  160. b.setAttribute('src', newSrc);
  161. img.parentNode.replaceChild(b, img)
  162.  
  163. if (b.parentNode.getAttribute('href')) {
  164. b.parentNode.setAttribute('href', b.parentNode.getAttribute('href').replace(originalSrc, newSrc));
  165. if (b.nextElementSibling && b.nextElementSibling.hasAttribute('data-error')) b.nextElementSibling.parentNode.removeChild(b.nextElementSibling);
  166. if (b.nextElementSibling && b.nextElementSibling.outerHTML.toLocaleLowerCase() == '<ins></ins>') b.nextElementSibling.parentNode.removeChild(b.nextElementSibling);
  167.  
  168.  
  169.  
  170. }
  171.  
  172. b.removeAttribute('anchored')
  173.  
  174.  
  175. }
  176.  
  177. }
  178. fx();
  179.  
  180.  
  181. }
  182.  
  183. })
  184.  
  185.  
  186. document.cssAll('div[contenteditable] div[data-ic][contenteditable="false"]').forEach((elm) => {
  187.  
  188. elm.removeAttribute('contenteditable')
  189. })
  190.  
  191.  
  192. document.cssAll('img[src]:not([alt]),img[src][alt=""]').forEach((el) => {
  193.  
  194. if (el.getAttribute('alt') || el.getAttribute('title')) return;
  195.  
  196. var text = '';
  197. if (el.tagName.toLowerCase() == 'img' && el.getAttribute('data-original')) {
  198. text = '[img]' + el.getAttribute('data-original') + '[/img]';
  199. } else if (el.tagName.toLowerCase() == 'img' && el.getAttribute('src')) {
  200. text = '[img]' + el.getAttribute('src') + '[/img]';
  201. }
  202. if (text) el.setAttribute('alt', text)
  203. if (text) el.setAttribute('title', text)
  204.  
  205. })
  206.  
  207.  
  208.  
  209. }, 33)
  210.  
  211.  
  212. var makePlain = false;
  213. document.addEventListener('drop', function(evt) {
  214. // console.log(evt, makePlain, evt.target)
  215.  
  216. var p = evt.target;
  217. var contenteditable = false;
  218. while (p) {
  219. if (p.hasAttribute('contenteditable') && p.getAttribute('contenteditable') != 'false') {
  220. contenteditable = true;
  221. break;
  222. }
  223. p = p.parentNode;
  224.  
  225. }
  226.  
  227. if (contenteditable) {
  228.  
  229. if (makePlain && evt.dataTransfer.getData('text/html')) {
  230.  
  231. var text = evt.dataTransfer.getData('text/html');
  232.  
  233.  
  234. setTimeout(function() {
  235. var sel = window.getSelection();
  236. if (sel.getRangeAt && sel.rangeCount) {
  237.  
  238.  
  239. var range = sel.getRangeAt(0);
  240.  
  241. var cloneContents = range.cloneContents();
  242.  
  243.  
  244. var hh = document.createElement('html')
  245. hh.innerHTML = text;
  246. console.log(hh.cloneNode(true))
  247. var hhPlain = getElementText(hh)
  248.  
  249. console.log(hhPlain)
  250. hh.innerText = hhPlain
  251.  
  252.  
  253. if (cloneContents.textContent !== hhPlain) {
  254.  
  255. range.deleteContents();
  256.  
  257. var trueHTML = '<p>' + hh.innerHTML.toLowerCase().replace(/<br\s*\/?>/g, "<br></p><p>") + "</p>"
  258.  
  259. console.log(trueHTML)
  260.  
  261. document.execCommand('insertHTML', false, trueHTML);
  262. }
  263.  
  264. }
  265.  
  266. }, 10);
  267. }
  268.  
  269. }
  270.  
  271.  
  272. }, true)
  273.  
  274.  
  275. document.addEventListener('dragstart', function(evt) {
  276. var editable = document.querySelector('div[contenteditable]')
  277. var dragFrom = evt.target
  278. if (editable && dragFrom) {
  279.  
  280. if (editable == dragFrom || editable.contains(dragFrom)) {
  281.  
  282. } else {
  283. makePlain = true;
  284.  
  285. }
  286.  
  287. }
  288. // console.log(evt)
  289. }, false);
  290.  
  291.  
  292. document.addEventListener('dragend', function(evt) {
  293. if (Event.prototype._preventDefault) {
  294. Event.prototype.preventDefault = Event.prototype._preventDefault
  295. Event.prototype._preventDefault = null
  296.  
  297. }
  298. setTimeout(function() {
  299. makePlain = false;
  300. }, 77);
  301. }, false);
  302.  
  303. document.addEventListener('drop', function(evt) {
  304.  
  305. setTimeout(function() {
  306. makePlain = false;
  307. }, 77);
  308. if (Event.prototype._preventDefault) {
  309. Event.prototype.preventDefault = Event.prototype._preventDefault
  310. Event.prototype._preventDefault = null
  311. }
  312.  
  313. var dropZone = document.querySelector('.EGBBkGyEbfIEpHMLTW84H');
  314. if (!dropZone) return;
  315. dropZone.removeAttribute('dragmode');
  316.  
  317.  
  318. }, true)
  319.  
  320.  
  321.  
  322. document.addEventListener('dragenter', function(evt) {
  323.  
  324. var dropZone = document.querySelector('.EGBBkGyEbfIEpHMLTW84H');
  325.  
  326.  
  327.  
  328. var isFileTransfer = false;
  329. if (evt.dataTransfer.types) {
  330. for (var i = 0; i < evt.dataTransfer.types.length; i++) {
  331. if (evt.dataTransfer.types[i] == "Files") {
  332. isFileTransfer = true;
  333. break;
  334. }
  335. }
  336. }
  337.  
  338. if (!isFileTransfer) {
  339.  
  340. if (dropZone)
  341. dropZone.setAttribute('dragmode', 'text');
  342. // evt.dataTransfer.effectAllowed='copy';
  343. if (!Event.prototype._preventDefault) {
  344. Event.prototype._preventDefault = Event.prototype.preventDefault;
  345. Event.prototype.preventDefault = function() {
  346. if (this.type == 'dragover') {
  347.  
  348. } else {
  349. return this._preventDefault();
  350. }
  351. //console.log(this)
  352. };
  353. }
  354.  
  355.  
  356.  
  357. } else {
  358. makePlain = false;
  359. if (dropZone)
  360. dropZone.setAttribute('dragmode', 'file');
  361.  
  362.  
  363. }
  364. // console.log('dragenter',!isFileTransfer)
  365.  
  366.  
  367.  
  368. }, false)
  369.  
  370.  
  371.  
  372.  
  373. // Your code here...
  374. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址