// ==UserScript== // @name Enhancement Userscript for LIHKG // @version 0.2 // @description An Enhancement Userscript for LIHKG // @include /https?\:\/\/lihkg\.com/ // @icon https://www.google.com/s2/favicons?domain=lihkg.com // @grant GM_addStyle // @namespace https://greasyfork.org/users/371179 // @downloadURL none // ==/UserScript== (function() { 'use strict'; GM_addStyle(` .EGBBkGyEbfIEpHMLTW84H:not([dragmode]),.EGBBkGyEbfIEpHMLTW84H[dragmode="text"]{position:fixed;left:-9999px;top:-9999px;width:2px;height:2px;} div[contenteditable] p>img~br:last-child,div[contenteditable] p>a~br:last-child,div[contenteditable] p>div~br:last-child{content:'';} `) //fix copy editing var getElementText = function(el) { var text = ''; // Text node (3) or CDATA node (4) - return its text if ((el.nodeType === 3) || (el.nodeType === 4)) { text = el.nodeValue; // If node is an element (1) and an img, input[type=image], or area element, return its alt text } else if ((el.nodeType === 1) && ( (el.tagName.toLowerCase() == 'img') || (el.tagName.toLowerCase() == 'area') || ((el.tagName.toLowerCase() == 'input') && el.getAttribute('type') && (el.getAttribute('type').toLowerCase() == 'image')) )) { text = el.getAttribute('alt') || ''; if (el.tagName.toLowerCase() == 'img' && text == '' && el.getAttribute('src')) { text = '[img]' + el.getAttribute('src') + '[/img]'; } // Traverse children unless this is a script or style element } else if ((el.nodeType === 1) && ( (el.tagName.toLowerCase() == 'br') )) { text = '\n'; // Traverse children unless this is a script or style element } else if ((el.nodeType === 1) && !el.tagName.match(/^(script|style)$/i)) { var children = el.childNodes; for (var i = 0, l = children.length; i < l; i++) { text += getElementText(children[i]); } } return text; }; document.cssAll = function() { var s = document.querySelectorAll.apply(this, arguments) s = Array.prototype.slice.call(s, 0) return s } function urlConvert(url) { var src = url.replace(/\w+\:\/\//, '') var replacements = [...src.matchAll(/[\w\.]+/g)].filter((t) => /\./.test(t)) if (replacements.length > 1) { replacements.length--; } replacements.forEach((s) => { src = src.replace(s, '') }) src = src.replace(/\/+/g, '/') return src; } var emoji = {}; setInterval(() => { document.cssAll('img[src*="lihkg.com"][alt]:not([title])').forEach(function(imgElm) { var src = imgElm.getAttribute('src'); var erc = urlConvert(src) var imgAlt = imgElm.getAttribute('alt') || ""; if (/^[\x20-\x7E]+$/.test(imgAlt) && /\#/.test(imgAlt)) { emoji[erc] = imgAlt.trim() } imgElm.setAttribute('title', imgAlt) }) document.cssAll('a[href*="profile/"]:not([href*="//"]):not([title])').forEach(function(aElm) { aElm.setAttribute('title', aElm.getAttribute('href')) }) document.cssAll('[data-ic~="hkgmoji"]:not([title])>img[src*="lihkg.com"]:not([alt])').forEach(function(imgElm) { var src = imgElm.getAttribute('src'); var erc = urlConvert(src) var text = emoji[erc] ? emoji[erc] : "[img]" + erc + "[/img]" imgElm.parentNode.setAttribute('title', text) imgElm.setAttribute('alt', text) }) document.cssAll('a[href*="local.lihkg.com"]>img:not([anchored])').forEach(function(img) { img.setAttribute('anchored', 'true') var originalSrc = img.getAttribute('src') || img.getAttribute('data-original') || "" var newSrc = originalSrc.replace('local.lihkg.com', 'cdn.lihkg.com'); if (newSrc && originalSrc != newSrc) { console.log(originalSrc, newSrc) var fx = function() { if (img.complete == false) return setTimeout(fx, 33); if (img.currentSrc == "") { var b = img.cloneNode(false); b.removeAttribute('data-original'); b.removeAttribute('data-src'); if (b.getAttribute('alt') == "") b.removeAttribute('alt') if (b.getAttribute('title') == "") b.removeAttribute('title') b.setAttribute('src', newSrc); img.parentNode.replaceChild(b, img) if (b.parentNode.getAttribute('href')) { b.parentNode.setAttribute('href', b.parentNode.getAttribute('href').replace(originalSrc, newSrc)); if (b.nextElementSibling && b.nextElementSibling.hasAttribute('data-error')) b.nextElementSibling.parentNode.removeChild(b.nextElementSibling); if (b.nextElementSibling && b.nextElementSibling.outerHTML.toLocaleLowerCase() == '') b.nextElementSibling.parentNode.removeChild(b.nextElementSibling); } b.removeAttribute('anchored') } } fx(); } }) document.cssAll('div[contenteditable] div[data-ic][contenteditable="false"]').forEach((elm) => { elm.removeAttribute('contenteditable') }) }, 33) var makePlain = false; document.addEventListener('drop', function(evt) { console.log(evt, makePlain, evt.target) var p = evt.target; var contenteditable = false; while (p) { if (p.hasAttribute('contenteditable') && p.getAttribute('contenteditable') != 'false') { contenteditable = true; break; } p = p.parentNode; } if (contenteditable) { if (makePlain && evt.dataTransfer.getData('text/html')) { var text = evt.dataTransfer.getData('text/html'); setTimeout(function() { var sel = window.getSelection(); if (sel.getRangeAt && sel.rangeCount) { var range = sel.getRangeAt(0); var cloneContents = range.cloneContents(); var hh = document.createElement('html') hh.innerHTML = text; var hhPlain = getElementText(hh) hh.innerText = hhPlain if (cloneContents.textContent !== hhPlain) { range.deleteContents(); document.execCommand('insertHTML', false, '

' + hh.innerHTML.toLowerCase().replace("
", "
").replace("
", "
").replace("
", "

") + "

"); } } }, 10); } } }, true) document.addEventListener('dragstart', function(evt) { var editable = document.querySelector('div[contenteditable]') var dragFrom = evt.target if (editable && dragFrom) { if (editable == dragFrom || editable.contains(dragFrom)) { } else { makePlain = true; } } console.log(evt) }, false); document.addEventListener('dragend', function(evt) { if (Event.prototype._preventDefault) { Event.prototype.preventDefault = Event.prototype._preventDefault Event.prototype._preventDefault = null } setTimeout(function() { makePlain = false; }, 77); }, false); document.addEventListener('drop', function(evt) { setTimeout(function() { makePlain = false; }, 77); if (Event.prototype._preventDefault) { Event.prototype.preventDefault = Event.prototype._preventDefault Event.prototype._preventDefault = null } var dropZone = document.querySelector('.EGBBkGyEbfIEpHMLTW84H'); if (!dropZone) return; dropZone.removeAttribute('dragmode'); }, true) document.addEventListener('dragenter', function(evt) { var dropZone = document.querySelector('.EGBBkGyEbfIEpHMLTW84H'); var isFileTransfer = false; if (evt.dataTransfer.types) { for (var i = 0; i < evt.dataTransfer.types.length; i++) { if (evt.dataTransfer.types[i] == "Files") { isFileTransfer = true; break; } } } if (!isFileTransfer) { if (dropZone) dropZone.setAttribute('dragmode', 'text'); // evt.dataTransfer.effectAllowed='copy'; if (!Event.prototype._preventDefault) { Event.prototype._preventDefault = Event.prototype.preventDefault; Event.prototype.preventDefault = function() { if (this.type == 'dragover') { } else { return this._preventDefault(); } //console.log(this) }; } } else { makePlain = false; if (dropZone) dropZone.setAttribute('dragmode', 'file'); } // console.log('dragenter',!isFileTransfer) }, false) // Your code here... })();