您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Конвертирует текст в виде ссылок в реальные ссылки, на которые можно кликнуть.
- // ==UserScript==
- // @name Text to URL
- // @namespace https://github.com/T1mL3arn
- // @author T1mL3arn
- // @description:ru Конвертирует текст в виде ссылок в реальные ссылки, на которые можно кликнуть.
- // @description:en Converts url-like text into clickable url.
- // @match *://*/*
- // @version 1.1.1
- // @run-at document-end
- // @license GPLv3
- // @supportURL https://greasyfork.org/en/scripts/367955-text-to-url/feedback
- // @homepageURL https://greasyfork.org/en/scripts/367955-text-to-url
- // @description Конвертирует текст в виде ссылок в реальные ссылки, на которые можно кликнуть.
- // ==/UserScript==
- ///TODO improve ereg to match URI syntax (https://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Generic_syntax) ?
- let linkEreg = /(?:https|http|ftp|file):\/\/.+?(?=[,.]?(?:\s|$))/gi;
- let linkEregLocal = /(?:https|http|ftp|file):\/\/.+?(?=[,.]?(?:\s|$))/i;
- let obsOptions = { childList: true, subtree: true };
- let wrappedCount = 0;
- function printWrappedCount() {
- if (wrappedCount > 0) {
- console.info(`[ ${GM_info.script.name} ] wrapped links count: ${wrappedCount}`);
- }
- }
- let obs = new MutationObserver((changes, obs) => {
- wrappedCount = 0;
- obs.disconnect();
- changes.forEach((change) => change.addedNodes.forEach((node) => fixLinks(node)) );
- obs.observe(document.body, obsOptions);
- printWrappedCount();
- });
- function fixLinks(node) {
- ///TODO consider not to run script for form and input elements!
- ///TODO also search syntax-highlith libraries and also exclude them
- if (node.tagName != 'A' && node.tagName != 'SCRIPT') {
- // this is a text node
- if (node.nodeType === 3) {
- let content = node.textContent;
- if (content && content != '') {
- if (linkEregLocal.test(content)) {
- wrapTextNode(node);
- }
- }
- } else if (node.childNodes && node.childNodes.length > 0) {
- node.childNodes.forEach(fixLinks);
- }
- }
- }
- function wrapTextNode(node) {
- let match;
- let sibling = node;
- let content = node.textContent;
- linkEreg.lastIndex = 0;
- while ((match = linkEreg.exec(content)) != null) {
- let fullMatch = match[0];
- let anchor = document.createElement('a');
- let range = document.createRange();
- range.setStart(sibling, linkEreg.lastIndex - match[0].length);
- range.setEnd(sibling, linkEreg.lastIndex);
- range.surroundContents(anchor);
- wrappedCount++;
- anchor.href = fullMatch;
- anchor.textContent = fullMatch;
- anchor.target = '_blank';
- anchor.title = 'open link in a new tab';
- anchor.setAttribute('ttu-wrapped', '1');
- linkEreg.lastIndex = 0;
- sibling = getNextTextSibling(anchor);
- if (sibling == null)
- break;
- else
- content = sibling.textContent;
- }
- }
- function getNextTextSibling(node) {
- let next = node.nextSibling;
- while (next != null) {
- if (next.nodeType == 3)
- return next;
- else
- next = node.nextSibling;
- }
- return null;
- }
- fixLinks(document.body);
- printWrappedCount();
- obs.observe(document.body, obsOptions);