Skip to content

Instantly share code, notes, and snippets.

@padolsey
Created November 19, 2022 22:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save padolsey/790c74b7663bbc5f9424da66a0423b4e to your computer and use it in GitHub Desktop.
Save padolsey/790c74b7663bbc5f9424da66a0423b4e to your computer and use it in GitHub Desktop.
Be careful.....
// ==UserScript==
// @name Mastodon Link To Own Instance
// @version 0.1
// @description Adds link to your own instance next to a mastadon
// @author You
// @match *://*/*
// @grant none
// ==/UserScript==
(function() {
// Minified dom find-replace thingy i made ages ago
/**
* findAndReplaceDOMText v 0.4.6
* @author James Padolsey http://james.padolsey.com
* @license http://unlicense.org/UNLICENSE
*
* Matches the text of a DOM node against a regular expression
* and replaces each match (or node-separated portions of the match)
* in the specified element.
*/
!function(e,t){"object"==typeof module&&module.exports?module.exports=t():"function"==typeof define&&define.amd?define(t):e.findAndReplaceDOMText=t()}(this,(function(){var e="first",t=document,n={}.hasOwnProperty;function r(){return i.apply(null,arguments)||o.apply(null,arguments)}function i(e,t,n,i,d){if(t&&!t.nodeType&&arguments.length<=2)return!1;var a,s="function"==typeof n;s&&(a=n,n=function(e,t){return a(e.text,t.startIndex)});var p=o(t,{find:e,wrap:s?null:n,replace:s?n:"$"+(i||"&"),prepMatch:function(e,t){if(!e[0])throw"findAndReplaceDOMText cannot handle zero-length matches";if(i>0){var n=e[i];e.index+=e[0].indexOf(n),e[0]=n}return e.endIndex=e.index+e[0].length,e.startIndex=e.index,e.index=t,e},filterElements:d});return r.revert=function(){return p.revert()},!0}function o(e,t){return new d(e,t)}function d(e,t){var i=t.preset&&r.PRESETS[t.preset];if(t.portionMode=t.portionMode||"retain",i)for(var o in i)n.call(i,o)&&!n.call(t,o)&&(t[o]=i[o]);this.node=e,this.options=t,this.prepMatch=t.prepMatch||this.prepMatch,this.reverts=[],this.matches=this.search(),this.matches.length&&this.processMatches()}return r.NON_PROSE_ELEMENTS={br:1,hr:1,script:1,style:1,img:1,video:1,audio:1,canvas:1,svg:1,map:1,object:1,input:1,textarea:1,select:1,option:1,optgroup:1,button:1},r.NON_CONTIGUOUS_PROSE_ELEMENTS={address:1,article:1,aside:1,blockquote:1,dd:1,div:1,dl:1,fieldset:1,figcaption:1,figure:1,footer:1,form:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,header:1,hgroup:1,hr:1,main:1,nav:1,noscript:1,ol:1,output:1,p:1,pre:1,section:1,ul:1,br:1,li:1,summary:1,dt:1,details:1,rp:1,rt:1,rtc:1,script:1,style:1,img:1,video:1,audio:1,canvas:1,svg:1,map:1,object:1,input:1,textarea:1,select:1,option:1,optgroup:1,button:1,table:1,tbody:1,thead:1,th:1,tr:1,td:1,caption:1,col:1,tfoot:1,colgroup:1},r.NON_INLINE_PROSE=function(e){return n.call(r.NON_CONTIGUOUS_PROSE_ELEMENTS,e.nodeName.toLowerCase())},r.PRESETS={prose:{forceContext:r.NON_INLINE_PROSE,filterElements:function(e){return!n.call(r.NON_PROSE_ELEMENTS,e.nodeName.toLowerCase())}}},r.Finder=d,d.prototype={search:function(){var e,t=0,n=0,r=this.options.find,i=this.getAggregateText(),o=[],d=this;return r="string"==typeof r?RegExp(String(r).replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1"),"g"):r,function i(a){for(var s=0,p=a.length;s<p;++s){var h=a[s];if("string"==typeof h){if(r.global)for(;e=r.exec(h);)o.push(d.prepMatch(e,t++,n));else(e=h.match(r))&&o.push(d.prepMatch(e,0,n));n+=h.length}else i(h)}}(i),o},prepMatch:function(e,t,n){if(!e[0])throw new Error("findAndReplaceDOMText cannot handle zero-length matches");return e.endIndex=n+e.index+e[0].length,e.startIndex=n+e.index,e.index=t,e},getAggregateText:function(){var e=this.options.filterElements,t=this.options.forceContext;return function n(r){if(r.nodeType===Node.TEXT_NODE)return[r.data];if(e&&!e(r))return[];var i=[""],o=0;if(r=r.firstChild)do{if(r.nodeType!==Node.TEXT_NODE){var d=n(r);t&&r.nodeType===Node.ELEMENT_NODE&&(!0===t||t(r))?(i[++o]=d,i[++o]=""):("string"==typeof d[0]&&(i[o]+=d.shift()),d.length&&(i[++o]=d,i[++o]=""))}else i[o]+=r.data}while(r=r.nextSibling);return i}(this.node)},processMatches:function(){var e,t,n,r=this.matches,i=this.node,o=this.options.filterElements,d=[],a=i,s=r.shift(),p=0,h=0,l=[i];e:for(;;){if(a.nodeType===Node.TEXT_NODE&&(!t&&a.length+p>=s.endIndex?t={node:a,index:h++,text:a.data.substring(s.startIndex-p,s.endIndex-p),indexInMatch:0===p?0:p-s.startIndex,indexInNode:s.startIndex-p,endIndexInNode:s.endIndex-p,isEnd:!0}:e&&d.push({node:a,index:h++,text:a.data,indexInMatch:p-s.startIndex,indexInNode:0}),!e&&a.length+p>s.startIndex&&(e={node:a,index:h++,indexInMatch:0,indexInNode:s.startIndex-p,endIndexInNode:s.endIndex-p,text:a.data.substring(s.startIndex-p,s.endIndex-p)}),p+=a.data.length),n=a.nodeType===Node.ELEMENT_NODE&&o&&!o(a),e&&t){if(a=this.replaceMatch(s,e,d,t),p-=t.node.data.length-t.endIndexInNode,e=null,t=null,d=[],h=0,!(s=r.shift()))break}else if(!n&&(a.firstChild||a.nextSibling)){a.firstChild?(l.push(a),a=a.firstChild):a=a.nextSibling;continue}for(;;){if(a.nextSibling){a=a.nextSibling;break}if((a=l.pop())===i)break e}}},revert:function(){for(var e=this.reverts.length;e--;)this.reverts[e]();this.reverts=[]},prepareReplacementString:function(t,n,r){var i=this.options.portionMode;return i===e&&n.indexInMatch>0?"":(t=t.replace(/\$(\d+|&|`|')/g,(function(e,t){var n;switch(t){case"&":n=r[0];break;case"`":n=r.input.substring(0,r.startIndex);break;case"'":n=r.input.substring(r.endIndex);break;default:n=r[+t]||""}return n})),i===e?t:n.isEnd?t.substring(n.indexInMatch):t.substring(n.indexInMatch,n.indexInMatch+n.text.length))},getPortionReplacementNode:function(e,n){var r=this.options.replace||"$&",i=this.options.wrap,o=this.options.wrapClass;if(i&&i.nodeType){var d=t.createElement("div");d.innerHTML=i.outerHTML||(new XMLSerializer).serializeToString(i),i=d.firstChild}if("function"==typeof r)return(r=r(e,n))&&r.nodeType?r:t.createTextNode(String(r));var a="string"==typeof i?t.createElement(i):i;return a&&o&&(a.className=o),(r=t.createTextNode(this.prepareReplacementString(r,e,n))).data&&a?(a.appendChild(r),a):r},replaceMatch:function(e,n,r,i){var o,d,a=n.node,s=i.node;if(a===s){var p=a;n.indexInNode>0&&(o=t.createTextNode(p.data.substring(0,n.indexInNode)),p.parentNode.insertBefore(o,p));var h=this.getPortionReplacementNode(i,e);return p.parentNode.insertBefore(h,p),i.endIndexInNode<p.length&&(d=t.createTextNode(p.data.substring(i.endIndexInNode)),p.parentNode.insertBefore(d,p)),p.parentNode.removeChild(p),this.reverts.push((function(){o===h.previousSibling&&o.parentNode.removeChild(o),d===h.nextSibling&&d.parentNode.removeChild(d),h.parentNode.replaceChild(p,h)})),h}o=t.createTextNode(a.data.substring(0,n.indexInNode)),d=t.createTextNode(s.data.substring(i.endIndexInNode));for(var l=this.getPortionReplacementNode(n,e),c=[],f=0,u=r.length;f<u;++f){var x=r[f],N=this.getPortionReplacementNode(x,e);x.node.parentNode.replaceChild(N,x.node),this.reverts.push(function(e,t){return function(){t.parentNode.replaceChild(e.node,t)}}(x,N)),c.push(N)}var g=this.getPortionReplacementNode(i,e);return a.parentNode.insertBefore(o,a),a.parentNode.insertBefore(l,a),a.parentNode.removeChild(a),s.parentNode.insertBefore(g,s),s.parentNode.insertBefore(d,s),s.parentNode.removeChild(s),this.reverts.push((function(){o.parentNode.removeChild(o),l.parentNode.replaceChild(a,l),d.parentNode.removeChild(d),g.parentNode.replaceChild(s,g)})),g}},r}));
const MY_INSTANCE = 'https://angelou.club';
function check() {
// not worth doing stuff unless mastodon is _at least_ mentioned somehow
if (/mastodon/.test(document.documentElement.innerHTML)) {
findAndReplaceDOMText(document.body, {
preset: 'prose',
find: /@\S+(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]/,
replace: (portion, match) => {
if (portion.node.parentNode.__mastoSeen__) return portion.text;
const a = document.createElement('a');
a.style = ' color: black; background: #f9e72d; border-radius: 2px; ';
a.href = MY_INSTANCE + '/web/' + match[0];
a.textContent = portion.text;
a.__mastoSeen__ = true;
return a;
}
});
}
}
// bleehhhhhhhhhh most masto instances hotload out content i.e. not discernable events really
// may as well keep checking, because it's pretty cheap
setInterval(check, 5000);
setTimeout(check, 1000);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment