@filteringdev/namulink 18.1.3 → 19.0.0-build.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,26 +1,29 @@
1
1
  // ==UserScript==
2
2
  // @name NamuLink
3
- // @encoding utf-8
3
+ //
4
4
  // @namespace https://github.com/FilteringDev/NamuLink
5
5
  // @homepageURL https://github.com/FilteringDev/NamuLink
6
6
  // @supportURL https://github.com/FilteringDev/NamuLink/issues
7
7
  // @updateURL https://cdn.jsdelivr.net/npm/@filteringdev/namulink@latest/dist/NamuLink.user.js
8
8
  // @downloadURL https://cdn.jsdelivr.net/npm/@filteringdev/namulink@latest/dist/NamuLink.user.js
9
- // @license MIT
9
+ // @license MPL-2.0
10
10
  //
11
- // @version 18.1.3
11
+ // @version 19.0.0-build.0
12
12
  // @author PiQuark6046 and contributors
13
13
  //
14
- // @match https://namu.wiki/*
15
- //
16
- // @description NamuLink blocks the PowerLink advertisement on NamuWiki.
17
- // @description:ko NamuLink는 나무위키에 있는 파워링크 광고를 차단합니다.
18
- //
19
14
  // @grant unsafeWindow
20
15
  // @run-at document-start
16
+ //
17
+ // @description NamuLink allows AdGuard, uBlock Origin, Brave and ABP to resist against Ad-Shield quickly.
18
+ // @description:ko NamuLink는 AdGuard, uBlock Origin, Brave 와 ABP가 애드쉴드에 빠르게 저항할 수 있도록 합니다.
19
+ // @description:ja NamuLinkを使うと、AdGuard, uBlock Origin, Brave, およびABPがAd-Shieldに素早く対抗できます。
20
+ //
21
+ // @match *://namu.wiki/*
22
+ // @match *://*.namu.wiki/*
21
23
  // ==/UserScript==
22
- // Used libraries:
23
- (()=>{function w(t={}){let e=x(t),p=e.Events.Navigate,f=e.Events.Rendered,g=o=>{window.dispatchEvent(new CustomEvent(p,{detail:o}))},l=o=>{window.dispatchEvent(new CustomEvent(f,{detail:o}))},a=window.location.href,n=0,r=!1,d=o=>{if(r)return;let u=window.location.href;if(u===a)return;let S=a;a=u;let h=++n;g({Seq:h,From:S,To:u,Cause:o}),(async()=>{let m=e.Root();if(!m){if(h!==n||r)return;l({Seq:h,Url:u,Ok:!0});return}let y=await M({Root:m,StableForMs:e.StableForMs,SampleWindowMs:e.SampleWindowMs,Threshold:e.Threshold,TimeoutMs:e.TimeoutMs,Ignore:e.IgnoreMutation});h!==n||r||l({Seq:h,Url:u,Ok:y})})()},s=o=>{let u=history[o].bind(history);Object.defineProperty(history,o,{value:(...h)=>{let m=u(...h);return queueMicrotask(()=>d(o)),m},configurable:!0,writable:!0})};s("pushState"),s("replaceState");let i=()=>d("popstate");window.addEventListener("popstate",i);let c=()=>d("hashchange");return e.WatchHashChange&&window.addEventListener("hashchange",c),queueMicrotask(()=>{if(r)return;let o=++n;g({Seq:o,From:null,To:window.location.href,Cause:"init"}),(async()=>{let u=e.Root();if(!u){if(o!==n||r)return;l({Seq:o,Url:window.location.href,Ok:!0});return}let S=await M({Root:u,StableForMs:e.StableForMs,SampleWindowMs:e.SampleWindowMs,Threshold:e.Threshold,TimeoutMs:e.TimeoutMs,Ignore:e.IgnoreMutation});o!==n||r||l({Seq:o,Url:window.location.href,Ok:S})})()}),()=>{r=!0,window.removeEventListener("popstate",i),e.WatchHashChange&&window.removeEventListener("hashchange",c)}}function b(t){if(t.type==="attributes"){let e=t.attributeName??"";if(e==="class"||e==="style"||e.startsWith("aria-")||e.startsWith("data-"))return!0}return!1}function x(t){return{Root:t.Root??(()=>document.querySelector("#app")??document.body),StableForMs:t.StableForMs??900,SampleWindowMs:t.SampleWindowMs??900,Threshold:t.Threshold??3,TimeoutMs:t.TimeoutMs??12e3,IgnoreMutation:t.IgnoreMutation??b,WatchHashChange:t.WatchHashChange??!0,Events:{Navigate:t.Events?.Navigate??"SpaNavigate",Rendered:t.Events?.Rendered??"SpaRendered"}}}async function M(t){let e=[],p=performance.now(),f=!1,g=new MutationObserver(a=>{let n=performance.now();for(let s of a){if(t.Ignore?.(s))continue;let i=1;s.type==="childList"&&(i=2),e.push({T:n,Score:i})}let r=n-t.SampleWindowMs;for(;e.length&&e[0].T<r;)e.shift();e.reduce((s,i)=>s+i.Score,0)>t.Threshold&&(p=n)});g.observe(t.Root,{subtree:!0,childList:!0,attributes:!0,characterData:!0});let l=performance.now();return await new Promise(a=>{let n=()=>{if(f)return;let r=performance.now();if(r-p>=t.StableForMs){f=!0,g.disconnect(),a(!0);return}if(r-l>=t.TimeoutMs){f=!0,g.disconnect(),a(!1);return}setTimeout(n,100)};setTimeout(n,0)})}function E(){let t=`
24
+
25
+
26
+ (()=>{function w(r={}){let e=R(r),p=e.Events.Navigate,f=e.Events.Rendered,m=a=>{window.dispatchEvent(new CustomEvent(p,{detail:a}))},l=a=>{window.dispatchEvent(new CustomEvent(f,{detail:a}))},u=window.location.href,i=0,t=!1,n=a=>{if(t)return;let s=window.location.href;if(s===u)return;let c=u;u=s;let d=++i;m({Seq:d,From:c,To:s,Cause:a}),(async()=>{let y=e.Root();if(!y){if(d!==i||t)return;l({Seq:d,Url:s,Ok:!0});return}let S=await M({Root:y,StableForMs:e.StableForMs,SampleWindowMs:e.SampleWindowMs,Threshold:e.Threshold,TimeoutMs:e.TimeoutMs,Ignore:e.IgnoreMutation});d!==i||t||l({Seq:d,Url:s,Ok:S})})()},o=a=>{let s=history[a].bind(history);Object.defineProperty(history,a,{value:(...d)=>{let y=s(...d);return queueMicrotask(()=>n(a)),y},configurable:!0,writable:!0})};o("pushState"),o("replaceState");let g=()=>n("popstate");window.addEventListener("popstate",g);let h=()=>n("hashchange");return e.WatchHashChange&&window.addEventListener("hashchange",h),queueMicrotask(()=>{if(t)return;let a=++i;m({Seq:a,From:null,To:window.location.href,Cause:"init"}),(async()=>{let s=e.Root();if(!s){if(a!==i||t)return;l({Seq:a,Url:window.location.href,Ok:!0});return}let c=await M({Root:s,StableForMs:e.StableForMs,SampleWindowMs:e.SampleWindowMs,Threshold:e.Threshold,TimeoutMs:e.TimeoutMs,Ignore:e.IgnoreMutation});a!==i||t||l({Seq:a,Url:window.location.href,Ok:c})})()}),()=>{t=!0,window.removeEventListener("popstate",g),e.WatchHashChange&&window.removeEventListener("hashchange",h)}}function b(r){if(r.type==="attributes"){let e=r.attributeName??"";if(e==="class"||e==="style"||e.startsWith("aria-")||e.startsWith("data-"))return!0}return!1}function R(r){return{Root:r.Root??(()=>document.querySelector("#app")??document.body),StableForMs:r.StableForMs??900,SampleWindowMs:r.SampleWindowMs??900,Threshold:r.Threshold??3,TimeoutMs:r.TimeoutMs??12e3,IgnoreMutation:r.IgnoreMutation??b,WatchHashChange:r.WatchHashChange??!0,Events:{Navigate:r.Events?.Navigate??"SpaNavigate",Rendered:r.Events?.Rendered??"SpaRendered"}}}async function M(r){let e=[],p=performance.now(),f=!1,m=new MutationObserver(u=>{let i=performance.now();for(let o of u){if(r.Ignore?.(o))continue;let g=1;o.type==="childList"&&(g=2),e.push({T:i,Score:g})}let t=i-r.SampleWindowMs;for(;e.length&&e[0].T<t;)e.shift();e.reduce((o,g)=>o+g.Score,0)>r.Threshold&&(p=i)});m.observe(r.Root,{subtree:!0,childList:!0,attributes:!0,characterData:!0});let l=performance.now();return await new Promise(u=>{let i=()=>{if(f)return;let t=performance.now();if(t-p>=r.StableForMs){f=!0,m.disconnect(),u(!0);return}if(t-l>=r.TimeoutMs){f=!0,m.disconnect(),u(!1);return}setTimeout(i,100)};setTimeout(i,0)})}function E(){let r=`
24
27
  self.onmessage = (e) => {
25
28
  const { entries, jobId } = e.data;
26
29
  // entries: Array<[string, number]>
@@ -28,7 +31,7 @@ self.onmessage = (e) => {
28
31
  entries.sort((a, b) => b[1] - a[1]);
29
32
  self.postMessage({ jobId, sorted: entries });
30
33
  };
31
- `;return URL.createObjectURL(new Blob([t],{type:"text/javascript"}))}function W(t){let e=E(),p=Array.from({length:t},()=>new Worker(e));return{Workers:p,dispose(){p.forEach(f=>f.terminate()),URL.revokeObjectURL(e)}}}function v(t=document){let e=Object.create(null),p=t.createTreeWalker(t.documentElement||t,NodeFilter.SHOW_ELEMENT),f=p.currentNode;for(;f;){if(f instanceof Element)for(let g of f.attributes){let l=g.name;l.startsWith("data-v-")&&(e[l]=(e[l]||0)+1)}f=p.nextNode()}return e}function k(t){let e=[];function p(l){e.push(l);let a=e.length-1;for(;a>0;){let n=a-1>>1;if(e[n].count>=e[a].count)break;[e[n],e[a]]=[e[a],e[n]],a=n}}function f(){let l=e[0],a=e.pop();if(e.length){e[0]=a;let n=0;for(;;){let r=n*2+1,d=r+1,s=n;if(r<e.length&&e[r].count>e[s].count&&(s=r),d<e.length&&e[d].count>e[s].count&&(s=d),s===n)break;[e[n],e[s]]=[e[s],e[n]],n=s}}return l}for(let l=0;l<t.length;l++){let a=t[l];if(a&&a.length){let[n,r]=a[0];p({Count:r,Attr:n,ChunkIndex:l,IndexInChunk:0})}}let g=[];for(;e.length;){let{Attr:l,Count:a,ChunkIndex:n,IndexInChunk:r}=f();g.push([l,a]);let d=r+1,s=t[n];if(d<s.length){let[i,c]=s[d];p({Count:c,Attr:i,ChunkIndex:n,IndexInChunk:d})}}return g}async function R(t){let e=Object.entries(t),p=Math.max(1,navigator.hardwareConcurrency||1),f=Math.min(8,Math.max(1,p-1)),l=e.length>=5e3&&f>1?f:1,a=W(l);try{let n=Array.from({length:l},()=>[]);for(let s=0;s<e.length;s++)n[s%l].push(e[s]);let r=await Promise.all(n.map((s,i)=>new Promise((c,o)=>{let u=a.Workers[i],S=i+":"+Date.now(),h=y=>{y.data?.jobId===S&&(u.removeEventListener("message",h),u.removeEventListener("error",m),c(y.data.sorted))},m=y=>{u.removeEventListener("message",h),u.removeEventListener("error",m),o(y)};u.addEventListener("message",h),u.addEventListener("error",m),u.postMessage({entries:s,jobId:S})}))),d=r.length===1?r[0]:k(r);return{Result:d,TotalKeys:d.length,WorkerCount:l,HardwareConcurrency:p}}finally{a.dispose()}}var L=typeof unsafeWindow<"u"?unsafeWindow:window;function I(t,e="NamuLink"){let p=t.Function.prototype.toString,f=[[/for *\( *; *; *\) *switch *\( *_[a-z0-9]+\[_[a-z0-9]+\([a-z0-9]+\)\] *=_[a-z0-9]+/,/_[a-z0-9]+\[('|")[A-Z]+('|")\]\)\(\[ *\]\)/,/0x[a-z0-9]+ *\) *; *case/],[/; *return *this\[_0x[a-z0-9]+\( *0x[0-9a-z]+ *\)/,/; *if *\( *_0x[a-z0-9]+ *&& *\( *_0x[a-z0-9]+ *= *_0x[a-z0-9]+/,/\) *, *void *\( *this *\[ *_0x[a-z0-9]+\( *0x[0-9a-z]+ *\) *\] *= *_0x[a-z0-9]+ *\[/]];t.Function.prototype.bind=new Proxy(t.Function.prototype.bind,{apply(a,n,r){let d=Reflect.apply(p,n,r);return f.filter(s=>s.filter(i=>i.test(d)).length>=3).length===1?(console.debug(`[${e}]: Function.prototype.bind:`,n),Reflect.apply(a,()=>{},[])):Reflect.apply(a,n,r)}});let g=[[/\( *\) *=> *{ *var *_0x[0-9a-z]+ *= *a0_0x[0-9a-f]+ *; *this\[ *_0x[a-z0-9]+\( *0x[0-9a-f]+ *\) *\]\(\); *}/,/\( *\) *=> *{ *var *_0x[0-9a-z]+ *= *a0_0x[0-9a-f]+ *; *this\[ *_0x[a-z0-9]+\( *0x[0-9a-f]+ *\) *\]\(\); *}/],[/\( *\) *=> *{ *var _0x[a-z0-9]+ *= *_0x[a-z0-9]+ *; *if *\( *this\[ *_0x[a-z0-9]+ *\( *0x[0-9a-f]+ *\) *\] *\) *return *clearTimeout/,/\( *0x[0-9a-f]+ *\) *\] *\) *, *void *\( *this\[ *_0x[a-z0-9]+\( *0x[0-9a-f]+ *\) *\] *= *void *\([x0-9a-f*+-]+ *\) *\) *; *this\[_0x[a-z0-9]+\( *0x[0-9a-f]+ *\) *\] *\(\) *;/]];t.setTimeout=new Proxy(t.setTimeout,{apply(a,n,r){let d=Reflect.apply(p,r[0],r);if(g.filter(s=>s.filter(i=>i.test(d)).length>=1).length===1){console.debug(`[${e}]: setTimeout:`,r[0]);return}return Reflect.apply(a,n,r)}}),document.readyState==="loading"?window.addEventListener("DOMContentLoaded",()=>{w({Root:()=>document.getElementById("#app"),StableForMs:900,SampleWindowMs:900,Threshold:3,TimeoutMs:12e3,IgnoreMutation:b,WatchHashChange:!0})}):window.addEventListener("DOMContentLoaded",()=>{w({Root:()=>document.getElementById("#app"),StableForMs:900,SampleWindowMs:900,Threshold:3,TimeoutMs:12e3,IgnoreMutation:b,WatchHashChange:!0})});let l=async()=>{let a=v(document),{Result:n,TotalKeys:r,WorkerCount:d,HardwareConcurrency:s}=await R(a),i=[];n.filter(([,c])=>c<=30).forEach(([c,o])=>{i.push(...[...document.querySelectorAll(`[${c}]`)].filter(u=>u instanceof HTMLElement))}),i=i.filter(c=>getComputedStyle(c).getPropertyValue("display")==="flex"),i=i.filter(c=>[...c.querySelectorAll("*")].some(o=>o instanceof HTMLElement&&typeof o.click=="function")),i=i.filter(c=>[...c.querySelectorAll("*")].filter(o=>o instanceof HTMLElement&&o.getBoundingClientRect().bottom-o.getBoundingClientRect().top>100&&o.getBoundingClientRect().right-o.getBoundingClientRect().left>100).length<=50),i=i.filter(c=>{let o=[...c.querySelectorAll("*")].filter(u=>u.getBoundingClientRect().bottom-u.getBoundingClientRect().top>25&&u.getBoundingClientRect().right-u.getBoundingClientRect().left>25&&u instanceof SVGPathElement&&u.getAttribute("d")!==null||u instanceof HTMLImageElement&&u.src.includes("//i.namu.wiki/i/")).length;return 1<=o&&o<=6}),i=i.filter(c=>[...c.querySelectorAll("*")].some(o=>o instanceof HTMLElement&&getComputedStyle(o,"::after").getPropertyValue("content").includes(":")&&o.getBoundingClientRect().right-o.getBoundingClientRect().left>20)===!1),i=i.filter(c=>[...c.querySelectorAll("*")].every(o=>o instanceof HTMLElement&&!new Date(o.getHTML()).getTime())),console.debug(`[${e}]`,i),i.forEach(c=>{setInterval(()=>{c.setAttribute("style","display: none !important; visibility: hidden !important;")},250)})};window.addEventListener("SpaRendered",()=>setTimeout(l,2500)),window.addEventListener("SpaRendered",l)}I(L);})();
34
+ `;return URL.createObjectURL(new Blob([r],{type:"text/javascript"}))}function P(r){let e=E(),p=Array.from({length:r},()=>new Worker(e));return{Workers:p,dispose(){p.forEach(f=>f.terminate()),URL.revokeObjectURL(e)}}}function v(r=document){let e=Object.create(null),p=r.createTreeWalker(r.documentElement||r,NodeFilter.SHOW_ELEMENT),f=p.currentNode;for(;f;){if(f instanceof Element)for(let m of f.attributes){let l=m.name;l.startsWith("data-v-")&&(e[l]=(e[l]||0)+1)}f=p.nextNode()}return e}function C(r){let e=[];function p(l){e.push(l);let u=e.length-1;for(;u>0;){let i=u-1>>1;if(e[i].count>=e[u].count)break;[e[i],e[u]]=[e[u],e[i]],u=i}}function f(){let l=e[0],u=e.pop();if(e.length){e[0]=u;let i=0;for(;;){let t=i*2+1,n=t+1,o=i;if(t<e.length&&e[t].count>e[o].count&&(o=t),n<e.length&&e[n].count>e[o].count&&(o=n),o===i)break;[e[i],e[o]]=[e[o],e[i]],i=o}}return l}for(let l=0;l<r.length;l++){let u=r[l];if(u&&u.length){let[i,t]=u[0];p({Count:t,Attr:i,ChunkIndex:l,IndexInChunk:0})}}let m=[];for(;e.length;){let{Attr:l,Count:u,ChunkIndex:i,IndexInChunk:t}=f();m.push([l,u]);let n=t+1,o=r[i];if(n<o.length){let[g,h]=o[n];p({Count:h,Attr:g,ChunkIndex:i,IndexInChunk:n})}}return m}async function x(r){let e=Object.entries(r),p=Math.max(1,navigator.hardwareConcurrency||1),f=Math.min(8,Math.max(1,p-1)),l=e.length>=5e3&&f>1?f:1,u=P(l);try{let i=Array.from({length:l},()=>[]);for(let o=0;o<e.length;o++)i[o%l].push(e[o]);let t=await Promise.all(i.map((o,g)=>new Promise((h,a)=>{let s=u.Workers[g],c=g+":"+Date.now(),d=S=>{S.data?.jobId===c&&(s.removeEventListener("message",d),s.removeEventListener("error",y),h(S.data.sorted))},y=S=>{s.removeEventListener("message",d),s.removeEventListener("error",y),a(S)};s.addEventListener("message",d),s.addEventListener("error",y),s.postMessage({entries:o,jobId:c})}))),n=t.length===1?t[0]:C(t);return{Result:n,TotalKeys:n.length,WorkerCount:l,HardwareConcurrency:p}}finally{u.dispose()}}var W=typeof unsafeWindow<"u"?unsafeWindow:window;function k(r,e="NamuLink"){let p=r.Function.prototype.toString,f=[[/for *\( *; *; *\) *switch *\( *_[a-z0-9]+\[_[a-z0-9]+\([a-z0-9]+\)\] *=_[a-z0-9]+/,/_[a-z0-9]+\[('|")[A-Z]+('|")\]\)\(\[ *\]\)/,/0x[a-z0-9]+ *\) *; *case/],[/; *return *this\[_0x[a-z0-9]+\( *0x[0-9a-z]+ *\)/,/; *if *\( *_0x[a-z0-9]+ *&& *\( *_0x[a-z0-9]+ *= *_0x[a-z0-9]+/,/\) *, *void *\( *this *\[ *_0x[a-z0-9]+\( *0x[0-9a-z]+ *\) *\] *= *_0x[a-z0-9]+ *\[/]];r.Function.prototype.bind=new Proxy(r.Function.prototype.bind,{apply(t,n,o){let g=Reflect.apply(p,n,o);return f.filter(h=>h.filter(a=>a.test(g)).length>=3).length===1?(console.debug(`[${e}]: Function.prototype.bind:`,n),Reflect.apply(t,()=>{},[])):Reflect.apply(t,n,o)}});let m=[[/\( *\) *=> *{ *var *_0x[0-9a-z]+ *= *a0_0x[0-9a-f]+ *; *this\[ *_0x[a-z0-9]+\( *0x[0-9a-f]+ *\) *\]\(\); *}/,/\( *\) *=> *{ *var *_0x[0-9a-z]+ *= *a0_0x[0-9a-f]+ *; *this\[ *_0x[a-z0-9]+\( *0x[0-9a-f]+ *\) *\]\(\); *}/],[/\( *\) *=> *{ *var _0x[a-z0-9]+ *= *_0x[a-z0-9]+ *; *if *\( *this\[ *_0x[a-z0-9]+ *\( *0x[0-9a-f]+ *\) *\] *\) *return *clearTimeout/,/\( *0x[0-9a-f]+ *\) *\] *\) *, *void *\( *this\[ *_0x[a-z0-9]+\( *0x[0-9a-f]+ *\) *\] *= *void *\([x0-9a-f*+-]+ *\) *\) *; *this\[_0x[a-z0-9]+\( *0x[0-9a-f]+ *\) *\] *\(\) *;/]];function l(t){let n=[];for(;t.parentElement;)n.push(t.parentElement),t=t.parentElement;return n}let u=()=>{let t=[...document.querySelectorAll('div[class*=" "] div[class]')].filter(n=>n instanceof HTMLElement);t=t.filter(n=>{let o=Number(getComputedStyle(n).getPropertyValue("padding-left").replaceAll("px","")),g=Number(getComputedStyle(n).getPropertyValue("padding-right").replaceAll("px","")),h=Number(getComputedStyle(n).getPropertyValue("padding-top").replaceAll("px","")),a=Number(getComputedStyle(n).getPropertyValue("padding-bottom").replaceAll("px",""));return o>5&&g>5&&h>5&&a>5}),t=t.filter(n=>[...n.querySelectorAll("*")].filter(o=>o instanceof HTMLElement&&getComputedStyle(o).getPropertyValue("animation-timing-function")==="ease-in-out").length>=3),t=t.filter(n=>l(n).some(o=>Number(getComputedStyle(o).getPropertyValue("margin-top").replaceAll("px",""))>10)),t=t.filter(n=>n.innerText.length<1e3),t=t.filter(n=>[...n.querySelectorAll('*[href="/RecentChanges"]')].filter(o=>o instanceof HTMLElement&&getComputedStyle(o).getPropertyValue("display")!=="none").length===0),t=t.filter(n=>!n.innerText.includes((new URL(location.href).searchParams.get("from")||"")+"\uC5D0\uC11C \uB118\uC5B4\uC634")),t=t.filter(n=>!/\[[0-9]+\] .+/.test(n.innerText)),t.forEach(n=>n.setAttribute("style","display: none !important; visibility: hidden !important;"))};r.setTimeout=new Proxy(r.setTimeout,{apply(t,n,o){let g=Reflect.apply(p,o[0],o);return m.filter(h=>h.filter(a=>a.test(g)).length>=1).length===1?(console.debug(`[${e}]: setTimeout:`,o[0]),Reflect.apply(t,n,[u,1500])):Reflect.apply(t,n,o)}}),document.readyState==="loading"?window.addEventListener("DOMContentLoaded",()=>{w({Root:()=>document.getElementById("#app"),StableForMs:900,SampleWindowMs:900,Threshold:3,TimeoutMs:12e3,IgnoreMutation:b,WatchHashChange:!0})}):window.addEventListener("DOMContentLoaded",()=>{w({Root:()=>document.getElementById("#app"),StableForMs:900,SampleWindowMs:900,Threshold:3,TimeoutMs:12e3,IgnoreMutation:b,WatchHashChange:!0})});let i=async()=>{let t=v(document),{Result:n,TotalKeys:o,WorkerCount:g,HardwareConcurrency:h}=await x(t),a=[];n.filter(([,s])=>s<=30).forEach(([s,c])=>{a.push(...[...document.querySelectorAll(`[${s}]`)].filter(d=>d instanceof HTMLElement))}),a=a.filter(s=>getComputedStyle(s).getPropertyValue("display")==="flex"),a=a.filter(s=>[...s.querySelectorAll("*")].some(c=>c instanceof HTMLElement&&typeof c.click=="function")),a=a.filter(s=>[...s.querySelectorAll("*")].filter(c=>c instanceof HTMLElement&&c.getBoundingClientRect().bottom-c.getBoundingClientRect().top>100&&c.getBoundingClientRect().right-c.getBoundingClientRect().left>100).length<=50),a=a.filter(s=>{let c=[...s.querySelectorAll("*")].filter(d=>d.getBoundingClientRect().bottom-d.getBoundingClientRect().top>25&&d.getBoundingClientRect().right-d.getBoundingClientRect().left>25&&d instanceof SVGPathElement&&d.getAttribute("d")!==null||d instanceof HTMLImageElement&&d.src.includes("//i.namu.wiki/i/")).length;return 1<=c&&c<=6}),a=a.filter(s=>[...s.querySelectorAll("*")].some(c=>c instanceof HTMLElement&&getComputedStyle(c,"::after").getPropertyValue("content").includes(":")&&c.getBoundingClientRect().right-c.getBoundingClientRect().left>20)===!1),a=a.filter(s=>[...s.querySelectorAll("*")].every(c=>c instanceof HTMLElement&&!new Date(c.getHTML()).getTime())),console.debug(`[${e}]`,a),a.forEach(s=>{setInterval(()=>{s.setAttribute("style","display: none !important; visibility: hidden !important;")},250)})};window.addEventListener("SpaRendered",()=>setTimeout(i,2500)),window.addEventListener("SpaRendered",i)}k(W);})();
32
35
  /*!
33
36
  * @license MPL-2.0
34
37
  * This Source Code Form is subject to the terms of the Mozilla Public
@@ -36,5 +39,5 @@ self.onmessage = (e) => {
36
39
  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
37
40
  *
38
41
  * Contributors:
39
- * - See Git history at https://github.com/FilteringDev/tinyShield for detailed authorship information.
42
+ * - See Git history at https://github.com/FilteringDev/NamuLink for detailed authorship information.
40
43
  */
@@ -5,6 +5,6 @@
5
5
  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
6
  *
7
7
  * Contributors:
8
- * - See Git history at https://github.com/FilteringDev/tinyShield for detailed authorship information.
8
+ * - See Git history at https://github.com/FilteringDev/NamuLink for detailed authorship information.
9
9
  */
10
10
  export declare function RunNamuLinkUserscript(BrowserWindow: typeof window, UserscriptName?: string): void;
package/dist/index.js ADDED
@@ -0,0 +1,133 @@
1
+ /*!
2
+ * @license MPL-2.0
3
+ * This Source Code Form is subject to the terms of the Mozilla Public
4
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
5
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
+ *
7
+ * Contributors:
8
+ * - See Git history at https://github.com/FilteringDev/NamuLink for detailed authorship information.
9
+ */
10
+ import * as SPA from './spa.js';
11
+ import * as Sort from './sort.js';
12
+ const Win = typeof unsafeWindow !== 'undefined' ? unsafeWindow : window;
13
+ export function RunNamuLinkUserscript(BrowserWindow, UserscriptName = 'NamuLink') {
14
+ const ProtectedFunctionPrototypeToString = BrowserWindow.Function.prototype.toString;
15
+ let PowerLinkGenerationPositiveRegExps = [[
16
+ /for *\( *; *; *\) *switch *\( *_[a-z0-9]+\[_[a-z0-9]+\([a-z0-9]+\)\] *=_[a-z0-9]+/,
17
+ /_[a-z0-9]+\[('|")[A-Z]+('|")\]\)\(\[ *\]\)/,
18
+ /0x[a-z0-9]+ *\) *; *case/
19
+ ], [
20
+ /; *return *this\[_0x[a-z0-9]+\( *0x[0-9a-z]+ *\)/,
21
+ /; *if *\( *_0x[a-z0-9]+ *&& *\( *_0x[a-z0-9]+ *= *_0x[a-z0-9]+/,
22
+ /\) *, *void *\( *this *\[ *_0x[a-z0-9]+\( *0x[0-9a-z]+ *\) *\] *= *_0x[a-z0-9]+ *\[/
23
+ ]];
24
+ BrowserWindow.Function.prototype.bind = new Proxy(BrowserWindow.Function.prototype.bind, {
25
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
26
+ apply(Target, ThisArg, Args) {
27
+ let StringifiedFunc = Reflect.apply(ProtectedFunctionPrototypeToString, ThisArg, Args);
28
+ if (PowerLinkGenerationPositiveRegExps.filter(PowerLinkGenerationPositiveRegExp => PowerLinkGenerationPositiveRegExp.filter(Index => Index.test(StringifiedFunc)).length >= 3).length === 1) {
29
+ console.debug(`[${UserscriptName}]: Function.prototype.bind:`, ThisArg);
30
+ return Reflect.apply(Target, () => { }, []);
31
+ }
32
+ return Reflect.apply(Target, ThisArg, Args);
33
+ }
34
+ });
35
+ let PowerLinkGenerationSkeletionPositiveRegExps = [[
36
+ /\( *\) *=> *{ *var *_0x[0-9a-z]+ *= *a0_0x[0-9a-f]+ *; *this\[ *_0x[a-z0-9]+\( *0x[0-9a-f]+ *\) *\]\(\); *}/,
37
+ /\( *\) *=> *{ *var *_0x[0-9a-z]+ *= *a0_0x[0-9a-f]+ *; *this\[ *_0x[a-z0-9]+\( *0x[0-9a-f]+ *\) *\]\(\); *}/
38
+ ], [
39
+ /\( *\) *=> *{ *var _0x[a-z0-9]+ *= *_0x[a-z0-9]+ *; *if *\( *this\[ *_0x[a-z0-9]+ *\( *0x[0-9a-f]+ *\) *\] *\) *return *clearTimeout/,
40
+ /\( *0x[0-9a-f]+ *\) *\] *\) *, *void *\( *this\[ *_0x[a-z0-9]+\( *0x[0-9a-f]+ *\) *\] *= *void *\([x0-9a-f*+-]+ *\) *\) *; *this\[_0x[a-z0-9]+\( *0x[0-9a-f]+ *\) *\] *\(\) *;/
41
+ ]];
42
+ function GetParents(Ele) {
43
+ let Parents = [];
44
+ while (Ele.parentElement) {
45
+ Parents.push(Ele.parentElement);
46
+ Ele = Ele.parentElement;
47
+ }
48
+ return Parents;
49
+ }
50
+ const HidePowerLinkPlaceholderWithAccount = () => {
51
+ let AdContainers = [...document.querySelectorAll('div[class*=" "] div[class]')].filter(AdContainer => AdContainer instanceof HTMLElement);
52
+ AdContainers = AdContainers.filter((AdContainer) => {
53
+ let AdContainerPaddingLeft = Number(getComputedStyle(AdContainer).getPropertyValue('padding-left').replaceAll('px', ''));
54
+ let AdContainerPaddingRight = Number(getComputedStyle(AdContainer).getPropertyValue('padding-right').replaceAll('px', ''));
55
+ let AdContainerPaddingTop = Number(getComputedStyle(AdContainer).getPropertyValue('padding-top').replaceAll('px', ''));
56
+ let AdContainerPaddingBottom = Number(getComputedStyle(AdContainer).getPropertyValue('padding-bottom').replaceAll('px', ''));
57
+ return AdContainerPaddingLeft > 5 && AdContainerPaddingRight > 5 && AdContainerPaddingTop > 5 && AdContainerPaddingBottom > 5;
58
+ });
59
+ AdContainers = AdContainers.filter(AdContainer => {
60
+ return [...AdContainer.querySelectorAll('*')].filter(Ele => Ele instanceof HTMLElement &&
61
+ getComputedStyle(Ele).getPropertyValue('animation-timing-function') === 'ease-in-out').length >= 3;
62
+ });
63
+ AdContainers = AdContainers.filter(AdContainer => GetParents(AdContainer).some(Parent => Number(getComputedStyle(Parent).getPropertyValue('margin-top').replaceAll('px', '')) > 10));
64
+ AdContainers = AdContainers.filter(AdContainer => AdContainer.innerText.length < 1000);
65
+ AdContainers = AdContainers.filter(AdContainer => [...AdContainer.querySelectorAll('*[href="/RecentChanges"]')].filter(Ele => Ele instanceof HTMLElement && getComputedStyle(Ele).getPropertyValue('display') !== 'none').length === 0);
66
+ AdContainers = AdContainers.filter(AdContainer => !AdContainer.innerText.includes((new URL(location.href).searchParams.get('from') || '') + '에서 넘어옴'));
67
+ AdContainers = AdContainers.filter(AdContainer => !/\[[0-9]+\] .+/.test(AdContainer.innerText));
68
+ AdContainers.forEach(Ele => Ele.setAttribute('style', 'display: none !important; visibility: hidden !important;'));
69
+ };
70
+ BrowserWindow.setTimeout = new Proxy(BrowserWindow.setTimeout, {
71
+ apply(Target, ThisArg, Args) {
72
+ let StringifiedFunc = Reflect.apply(ProtectedFunctionPrototypeToString, Args[0], Args);
73
+ if (PowerLinkGenerationSkeletionPositiveRegExps.filter(PowerLinkGenerationSkeletionPositiveRegExp => PowerLinkGenerationSkeletionPositiveRegExp.filter(Index => Index.test(StringifiedFunc)).length >= 1).length === 1) {
74
+ console.debug(`[${UserscriptName}]: setTimeout:`, Args[0]);
75
+ return Reflect.apply(Target, ThisArg, [HidePowerLinkPlaceholderWithAccount, 1500]);
76
+ }
77
+ return Reflect.apply(Target, ThisArg, Args);
78
+ }
79
+ });
80
+ if (document.readyState === 'loading') {
81
+ window.addEventListener('DOMContentLoaded', () => {
82
+ SPA.InstallSpaNavigationBridge({
83
+ Root: () => document.getElementById('#app'),
84
+ StableForMs: 900,
85
+ SampleWindowMs: 900,
86
+ Threshold: 3,
87
+ TimeoutMs: 12000,
88
+ IgnoreMutation: SPA.DefaultIgnoreMutation,
89
+ WatchHashChange: true
90
+ });
91
+ });
92
+ }
93
+ else {
94
+ // 이미 DOMContentLoaded 이후
95
+ window.addEventListener('DOMContentLoaded', () => {
96
+ SPA.InstallSpaNavigationBridge({
97
+ Root: () => document.getElementById('#app'),
98
+ StableForMs: 900,
99
+ SampleWindowMs: 900,
100
+ Threshold: 3,
101
+ TimeoutMs: 12000,
102
+ IgnoreMutation: SPA.DefaultIgnoreMutation,
103
+ WatchHashChange: true
104
+ });
105
+ });
106
+ }
107
+ const Handler = async () => {
108
+ let HTMLEle = Sort.CollectDataVAttributes(document);
109
+ const { Result, TotalKeys, WorkerCount, HardwareConcurrency } = await Sort.RankCountsWithWorkersParallel(HTMLEle);
110
+ let TargetedAttrsDOMs = [];
111
+ Result.filter(([, Count]) => Count <= 30).forEach(([Attr, Count]) => {
112
+ TargetedAttrsDOMs.push(...[...document.querySelectorAll(`[${Attr}]`)].filter((El) => El instanceof HTMLElement));
113
+ });
114
+ TargetedAttrsDOMs = TargetedAttrsDOMs.filter(El => getComputedStyle(El).getPropertyValue('display') === 'flex');
115
+ TargetedAttrsDOMs = TargetedAttrsDOMs.filter(El => [...El.querySelectorAll('*')].some(Child => Child instanceof HTMLElement && typeof Child.click === 'function'));
116
+ TargetedAttrsDOMs = TargetedAttrsDOMs.filter(El => [...El.querySelectorAll('*')].filter(Child => Child instanceof HTMLElement && Child.getBoundingClientRect().bottom - Child.getBoundingClientRect().top > 100 && Child.getBoundingClientRect().right - Child.getBoundingClientRect().left > 100).length <= 50);
117
+ TargetedAttrsDOMs = TargetedAttrsDOMs.filter(El => {
118
+ let Count = [...El.querySelectorAll('*')].filter(Child => (Child.getBoundingClientRect().bottom - Child.getBoundingClientRect().top > 25 && Child.getBoundingClientRect().right - Child.getBoundingClientRect().left > 25 && (Child instanceof SVGPathElement && Child.getAttribute('d') !== null) || (Child instanceof HTMLImageElement && Child.src.includes('//i.namu.wiki/i/')))).length;
119
+ return 1 <= Count && Count <= 6;
120
+ });
121
+ TargetedAttrsDOMs = TargetedAttrsDOMs.filter(El => [...El.querySelectorAll('*')].some(Child => Child instanceof HTMLElement && getComputedStyle(Child, '::after').getPropertyValue('content').includes(':') && Child.getBoundingClientRect().right - Child.getBoundingClientRect().left > 20) === false);
122
+ TargetedAttrsDOMs = TargetedAttrsDOMs.filter(El => [...El.querySelectorAll('*')].every(Child => Child instanceof HTMLElement && !new Date(Child.getHTML()).getTime()));
123
+ console.debug(`[${UserscriptName}]`, TargetedAttrsDOMs);
124
+ TargetedAttrsDOMs.forEach(El => {
125
+ setInterval(() => {
126
+ El.setAttribute('style', 'display: none !important; visibility: hidden !important;');
127
+ }, 250);
128
+ });
129
+ };
130
+ window.addEventListener('SpaRendered', () => setTimeout(Handler, 2500));
131
+ window.addEventListener('SpaRendered', Handler);
132
+ }
133
+ RunNamuLinkUserscript(Win);
package/dist/sort.js ADDED
@@ -0,0 +1,147 @@
1
+ export function CreateSortWorkerURL() {
2
+ const WorkerCode = `
3
+ self.onmessage = (e) => {
4
+ const { entries, jobId } = e.data;
5
+ // entries: Array<[string, number]>
6
+ // 내림차순 정렬
7
+ entries.sort((a, b) => b[1] - a[1]);
8
+ self.postMessage({ jobId, sorted: entries });
9
+ };
10
+ `;
11
+ return URL.createObjectURL(new Blob([WorkerCode], { type: 'text/javascript' }));
12
+ }
13
+ export function MakeWorkerPool(Size) {
14
+ const Url = CreateSortWorkerURL();
15
+ const Workers = Array.from({ length: Size }, () => new Worker(Url));
16
+ return {
17
+ Workers,
18
+ dispose() {
19
+ Workers.forEach(W => W.terminate());
20
+ URL.revokeObjectURL(Url);
21
+ }
22
+ };
23
+ }
24
+ export function CollectDataVAttributes(Root = document) {
25
+ const Counts = Object.create(null);
26
+ const Walker = Root.createTreeWalker(Root.documentElement || Root, NodeFilter.SHOW_ELEMENT);
27
+ let Node = Walker.currentNode;
28
+ while (Node) {
29
+ if (Node instanceof Element) {
30
+ for (const Attr of Node.attributes) {
31
+ const Name = Attr.name;
32
+ if (Name.startsWith('data-v-')) {
33
+ Counts[Name] = (Counts[Name] || 0) + 1;
34
+ }
35
+ }
36
+ }
37
+ Node = Walker.nextNode();
38
+ }
39
+ return Counts;
40
+ }
41
+ export function MergeSortedChunks(Chunks) {
42
+ // chunks: Array<Array<[string, number]>> 각각 내림차순
43
+ // 결과: 전체 내림차순
44
+ // 간단한 max-heap (count 기준)
45
+ const Heap = [];
46
+ function Push(Item) {
47
+ Heap.push(Item);
48
+ let I = Heap.length - 1;
49
+ while (I > 0) {
50
+ const P = (I - 1) >> 1;
51
+ if (Heap[P].count >= Heap[I].count)
52
+ break;
53
+ [Heap[P], Heap[I]] = [Heap[I], Heap[P]];
54
+ I = P;
55
+ }
56
+ }
57
+ ;
58
+ function Pop() {
59
+ const Top = Heap[0];
60
+ const Last = Heap.pop();
61
+ if (Heap.length) {
62
+ Heap[0] = Last;
63
+ let I = 0;
64
+ while (true) {
65
+ const L = I * 2 + 1;
66
+ const R = L + 1;
67
+ let M = I;
68
+ if (L < Heap.length && Heap[L].count > Heap[M].count)
69
+ M = L;
70
+ if (R < Heap.length && Heap[R].count > Heap[M].count)
71
+ M = R;
72
+ if (M === I)
73
+ break;
74
+ [Heap[I], Heap[M]] = [Heap[M], Heap[I]];
75
+ I = M;
76
+ }
77
+ }
78
+ return Top;
79
+ }
80
+ for (let C = 0; C < Chunks.length; C++) {
81
+ const Arr = Chunks[C];
82
+ if (Arr && Arr.length) {
83
+ const [Attr, Count] = Arr[0];
84
+ Push({ Count, Attr, ChunkIndex: C, IndexInChunk: 0 });
85
+ }
86
+ }
87
+ const Out = [];
88
+ while (Heap.length) {
89
+ const { Attr, Count, ChunkIndex, IndexInChunk } = Pop();
90
+ Out.push([Attr, Count]);
91
+ const NextIndex = IndexInChunk + 1;
92
+ const Arr = Chunks[ChunkIndex];
93
+ if (NextIndex < Arr.length) {
94
+ const [NAttr, NCount] = Arr[NextIndex];
95
+ Push({ Count: NCount, Attr: NAttr, ChunkIndex, IndexInChunk: NextIndex });
96
+ }
97
+ }
98
+ return Out;
99
+ }
100
+ export async function RankCountsWithWorkersParallel(Counts) {
101
+ const Entries = Object.entries(Counts); // [attr, count][]
102
+ // 논리 코어 수 기반 워커 개수 결정
103
+ // - 너무 많이 만들면 오히려 역효과라 상한을 둠
104
+ const Hc = Math.max(1, navigator.hardwareConcurrency || 1);
105
+ const WorkerCount = Math.min(8, Math.max(1, Hc - 1));
106
+ // entries가 적으면 병렬화 이득이 거의 없음 → 1개로
107
+ const ShouldParallel = Entries.length >= 5000 && WorkerCount > 1;
108
+ const ActualWorkers = ShouldParallel ? WorkerCount : 1;
109
+ const Pool = MakeWorkerPool(ActualWorkers);
110
+ try {
111
+ // chunks 분할
112
+ const Chunks = Array.from({ length: ActualWorkers }, () => []);
113
+ for (let I = 0; I < Entries.length; I++) {
114
+ Chunks[I % ActualWorkers].push(Entries[I]);
115
+ }
116
+ // 각 워커에 정렬 요청
117
+ const SortedChunks = await Promise.all(Chunks.map((ChunkEntries, Idx) => {
118
+ return new Promise((Resolve, Reject) => {
119
+ const Worker = Pool.Workers[Idx];
120
+ const JobId = Idx + ':' + Date.now();
121
+ const OnMsg = (E) => {
122
+ if (E.data?.jobId !== JobId)
123
+ return;
124
+ Worker.removeEventListener('message', OnMsg);
125
+ Worker.removeEventListener('error', OnErr);
126
+ Resolve(E.data.sorted);
127
+ };
128
+ const OnErr = (Err) => {
129
+ Worker.removeEventListener('message', OnMsg);
130
+ Worker.removeEventListener('error', OnErr);
131
+ Reject(Err);
132
+ };
133
+ Worker.addEventListener('message', OnMsg);
134
+ Worker.addEventListener('error', OnErr);
135
+ Worker.postMessage({ entries: ChunkEntries, jobId: JobId });
136
+ });
137
+ }));
138
+ // 병합해서 전체 순위 생성
139
+ const Merged = (SortedChunks.length === 1)
140
+ ? SortedChunks[0]
141
+ : MergeSortedChunks(SortedChunks);
142
+ return { Result: Merged, TotalKeys: Merged.length, WorkerCount: ActualWorkers, HardwareConcurrency: Hc };
143
+ }
144
+ finally {
145
+ Pool.dispose();
146
+ }
147
+ }
@@ -5,7 +5,7 @@
5
5
  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
6
  *
7
7
  * Contributors:
8
- * - See Git history at https://github.com/FilteringDev/tinyShield for detailed authorship information.
8
+ * - See Git history at https://github.com/FilteringDev/NamuLink for detailed authorship information.
9
9
  */
10
10
  type SpaNavigateCause = 'init' | 'pushState' | 'replaceState' | 'popstate' | 'hashchange';
11
11
  export type SpaNavigateDetail = {
package/dist/spa.js ADDED
@@ -0,0 +1,189 @@
1
+ /*!
2
+ * @license MPL-2.0
3
+ * This Source Code Form is subject to the terms of the Mozilla Public
4
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
5
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
+ *
7
+ * Contributors:
8
+ * - See Git history at https://github.com/FilteringDev/NamuLink for detailed authorship information.
9
+ */
10
+ /**
11
+ * SPA 라우팅(URL 변경)을 감지해 커스텀 이벤트를 발행하고,
12
+ * DOM이 충분히 안정화되면 'Rendered' 이벤트까지 발행하는 브릿지
13
+ *
14
+ * Events (PascalCase):
15
+ * - 'SpaNavigate' => CustomEvent<SpaNavigateDetail>
16
+ * - 'SpaRendered' => CustomEvent<SpaRenderedDetail>
17
+ */
18
+ export function InstallSpaNavigationBridge(Options = {}) {
19
+ const Opts = NormalizeOptions(Options);
20
+ const EventNavigate = Opts.Events.Navigate;
21
+ const EventRendered = Opts.Events.Rendered;
22
+ const FireNavigate = (Detail) => {
23
+ window.dispatchEvent(new CustomEvent(EventNavigate, { detail: Detail }));
24
+ };
25
+ const FireRendered = (Detail) => {
26
+ window.dispatchEvent(new CustomEvent(EventRendered, { detail: Detail }));
27
+ };
28
+ let LastUrl = window.location.href;
29
+ let NavSeq = 0;
30
+ let Disposed = false;
31
+ const OnUrlMaybeChanged = (Cause) => {
32
+ if (Disposed)
33
+ return;
34
+ const Url = window.location.href;
35
+ if (Url === LastUrl)
36
+ return;
37
+ const From = LastUrl;
38
+ LastUrl = Url;
39
+ const Seq = ++NavSeq;
40
+ FireNavigate({ Seq, From, To: Url, Cause });
41
+ void (async () => {
42
+ const Root = Opts.Root();
43
+ if (!Root) {
44
+ if (Seq !== NavSeq || Disposed)
45
+ return;
46
+ FireRendered({ Seq, Url, Ok: true });
47
+ return;
48
+ }
49
+ const Ok = await WaitForDomMostlyStable({
50
+ Root: Root,
51
+ StableForMs: Opts.StableForMs,
52
+ SampleWindowMs: Opts.SampleWindowMs,
53
+ Threshold: Opts.Threshold,
54
+ TimeoutMs: Opts.TimeoutMs,
55
+ Ignore: Opts.IgnoreMutation,
56
+ });
57
+ if (Seq !== NavSeq || Disposed)
58
+ return;
59
+ FireRendered({ Seq, Url, Ok });
60
+ })();
61
+ };
62
+ const PatchHistory = (MethodName) => {
63
+ const Original = history[MethodName].bind(history);
64
+ const Patched = (...Args) => {
65
+ const Ret = Original(...Args);
66
+ queueMicrotask(() => OnUrlMaybeChanged(MethodName));
67
+ return Ret;
68
+ };
69
+ Object.defineProperty(history, MethodName, {
70
+ value: Patched,
71
+ configurable: true,
72
+ writable: true,
73
+ });
74
+ };
75
+ PatchHistory('pushState');
76
+ PatchHistory('replaceState');
77
+ const OnPopState = () => OnUrlMaybeChanged('popstate');
78
+ window.addEventListener('popstate', OnPopState);
79
+ const OnHashChange = () => OnUrlMaybeChanged('hashchange');
80
+ if (Opts.WatchHashChange)
81
+ window.addEventListener('hashchange', OnHashChange);
82
+ queueMicrotask(() => {
83
+ if (Disposed)
84
+ return;
85
+ const Seq = ++NavSeq;
86
+ FireNavigate({ Seq, From: null, To: window.location.href, Cause: 'init' });
87
+ void (async () => {
88
+ const Root = Opts.Root();
89
+ if (!Root) {
90
+ if (Seq !== NavSeq || Disposed)
91
+ return;
92
+ FireRendered({ Seq, Url: window.location.href, Ok: true });
93
+ return;
94
+ }
95
+ const Ok = await WaitForDomMostlyStable({
96
+ Root: Root,
97
+ StableForMs: Opts.StableForMs,
98
+ SampleWindowMs: Opts.SampleWindowMs,
99
+ Threshold: Opts.Threshold,
100
+ TimeoutMs: Opts.TimeoutMs,
101
+ Ignore: Opts.IgnoreMutation,
102
+ });
103
+ if (Seq !== NavSeq || Disposed)
104
+ return;
105
+ FireRendered({ Seq, Url: window.location.href, Ok: Ok });
106
+ })();
107
+ });
108
+ return () => {
109
+ Disposed = true;
110
+ window.removeEventListener('popstate', OnPopState);
111
+ if (Opts.WatchHashChange)
112
+ window.removeEventListener('hashchange', OnHashChange);
113
+ };
114
+ }
115
+ export function DefaultIgnoreMutation(Mutation) {
116
+ if (Mutation.type === 'attributes') {
117
+ const Name = Mutation.attributeName ?? '';
118
+ if (Name === 'class' || Name === 'style')
119
+ return true;
120
+ if (Name.startsWith('aria-') || Name.startsWith('data-'))
121
+ return true;
122
+ }
123
+ return false;
124
+ }
125
+ function NormalizeOptions(Options) {
126
+ return {
127
+ Root: Options.Root ?? (() => document.querySelector('#app') ?? document.body),
128
+ StableForMs: Options.StableForMs ?? 900,
129
+ SampleWindowMs: Options.SampleWindowMs ?? 900,
130
+ Threshold: Options.Threshold ?? 3,
131
+ TimeoutMs: Options.TimeoutMs ?? 12000,
132
+ IgnoreMutation: Options.IgnoreMutation ?? DefaultIgnoreMutation,
133
+ WatchHashChange: Options.WatchHashChange ?? true,
134
+ Events: {
135
+ Navigate: Options.Events?.Navigate ?? 'SpaNavigate',
136
+ Rendered: Options.Events?.Rendered ?? 'SpaRendered',
137
+ },
138
+ };
139
+ }
140
+ async function WaitForDomMostlyStable(Opts) {
141
+ const Events = [];
142
+ let LastAboveAt = performance.now();
143
+ let Done = false;
144
+ const Observer = new MutationObserver((List) => {
145
+ const Now = performance.now();
146
+ for (const M of List) {
147
+ if (Opts.Ignore?.(M))
148
+ continue;
149
+ let Score = 1;
150
+ if (M.type === 'childList')
151
+ Score = 2;
152
+ Events.push({ T: Now, Score });
153
+ }
154
+ const Cutoff = Now - Opts.SampleWindowMs;
155
+ while (Events.length && Events[0].T < Cutoff)
156
+ Events.shift();
157
+ const WindowScore = Events.reduce((Sum, E) => Sum + E.Score, 0);
158
+ if (WindowScore > Opts.Threshold)
159
+ LastAboveAt = Now;
160
+ });
161
+ Observer.observe(Opts.Root, {
162
+ subtree: true,
163
+ childList: true,
164
+ attributes: true,
165
+ characterData: true,
166
+ });
167
+ const Start = performance.now();
168
+ return await new Promise((Resolve) => {
169
+ const Tick = () => {
170
+ if (Done)
171
+ return;
172
+ const Now = performance.now();
173
+ if (Now - LastAboveAt >= Opts.StableForMs) {
174
+ Done = true;
175
+ Observer.disconnect();
176
+ Resolve(true);
177
+ return;
178
+ }
179
+ if (Now - Start >= Opts.TimeoutMs) {
180
+ Done = true;
181
+ Observer.disconnect();
182
+ Resolve(false);
183
+ return;
184
+ }
185
+ setTimeout(Tick, 100);
186
+ };
187
+ setTimeout(Tick, 0);
188
+ });
189
+ }
package/package.json CHANGED
@@ -1,57 +1,41 @@
1
1
  {
2
2
  "name": "@filteringdev/namulink",
3
- "version": "18.1.3",
3
+ "version": "19.0.0-build.0",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "scripts": {
7
- "build:interface": "esbuild sources/interface.ts --bundle --format=esm --splitting --sourcemap --target=es2024 --external:/node_modules --outdir=dist && tsc --outDir dist/types --declaration --emitDeclarationOnly",
8
- "build:userscript": "esbuild sources/src/index.ts --bundle --minify --define:global=window --inject:./sources/esbuild.inject.ts --banner:js=\"$(cat ./sources/banner.txt)\" --target=es2024,chrome119,safari17,firefox121 --outfile=./dist/NamuLink.user.js",
7
+ "build:interface": "tsc -p userscript/tsconfig.json",
8
+ "build:userscript": "npm run build -w builder -- --minify true --use-cache false --build-type production --SubscriptionUrl https://cdn.jsdelivr.net/npm/@filteringdev/namulink@latest/dist/NamuLink.user.js",
9
9
  "build": "npm run build:interface && npm run build:userscript",
10
- "debug": "esbuild sources/src/index.ts --bundle --define:global=window --inject:./sources/esbuild.inject.ts --banner:js=\"$(cat ./sources/banner.txt)\" --target=es2024,chrome119,safari17,firefox121 --outfile=./dist/NamuLink-debug.user.js",
11
- "lint": "tsc --noEmit && eslint sources --ext .ts"
12
- },
13
- "keywords": [],
14
- "author": {
15
- "name": "PiQuark6046",
16
- "email": "piquark6046@proton.me",
17
- "url": "https://github.com/PiQuark6046"
10
+ "debug": "npm run debug -w builder",
11
+ "lint": "npm run lint -w builder && npm run lint -w userscript"
18
12
  },
13
+ "keywords": [
14
+ "namu.wiki",
15
+ "NamuWiki"
16
+ ],
19
17
  "files": [
20
18
  "dist/**/*"
21
19
  ],
22
20
  "exports": {
23
21
  ".": {
24
- "import": "./dist/interface.js",
25
- "types": "./dist/types/interface.d.ts"
22
+ "import": "./dist/index.js",
23
+ "types": "./dist/index.d.ts"
26
24
  }
27
25
  },
28
- "types": "./dist/types/interface.d.ts",
29
26
  "repository": {
30
27
  "type": "git",
31
28
  "url": "git+https://github.com/FilteringDev/NamuLink.git"
32
29
  },
33
- "contributors": [
34
- {
35
- "name": "green1052",
36
- "url": "https://github.com/green1052"
37
- },
38
- {
39
- "name": "gaeulbyul",
40
- "url": "https://github.com/gaeulbyul"
41
- },
42
- {
43
- "name": "Adguard Software Ltd.",
44
- "url": "https://adguard.com/"
45
- }
30
+ "license": "MPL-2.0",
31
+ "workspaces": [
32
+ "userscript",
33
+ "builder"
46
34
  ],
47
- "license": "MIT",
48
- "dependencies": {
49
- "@types/node": "^24.10.4"
50
- },
51
35
  "devDependencies": {
52
- "esbuild": "^0.27.2",
53
- "eslint": "^9.39.2",
54
- "typescript": "^5.9.3",
55
- "typescript-eslint": "^8.50.1"
36
+ "@typescript-eslint/eslint-plugin": "^8.57.0",
37
+ "@typescript-eslint/parser": "^8.57.0",
38
+ "eslint": "^10.0.3",
39
+ "typescript-eslint": "^8.57.0"
56
40
  }
57
41
  }
package/dist/interface.js DELETED
@@ -1,402 +0,0 @@
1
- // sources/src/spa.ts
2
- function InstallSpaNavigationBridge(Options = {}) {
3
- const Opts = NormalizeOptions(Options);
4
- const EventNavigate = Opts.Events.Navigate;
5
- const EventRendered = Opts.Events.Rendered;
6
- const FireNavigate = (Detail) => {
7
- window.dispatchEvent(new CustomEvent(EventNavigate, { detail: Detail }));
8
- };
9
- const FireRendered = (Detail) => {
10
- window.dispatchEvent(new CustomEvent(EventRendered, { detail: Detail }));
11
- };
12
- let LastUrl = window.location.href;
13
- let NavSeq = 0;
14
- let Disposed = false;
15
- const OnUrlMaybeChanged = (Cause) => {
16
- if (Disposed) return;
17
- const Url = window.location.href;
18
- if (Url === LastUrl) return;
19
- const From = LastUrl;
20
- LastUrl = Url;
21
- const Seq = ++NavSeq;
22
- FireNavigate({ Seq, From, To: Url, Cause });
23
- void (async () => {
24
- const Root = Opts.Root();
25
- if (!Root) {
26
- if (Seq !== NavSeq || Disposed) return;
27
- FireRendered({ Seq, Url, Ok: true });
28
- return;
29
- }
30
- const Ok = await WaitForDomMostlyStable({
31
- Root,
32
- StableForMs: Opts.StableForMs,
33
- SampleWindowMs: Opts.SampleWindowMs,
34
- Threshold: Opts.Threshold,
35
- TimeoutMs: Opts.TimeoutMs,
36
- Ignore: Opts.IgnoreMutation
37
- });
38
- if (Seq !== NavSeq || Disposed) return;
39
- FireRendered({ Seq, Url, Ok });
40
- })();
41
- };
42
- const PatchHistory = (MethodName) => {
43
- const Original = history[MethodName].bind(history);
44
- const Patched = (...Args) => {
45
- const Ret = Original(...Args);
46
- queueMicrotask(() => OnUrlMaybeChanged(MethodName));
47
- return Ret;
48
- };
49
- Object.defineProperty(history, MethodName, {
50
- value: Patched,
51
- configurable: true,
52
- writable: true
53
- });
54
- };
55
- PatchHistory("pushState");
56
- PatchHistory("replaceState");
57
- const OnPopState = () => OnUrlMaybeChanged("popstate");
58
- window.addEventListener("popstate", OnPopState);
59
- const OnHashChange = () => OnUrlMaybeChanged("hashchange");
60
- if (Opts.WatchHashChange) window.addEventListener("hashchange", OnHashChange);
61
- queueMicrotask(() => {
62
- if (Disposed) return;
63
- const Seq = ++NavSeq;
64
- FireNavigate({ Seq, From: null, To: window.location.href, Cause: "init" });
65
- void (async () => {
66
- const Root = Opts.Root();
67
- if (!Root) {
68
- if (Seq !== NavSeq || Disposed) return;
69
- FireRendered({ Seq, Url: window.location.href, Ok: true });
70
- return;
71
- }
72
- const Ok = await WaitForDomMostlyStable({
73
- Root,
74
- StableForMs: Opts.StableForMs,
75
- SampleWindowMs: Opts.SampleWindowMs,
76
- Threshold: Opts.Threshold,
77
- TimeoutMs: Opts.TimeoutMs,
78
- Ignore: Opts.IgnoreMutation
79
- });
80
- if (Seq !== NavSeq || Disposed) return;
81
- FireRendered({ Seq, Url: window.location.href, Ok });
82
- })();
83
- });
84
- return () => {
85
- Disposed = true;
86
- window.removeEventListener("popstate", OnPopState);
87
- if (Opts.WatchHashChange) window.removeEventListener("hashchange", OnHashChange);
88
- };
89
- }
90
- function DefaultIgnoreMutation(Mutation) {
91
- if (Mutation.type === "attributes") {
92
- const Name = Mutation.attributeName ?? "";
93
- if (Name === "class" || Name === "style") return true;
94
- if (Name.startsWith("aria-") || Name.startsWith("data-")) return true;
95
- }
96
- return false;
97
- }
98
- function NormalizeOptions(Options) {
99
- return {
100
- Root: Options.Root ?? (() => document.querySelector("#app") ?? document.body),
101
- StableForMs: Options.StableForMs ?? 900,
102
- SampleWindowMs: Options.SampleWindowMs ?? 900,
103
- Threshold: Options.Threshold ?? 3,
104
- TimeoutMs: Options.TimeoutMs ?? 12e3,
105
- IgnoreMutation: Options.IgnoreMutation ?? DefaultIgnoreMutation,
106
- WatchHashChange: Options.WatchHashChange ?? true,
107
- Events: {
108
- Navigate: Options.Events?.Navigate ?? "SpaNavigate",
109
- Rendered: Options.Events?.Rendered ?? "SpaRendered"
110
- }
111
- };
112
- }
113
- async function WaitForDomMostlyStable(Opts) {
114
- const Events = [];
115
- let LastAboveAt = performance.now();
116
- let Done = false;
117
- const Observer = new MutationObserver((List) => {
118
- const Now = performance.now();
119
- for (const M of List) {
120
- if (Opts.Ignore?.(M)) continue;
121
- let Score = 1;
122
- if (M.type === "childList") Score = 2;
123
- Events.push({ T: Now, Score });
124
- }
125
- const Cutoff = Now - Opts.SampleWindowMs;
126
- while (Events.length && Events[0].T < Cutoff) Events.shift();
127
- const WindowScore = Events.reduce((Sum, E) => Sum + E.Score, 0);
128
- if (WindowScore > Opts.Threshold) LastAboveAt = Now;
129
- });
130
- Observer.observe(Opts.Root, {
131
- subtree: true,
132
- childList: true,
133
- attributes: true,
134
- characterData: true
135
- });
136
- const Start = performance.now();
137
- return await new Promise((Resolve) => {
138
- const Tick = () => {
139
- if (Done) return;
140
- const Now = performance.now();
141
- if (Now - LastAboveAt >= Opts.StableForMs) {
142
- Done = true;
143
- Observer.disconnect();
144
- Resolve(true);
145
- return;
146
- }
147
- if (Now - Start >= Opts.TimeoutMs) {
148
- Done = true;
149
- Observer.disconnect();
150
- Resolve(false);
151
- return;
152
- }
153
- setTimeout(Tick, 100);
154
- };
155
- setTimeout(Tick, 0);
156
- });
157
- }
158
-
159
- // sources/src/sort.ts
160
- function CreateSortWorkerURL() {
161
- const WorkerCode = `
162
- self.onmessage = (e) => {
163
- const { entries, jobId } = e.data;
164
- // entries: Array<[string, number]>
165
- // \uB0B4\uB9BC\uCC28\uC21C \uC815\uB82C
166
- entries.sort((a, b) => b[1] - a[1]);
167
- self.postMessage({ jobId, sorted: entries });
168
- };
169
- `;
170
- return URL.createObjectURL(new Blob([WorkerCode], { type: "text/javascript" }));
171
- }
172
- function MakeWorkerPool(Size) {
173
- const Url = CreateSortWorkerURL();
174
- const Workers = Array.from({ length: Size }, () => new Worker(Url));
175
- return {
176
- Workers,
177
- dispose() {
178
- Workers.forEach((W) => W.terminate());
179
- URL.revokeObjectURL(Url);
180
- }
181
- };
182
- }
183
- function CollectDataVAttributes(Root = document) {
184
- const Counts = /* @__PURE__ */ Object.create(null);
185
- const Walker = Root.createTreeWalker(
186
- Root.documentElement || Root,
187
- NodeFilter.SHOW_ELEMENT
188
- );
189
- let Node = Walker.currentNode;
190
- while (Node) {
191
- if (Node instanceof Element) {
192
- for (const Attr of Node.attributes) {
193
- const Name = Attr.name;
194
- if (Name.startsWith("data-v-")) {
195
- Counts[Name] = (Counts[Name] || 0) + 1;
196
- }
197
- }
198
- }
199
- Node = Walker.nextNode();
200
- }
201
- return Counts;
202
- }
203
- function MergeSortedChunks(Chunks) {
204
- const Heap = [];
205
- function Push(Item) {
206
- Heap.push(Item);
207
- let I = Heap.length - 1;
208
- while (I > 0) {
209
- const P = I - 1 >> 1;
210
- if (Heap[P].count >= Heap[I].count) break;
211
- [Heap[P], Heap[I]] = [Heap[I], Heap[P]];
212
- I = P;
213
- }
214
- }
215
- ;
216
- function Pop() {
217
- const Top = Heap[0];
218
- const Last = Heap.pop();
219
- if (Heap.length) {
220
- Heap[0] = Last;
221
- let I = 0;
222
- while (true) {
223
- const L = I * 2 + 1;
224
- const R = L + 1;
225
- let M = I;
226
- if (L < Heap.length && Heap[L].count > Heap[M].count) M = L;
227
- if (R < Heap.length && Heap[R].count > Heap[M].count) M = R;
228
- if (M === I) break;
229
- [Heap[I], Heap[M]] = [Heap[M], Heap[I]];
230
- I = M;
231
- }
232
- }
233
- return Top;
234
- }
235
- for (let C = 0; C < Chunks.length; C++) {
236
- const Arr = Chunks[C];
237
- if (Arr && Arr.length) {
238
- const [Attr, Count] = Arr[0];
239
- Push({ Count, Attr, ChunkIndex: C, IndexInChunk: 0 });
240
- }
241
- }
242
- const Out = [];
243
- while (Heap.length) {
244
- const { Attr, Count, ChunkIndex, IndexInChunk } = Pop();
245
- Out.push([Attr, Count]);
246
- const NextIndex = IndexInChunk + 1;
247
- const Arr = Chunks[ChunkIndex];
248
- if (NextIndex < Arr.length) {
249
- const [NAttr, NCount] = Arr[NextIndex];
250
- Push({ Count: NCount, Attr: NAttr, ChunkIndex, IndexInChunk: NextIndex });
251
- }
252
- }
253
- return Out;
254
- }
255
- async function RankCountsWithWorkersParallel(Counts) {
256
- const Entries = Object.entries(Counts);
257
- const Hc = Math.max(1, navigator.hardwareConcurrency || 1);
258
- const WorkerCount = Math.min(8, Math.max(1, Hc - 1));
259
- const ShouldParallel = Entries.length >= 5e3 && WorkerCount > 1;
260
- const ActualWorkers = ShouldParallel ? WorkerCount : 1;
261
- const Pool = MakeWorkerPool(ActualWorkers);
262
- try {
263
- const Chunks = Array.from({ length: ActualWorkers }, () => []);
264
- for (let I = 0; I < Entries.length; I++) {
265
- Chunks[I % ActualWorkers].push(Entries[I]);
266
- }
267
- const SortedChunks = await Promise.all(
268
- Chunks.map((ChunkEntries, Idx) => {
269
- return new Promise((Resolve, Reject) => {
270
- const Worker2 = Pool.Workers[Idx];
271
- const JobId = Idx + ":" + Date.now();
272
- const OnMsg = (E) => {
273
- if (E.data?.jobId !== JobId) return;
274
- Worker2.removeEventListener("message", OnMsg);
275
- Worker2.removeEventListener("error", OnErr);
276
- Resolve(E.data.sorted);
277
- };
278
- const OnErr = (Err) => {
279
- Worker2.removeEventListener("message", OnMsg);
280
- Worker2.removeEventListener("error", OnErr);
281
- Reject(Err);
282
- };
283
- Worker2.addEventListener("message", OnMsg);
284
- Worker2.addEventListener("error", OnErr);
285
- Worker2.postMessage({ entries: ChunkEntries, jobId: JobId });
286
- });
287
- })
288
- );
289
- const Merged = SortedChunks.length === 1 ? SortedChunks[0] : MergeSortedChunks(SortedChunks);
290
- return { Result: Merged, TotalKeys: Merged.length, WorkerCount: ActualWorkers, HardwareConcurrency: Hc };
291
- } finally {
292
- Pool.dispose();
293
- }
294
- }
295
-
296
- // sources/src/index.ts
297
- var Win = typeof unsafeWindow !== "undefined" ? unsafeWindow : window;
298
- function RunNamuLinkUserscript(BrowserWindow, UserscriptName = "NamuLink") {
299
- const ProtectedFunctionPrototypeToString = BrowserWindow.Function.prototype.toString;
300
- let PowerLinkGenerationPositiveRegExps = [[
301
- /for *\( *; *; *\) *switch *\( *_[a-z0-9]+\[_[a-z0-9]+\([a-z0-9]+\)\] *=_[a-z0-9]+/,
302
- /_[a-z0-9]+\[('|")[A-Z]+('|")\]\)\(\[ *\]\)/,
303
- /0x[a-z0-9]+ *\) *; *case/
304
- ], [
305
- /; *return *this\[_0x[a-z0-9]+\( *0x[0-9a-z]+ *\)/,
306
- /; *if *\( *_0x[a-z0-9]+ *&& *\( *_0x[a-z0-9]+ *= *_0x[a-z0-9]+/,
307
- /\) *, *void *\( *this *\[ *_0x[a-z0-9]+\( *0x[0-9a-z]+ *\) *\] *= *_0x[a-z0-9]+ *\[/
308
- ]];
309
- BrowserWindow.Function.prototype.bind = new Proxy(BrowserWindow.Function.prototype.bind, {
310
- // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
311
- apply(Target, ThisArg, Args) {
312
- let StringifiedFunc = Reflect.apply(ProtectedFunctionPrototypeToString, ThisArg, Args);
313
- if (PowerLinkGenerationPositiveRegExps.filter((PowerLinkGenerationPositiveRegExp) => PowerLinkGenerationPositiveRegExp.filter((Index) => Index.test(StringifiedFunc)).length >= 3).length === 1) {
314
- console.debug(`[${UserscriptName}]: Function.prototype.bind:`, ThisArg);
315
- return Reflect.apply(Target, () => {
316
- }, []);
317
- }
318
- return Reflect.apply(Target, ThisArg, Args);
319
- }
320
- });
321
- let PowerLinkGenerationSkeletionPositiveRegExps = [[
322
- /\( *\) *=> *{ *var *_0x[0-9a-z]+ *= *a0_0x[0-9a-f]+ *; *this\[ *_0x[a-z0-9]+\( *0x[0-9a-f]+ *\) *\]\(\); *}/,
323
- /\( *\) *=> *{ *var *_0x[0-9a-z]+ *= *a0_0x[0-9a-f]+ *; *this\[ *_0x[a-z0-9]+\( *0x[0-9a-f]+ *\) *\]\(\); *}/
324
- ], [
325
- /\( *\) *=> *{ *var _0x[a-z0-9]+ *= *_0x[a-z0-9]+ *; *if *\( *this\[ *_0x[a-z0-9]+ *\( *0x[0-9a-f]+ *\) *\] *\) *return *clearTimeout/,
326
- /\( *0x[0-9a-f]+ *\) *\] *\) *, *void *\( *this\[ *_0x[a-z0-9]+\( *0x[0-9a-f]+ *\) *\] *= *void *\([x0-9a-f*+-]+ *\) *\) *; *this\[_0x[a-z0-9]+\( *0x[0-9a-f]+ *\) *\] *\(\) *;/
327
- ]];
328
- BrowserWindow.setTimeout = new Proxy(BrowserWindow.setTimeout, {
329
- apply(Target, ThisArg, Args) {
330
- let StringifiedFunc = Reflect.apply(ProtectedFunctionPrototypeToString, Args[0], Args);
331
- if (PowerLinkGenerationSkeletionPositiveRegExps.filter((PowerLinkGenerationSkeletionPositiveRegExp) => PowerLinkGenerationSkeletionPositiveRegExp.filter((Index) => Index.test(StringifiedFunc)).length >= 1).length === 1) {
332
- console.debug(`[${UserscriptName}]: setTimeout:`, Args[0]);
333
- return;
334
- }
335
- return Reflect.apply(Target, ThisArg, Args);
336
- }
337
- });
338
- if (document.readyState === "loading") {
339
- window.addEventListener("DOMContentLoaded", () => {
340
- InstallSpaNavigationBridge({
341
- Root: () => document.getElementById("#app"),
342
- StableForMs: 900,
343
- SampleWindowMs: 900,
344
- Threshold: 3,
345
- TimeoutMs: 12e3,
346
- IgnoreMutation: DefaultIgnoreMutation,
347
- WatchHashChange: true
348
- });
349
- });
350
- } else {
351
- window.addEventListener("DOMContentLoaded", () => {
352
- InstallSpaNavigationBridge({
353
- Root: () => document.getElementById("#app"),
354
- StableForMs: 900,
355
- SampleWindowMs: 900,
356
- Threshold: 3,
357
- TimeoutMs: 12e3,
358
- IgnoreMutation: DefaultIgnoreMutation,
359
- WatchHashChange: true
360
- });
361
- });
362
- }
363
- const Handler = async () => {
364
- let HTMLEle = CollectDataVAttributes(document);
365
- const { Result, TotalKeys, WorkerCount, HardwareConcurrency } = await RankCountsWithWorkersParallel(HTMLEle);
366
- let TargetedAttrsDOMs = [];
367
- Result.filter(([, Count]) => Count <= 30).forEach(([Attr, Count]) => {
368
- TargetedAttrsDOMs.push(...[...document.querySelectorAll(`[${Attr}]`)].filter((El) => El instanceof HTMLElement));
369
- });
370
- TargetedAttrsDOMs = TargetedAttrsDOMs.filter((El) => getComputedStyle(El).getPropertyValue("display") === "flex");
371
- TargetedAttrsDOMs = TargetedAttrsDOMs.filter((El) => [...El.querySelectorAll("*")].some((Child) => Child instanceof HTMLElement && typeof Child.click === "function"));
372
- TargetedAttrsDOMs = TargetedAttrsDOMs.filter((El) => [...El.querySelectorAll("*")].filter((Child) => Child instanceof HTMLElement && Child.getBoundingClientRect().bottom - Child.getBoundingClientRect().top > 100 && Child.getBoundingClientRect().right - Child.getBoundingClientRect().left > 100).length <= 50);
373
- TargetedAttrsDOMs = TargetedAttrsDOMs.filter((El) => {
374
- let Count = [...El.querySelectorAll("*")].filter((Child) => Child.getBoundingClientRect().bottom - Child.getBoundingClientRect().top > 25 && Child.getBoundingClientRect().right - Child.getBoundingClientRect().left > 25 && (Child instanceof SVGPathElement && Child.getAttribute("d") !== null) || Child instanceof HTMLImageElement && Child.src.includes("//i.namu.wiki/i/")).length;
375
- return 1 <= Count && Count <= 6;
376
- });
377
- TargetedAttrsDOMs = TargetedAttrsDOMs.filter((El) => [...El.querySelectorAll("*")].some((Child) => Child instanceof HTMLElement && getComputedStyle(Child, "::after").getPropertyValue("content").includes(":") && Child.getBoundingClientRect().right - Child.getBoundingClientRect().left > 20) === false);
378
- TargetedAttrsDOMs = TargetedAttrsDOMs.filter((El) => [...El.querySelectorAll("*")].every((Child) => Child instanceof HTMLElement && !new Date(Child.getHTML()).getTime()));
379
- console.debug(`[${UserscriptName}]`, TargetedAttrsDOMs);
380
- TargetedAttrsDOMs.forEach((El) => {
381
- setInterval(() => {
382
- El.setAttribute("style", "display: none !important; visibility: hidden !important;");
383
- }, 250);
384
- });
385
- };
386
- window.addEventListener("SpaRendered", () => setTimeout(Handler, 2500));
387
- window.addEventListener("SpaRendered", Handler);
388
- }
389
- RunNamuLinkUserscript(Win);
390
- export {
391
- RunNamuLinkUserscript
392
- };
393
- /*!
394
- * @license MPL-2.0
395
- * This Source Code Form is subject to the terms of the Mozilla Public
396
- * License, v. 2.0. If a copy of the MPL was not distributed with this
397
- * file, You can obtain one at https://mozilla.org/MPL/2.0/.
398
- *
399
- * Contributors:
400
- * - See Git history at https://github.com/FilteringDev/tinyShield for detailed authorship information.
401
- */
402
- //# sourceMappingURL=interface.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../sources/src/spa.ts", "../sources/src/sort.ts", "../sources/src/index.ts"],
4
- "sourcesContent": ["/*!\n * @license MPL-2.0\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n *\n * Contributors:\n * - See Git history at https://github.com/FilteringDev/tinyShield for detailed authorship information.\n */\n\ntype SpaNavigateCause =\n | 'init'\n | 'pushState'\n | 'replaceState'\n | 'popstate'\n | 'hashchange'\n\nexport type SpaNavigateDetail = {\n Seq: number\n From: string | null\n To: string\n Cause: SpaNavigateCause\n}\n\nexport type SpaRenderedDetail = {\n Seq: number\n Url: string\n Ok: boolean\n}\n\nexport type IgnoreMutation = (Mutation: MutationRecord) => boolean\n\nexport type SpaBridgeOptions = {\n Root?: () => Node | null\n StableForMs?: number\n SampleWindowMs?: number\n Threshold?: number\n TimeoutMs?: number\n IgnoreMutation?: IgnoreMutation\n WatchHashChange?: boolean\n Events?: {\n Navigate?: 'SpaNavigate'\n Rendered?: 'SpaRendered'\n }\n}\n\ntype WaitStableOptions = {\n Root: Node\n StableForMs: number\n SampleWindowMs: number\n Threshold: number\n TimeoutMs: number\n Ignore?: IgnoreMutation\n}\n\n/**\n * SPA \uB77C\uC6B0\uD305(URL \uBCC0\uACBD)\uC744 \uAC10\uC9C0\uD574 \uCEE4\uC2A4\uD140 \uC774\uBCA4\uD2B8\uB97C \uBC1C\uD589\uD558\uACE0,\n * DOM\uC774 \uCDA9\uBD84\uD788 \uC548\uC815\uD654\uB418\uBA74 'Rendered' \uC774\uBCA4\uD2B8\uAE4C\uC9C0 \uBC1C\uD589\uD558\uB294 \uBE0C\uB9BF\uC9C0\n *\n * Events (PascalCase):\n * - 'SpaNavigate' => CustomEvent<SpaNavigateDetail>\n * - 'SpaRendered' => CustomEvent<SpaRenderedDetail>\n */\nexport function InstallSpaNavigationBridge(Options: SpaBridgeOptions = {}): () => void {\n\n const Opts = NormalizeOptions(Options)\n\n const EventNavigate = Opts.Events.Navigate\n const EventRendered = Opts.Events.Rendered\n\n const FireNavigate = (Detail: SpaNavigateDetail) => {\n window.dispatchEvent(new CustomEvent<SpaNavigateDetail>(EventNavigate, { detail: Detail }))\n }\n\n const FireRendered = (Detail: SpaRenderedDetail) => {\n window.dispatchEvent(new CustomEvent<SpaRenderedDetail>(EventRendered, { detail: Detail }))\n }\n\n let LastUrl = window.location.href\n let NavSeq = 0\n let Disposed = false\n\n const OnUrlMaybeChanged = (Cause: SpaNavigateCause) => {\n if (Disposed) return\n\n const Url = window.location.href\n if (Url === LastUrl) return\n\n const From = LastUrl\n LastUrl = Url\n\n const Seq = ++NavSeq\n FireNavigate({ Seq, From, To: Url, Cause })\n\n void (async () => {\n const Root = Opts.Root()\n if (!Root) {\n if (Seq !== NavSeq || Disposed) return\n FireRendered({ Seq, Url, Ok: true })\n return\n }\n\n const Ok = await WaitForDomMostlyStable({\n Root: Root,\n StableForMs: Opts.StableForMs,\n SampleWindowMs: Opts.SampleWindowMs,\n Threshold: Opts.Threshold,\n TimeoutMs: Opts.TimeoutMs,\n Ignore: Opts.IgnoreMutation,\n })\n\n if (Seq !== NavSeq || Disposed) return\n FireRendered({ Seq, Url, Ok })\n })()\n }\n\n const PatchHistory = (MethodName: 'pushState' | 'replaceState') => {\n const Original = history[MethodName].bind(history)\n\n const Patched = (...Args: Parameters<History['pushState']>): ReturnType<History['pushState']> => {\n const Ret = Original(...Args)\n queueMicrotask(() => OnUrlMaybeChanged(MethodName))\n return Ret\n }\n\n Object.defineProperty(history, MethodName, {\n value: Patched,\n configurable: true,\n writable: true,\n })\n }\n\n PatchHistory('pushState')\n PatchHistory('replaceState')\n\n const OnPopState = () => OnUrlMaybeChanged('popstate')\n window.addEventListener('popstate', OnPopState)\n\n const OnHashChange = () => OnUrlMaybeChanged('hashchange')\n if (Opts.WatchHashChange) window.addEventListener('hashchange', OnHashChange)\n\n queueMicrotask(() => {\n if (Disposed) return\n\n const Seq = ++NavSeq\n FireNavigate({ Seq, From: null, To: window.location.href, Cause: 'init' })\n\n void (async () => {\n const Root = Opts.Root()\n if (!Root) {\n if (Seq !== NavSeq || Disposed) return\n FireRendered({ Seq, Url: window.location.href, Ok: true })\n return\n }\n\n const Ok = await WaitForDomMostlyStable({\n Root: Root,\n StableForMs: Opts.StableForMs,\n SampleWindowMs: Opts.SampleWindowMs,\n Threshold: Opts.Threshold,\n TimeoutMs: Opts.TimeoutMs,\n Ignore: Opts.IgnoreMutation,\n })\n\n if (Seq !== NavSeq || Disposed) return\n FireRendered({ Seq, Url: window.location.href, Ok: Ok })\n })()\n })\n\n return () => {\n Disposed = true\n window.removeEventListener('popstate', OnPopState)\n if (Opts.WatchHashChange) window.removeEventListener('hashchange', OnHashChange)\n }\n}\n\nexport function DefaultIgnoreMutation(Mutation: MutationRecord): boolean {\n if (Mutation.type === 'attributes') {\n const Name = Mutation.attributeName ?? ''\n if (Name === 'class' || Name === 'style') return true\n if (Name.startsWith('aria-') || Name.startsWith('data-')) return true\n }\n return false\n}\n\nfunction NormalizeOptions(Options: SpaBridgeOptions) {\n return {\n Root: Options.Root ?? (() => document.querySelector('#app') ?? document.body),\n StableForMs: Options.StableForMs ?? 900,\n SampleWindowMs: Options.SampleWindowMs ?? 900,\n Threshold: Options.Threshold ?? 3,\n TimeoutMs: Options.TimeoutMs ?? 12000,\n IgnoreMutation: Options.IgnoreMutation ?? DefaultIgnoreMutation,\n WatchHashChange: Options.WatchHashChange ?? true,\n Events: {\n Navigate: Options.Events?.Navigate ?? 'SpaNavigate',\n Rendered: Options.Events?.Rendered ?? 'SpaRendered',\n },\n }\n}\n\nasync function WaitForDomMostlyStable(Opts: WaitStableOptions): Promise<boolean> {\n const Events: Array<{ T: number; Score: number }> = []\n let LastAboveAt = performance.now()\n let Done = false\n\n const Observer = new MutationObserver((List) => {\n const Now = performance.now()\n\n for (const M of List) {\n if (Opts.Ignore?.(M)) continue\n\n let Score = 1\n if (M.type === 'childList') Score = 2\n Events.push({ T: Now, Score })\n }\n\n const Cutoff = Now - Opts.SampleWindowMs\n while (Events.length && Events[0].T < Cutoff) Events.shift()\n\n const WindowScore = Events.reduce((Sum, E) => Sum + E.Score, 0)\n if (WindowScore > Opts.Threshold) LastAboveAt = Now\n })\n\n Observer.observe(Opts.Root, {\n subtree: true,\n childList: true,\n attributes: true,\n characterData: true,\n })\n\n const Start = performance.now()\n\n return await new Promise<boolean>((Resolve) => {\n const Tick = () => {\n if (Done) return\n\n const Now = performance.now()\n\n if (Now - LastAboveAt >= Opts.StableForMs) {\n Done = true\n Observer.disconnect()\n Resolve(true)\n return\n }\n\n if (Now - Start >= Opts.TimeoutMs) {\n Done = true\n Observer.disconnect()\n Resolve(false)\n return\n }\n\n setTimeout(Tick, 100)\n }\n\n setTimeout(Tick, 0)\n })\n}", "export function CreateSortWorkerURL() {\n const WorkerCode = `\nself.onmessage = (e) => {\n const { entries, jobId } = e.data;\n // entries: Array<[string, number]>\n // \uB0B4\uB9BC\uCC28\uC21C \uC815\uB82C\n entries.sort((a, b) => b[1] - a[1]);\n self.postMessage({ jobId, sorted: entries });\n};\n`\n return URL.createObjectURL(new Blob([WorkerCode], { type: 'text/javascript' }))\n}\n\nexport function MakeWorkerPool(Size: number) {\n const Url = CreateSortWorkerURL()\n const Workers = Array.from({ length: Size }, () => new Worker(Url))\n return {\n Workers,\n dispose() {\n Workers.forEach(W => W.terminate())\n URL.revokeObjectURL(Url)\n }\n }\n}\n\nexport function CollectDataVAttributes(Root = document): Record<string, number> {\n const Counts = Object.create(null)\n\n const Walker = Root.createTreeWalker(\n Root.documentElement || Root,\n NodeFilter.SHOW_ELEMENT\n )\n\n let Node = Walker.currentNode\n while (Node) {\n if (Node instanceof Element) {\n for (const Attr of Node.attributes) {\n const Name = Attr.name\n if (Name.startsWith('data-v-')) {\n Counts[Name] = (Counts[Name] || 0) + 1\n }\n }\n }\n Node = Walker.nextNode()\n }\n return Counts\n}\n\nexport function MergeSortedChunks(Chunks: Array<Array<[string, number]>>): Array<[string, number]> {\n // chunks: Array<Array<[string, number]>> \uAC01\uAC01 \uB0B4\uB9BC\uCC28\uC21C\n // \uACB0\uACFC: \uC804\uCCB4 \uB0B4\uB9BC\uCC28\uC21C\n\n // \uAC04\uB2E8\uD55C max-heap (count \uAE30\uC900)\n const Heap = []\n function Push(Item) {\n Heap.push(Item)\n let I = Heap.length - 1\n while (I > 0) {\n const P = (I - 1) >> 1\n if (Heap[P].count >= Heap[I].count) break\n [Heap[P], Heap[I]] = [Heap[I], Heap[P]]\n I = P\n }\n };\n function Pop() {\n const Top = Heap[0]\n const Last = Heap.pop()\n if (Heap.length) {\n Heap[0] = Last\n let I = 0\n while (true) {\n const L = I * 2 + 1\n const R = L + 1\n let M = I\n if (L < Heap.length && Heap[L].count > Heap[M].count) M = L\n if (R < Heap.length && Heap[R].count > Heap[M].count) M = R\n if (M === I) break\n [Heap[I], Heap[M]] = [Heap[M], Heap[I]]\n I = M\n }\n }\n return Top\n }\n\n for (let C = 0; C < Chunks.length; C++) {\n const Arr = Chunks[C]\n if (Arr && Arr.length) {\n const [Attr, Count] = Arr[0]\n Push({ Count, Attr, ChunkIndex: C, IndexInChunk: 0 })\n }\n }\n\n const Out = []\n while (Heap.length) {\n const { Attr, Count, ChunkIndex, IndexInChunk } = Pop()\n Out.push([Attr, Count])\n\n const NextIndex = IndexInChunk + 1\n const Arr = Chunks[ChunkIndex]\n if (NextIndex < Arr.length) {\n const [NAttr, NCount] = Arr[NextIndex]\n Push({ Count: NCount, Attr: NAttr, ChunkIndex, IndexInChunk: NextIndex })\n }\n }\n\n return Out\n}\n\nexport async function RankCountsWithWorkersParallel(Counts: Record<string, number>) {\n const Entries = Object.entries(Counts) // [attr, count][]\n\n // \uB17C\uB9AC \uCF54\uC5B4 \uC218 \uAE30\uBC18 \uC6CC\uCEE4 \uAC1C\uC218 \uACB0\uC815\n // - \uB108\uBB34 \uB9CE\uC774 \uB9CC\uB4E4\uBA74 \uC624\uD788\uB824 \uC5ED\uD6A8\uACFC\uB77C \uC0C1\uD55C\uC744 \uB460\n const Hc = Math.max(1, navigator.hardwareConcurrency || 1)\n const WorkerCount = Math.min(8, Math.max(1, Hc - 1))\n\n // entries\uAC00 \uC801\uC73C\uBA74 \uBCD1\uB82C\uD654 \uC774\uB4DD\uC774 \uAC70\uC758 \uC5C6\uC74C \u2192 1\uAC1C\uB85C\n const ShouldParallel = Entries.length >= 5000 && WorkerCount > 1\n const ActualWorkers = ShouldParallel ? WorkerCount : 1\n const Pool = MakeWorkerPool(ActualWorkers)\n\n try {\n // chunks \uBD84\uD560\n const Chunks = Array.from({ length: ActualWorkers }, () => [])\n for (let I = 0; I < Entries.length; I++) {\n Chunks[I % ActualWorkers].push(Entries[I])\n }\n\n // \uAC01 \uC6CC\uCEE4\uC5D0 \uC815\uB82C \uC694\uCCAD\n const SortedChunks = await Promise.all(\n Chunks.map((ChunkEntries, Idx) => {\n return new Promise<Array<[string, number]>>((Resolve, Reject) => {\n const Worker = Pool.Workers[Idx]\n const JobId = Idx + ':' + Date.now()\n\n const OnMsg = (E) => {\n if (E.data?.jobId !== JobId) return\n Worker.removeEventListener('message', OnMsg)\n Worker.removeEventListener('error', OnErr)\n Resolve(E.data.sorted)\n }\n const OnErr = (Err) => {\n Worker.removeEventListener('message', OnMsg)\n Worker.removeEventListener('error', OnErr)\n Reject(Err)\n }\n\n Worker.addEventListener('message', OnMsg)\n Worker.addEventListener('error', OnErr)\n Worker.postMessage({ entries: ChunkEntries, jobId: JobId })\n })\n })\n )\n // \uBCD1\uD569\uD574\uC11C \uC804\uCCB4 \uC21C\uC704 \uC0DD\uC131\n const Merged = (SortedChunks.length === 1)\n ? SortedChunks[0]\n : MergeSortedChunks(SortedChunks)\n\n return { Result: Merged, TotalKeys: Merged.length, WorkerCount: ActualWorkers, HardwareConcurrency: Hc }\n } finally {\n Pool.dispose()\n }\n}", "/*!\n * @license MPL-2.0\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n *\n * Contributors:\n * - See Git history at https://github.com/FilteringDev/tinyShield for detailed authorship information.\n */\n\ntype unsafeWindow = typeof window\n// eslint-disable-next-line @typescript-eslint/naming-convention\ndeclare const unsafeWindow: unsafeWindow\nimport * as SPA from './spa.js'\nimport * as Sort from './sort.js'\n\nconst Win = typeof unsafeWindow !== 'undefined' ? unsafeWindow : window\n\nexport function RunNamuLinkUserscript(BrowserWindow: typeof window, UserscriptName: string = 'NamuLink'): void {\n const ProtectedFunctionPrototypeToString = BrowserWindow.Function.prototype.toString\n\n let PowerLinkGenerationPositiveRegExps: RegExp[][] = [[\n /for *\\( *; *; *\\) *switch *\\( *_[a-z0-9]+\\[_[a-z0-9]+\\([a-z0-9]+\\)\\] *=_[a-z0-9]+/,\n /_[a-z0-9]+\\[('|\")[A-Z]+('|\")\\]\\)\\(\\[ *\\]\\)/,\n /0x[a-z0-9]+ *\\) *; *case/\n ], [\n /; *return *this\\[_0x[a-z0-9]+\\( *0x[0-9a-z]+ *\\)/,\n /; *if *\\( *_0x[a-z0-9]+ *&& *\\( *_0x[a-z0-9]+ *= *_0x[a-z0-9]+/,\n /\\) *, *void *\\( *this *\\[ *_0x[a-z0-9]+\\( *0x[0-9a-z]+ *\\) *\\] *= *_0x[a-z0-9]+ *\\[/\n ]]\n\n BrowserWindow.Function.prototype.bind = new Proxy(BrowserWindow.Function.prototype.bind, {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n apply(Target: typeof Function.prototype.bind, ThisArg: Function, Args: Parameters<typeof Function.prototype.bind>) {\n let StringifiedFunc = Reflect.apply(ProtectedFunctionPrototypeToString, ThisArg, Args) as string\n if (PowerLinkGenerationPositiveRegExps.filter(PowerLinkGenerationPositiveRegExp => PowerLinkGenerationPositiveRegExp.filter(Index => Index.test(StringifiedFunc)).length >= 3).length === 1) {\n console.debug(`[${UserscriptName}]: Function.prototype.bind:`, ThisArg)\n return Reflect.apply(Target, () => {}, [])\n }\n return Reflect.apply(Target, ThisArg, Args)\n }\n })\n\n let PowerLinkGenerationSkeletionPositiveRegExps: RegExp[][] = [[\n /\\( *\\) *=> *{ *var *_0x[0-9a-z]+ *= *a0_0x[0-9a-f]+ *; *this\\[ *_0x[a-z0-9]+\\( *0x[0-9a-f]+ *\\) *\\]\\(\\); *}/,\n /\\( *\\) *=> *{ *var *_0x[0-9a-z]+ *= *a0_0x[0-9a-f]+ *; *this\\[ *_0x[a-z0-9]+\\( *0x[0-9a-f]+ *\\) *\\]\\(\\); *}/\n ], [\n /\\( *\\) *=> *{ *var _0x[a-z0-9]+ *= *_0x[a-z0-9]+ *; *if *\\( *this\\[ *_0x[a-z0-9]+ *\\( *0x[0-9a-f]+ *\\) *\\] *\\) *return *clearTimeout/,\n /\\( *0x[0-9a-f]+ *\\) *\\] *\\) *, *void *\\( *this\\[ *_0x[a-z0-9]+\\( *0x[0-9a-f]+ *\\) *\\] *= *void *\\([x0-9a-f*+-]+ *\\) *\\) *; *this\\[_0x[a-z0-9]+\\( *0x[0-9a-f]+ *\\) *\\] *\\(\\) *;/\n ]]\n\n BrowserWindow.setTimeout = new Proxy(BrowserWindow.setTimeout, {\n apply(Target: typeof setTimeout, ThisArg: undefined, Args: Parameters<typeof setTimeout>) {\n let StringifiedFunc = Reflect.apply(ProtectedFunctionPrototypeToString, Args[0], Args) as string\n if (PowerLinkGenerationSkeletionPositiveRegExps.filter(PowerLinkGenerationSkeletionPositiveRegExp => PowerLinkGenerationSkeletionPositiveRegExp.filter(Index => Index.test(StringifiedFunc)).length >= 1).length === 1) {\n console.debug(`[${UserscriptName}]: setTimeout:`, Args[0])\n return\n }\n\n return Reflect.apply(Target, ThisArg, Args)\n }\n })\n\n if (document.readyState === 'loading') {\n window.addEventListener('DOMContentLoaded', () => {\n SPA.InstallSpaNavigationBridge({\n Root: () => document.getElementById('#app'),\n StableForMs: 900,\n SampleWindowMs: 900,\n Threshold: 3,\n TimeoutMs: 12000,\n IgnoreMutation: SPA.DefaultIgnoreMutation,\n WatchHashChange: true\n })\n })\n } else {\n // \uC774\uBBF8 DOMContentLoaded \uC774\uD6C4\n window.addEventListener('DOMContentLoaded', () => {\n SPA.InstallSpaNavigationBridge({\n Root: () => document.getElementById('#app'),\n StableForMs: 900,\n SampleWindowMs: 900,\n Threshold: 3,\n TimeoutMs: 12000,\n IgnoreMutation: SPA.DefaultIgnoreMutation,\n WatchHashChange: true\n })\n })\n }\n\n const Handler = async () => {\n let HTMLEle = Sort.CollectDataVAttributes(document)\n const { Result, TotalKeys, WorkerCount, HardwareConcurrency } = await Sort.RankCountsWithWorkersParallel(HTMLEle)\n let TargetedAttrsDOMs: HTMLElement[] = []\n Result.filter(([, Count]) => Count <= 30).forEach(([Attr, Count]) => {\n TargetedAttrsDOMs.push(...[...document.querySelectorAll(`[${Attr}]`)].filter((El) => El instanceof HTMLElement))\n })\n TargetedAttrsDOMs = TargetedAttrsDOMs.filter(El => getComputedStyle(El).getPropertyValue('display') === 'flex')\n TargetedAttrsDOMs = TargetedAttrsDOMs.filter(El => [...El.querySelectorAll('*')].some(Child => Child instanceof HTMLElement && typeof Child.click === 'function'))\n TargetedAttrsDOMs = TargetedAttrsDOMs.filter(El => [...El.querySelectorAll('*')].filter(Child => Child instanceof HTMLElement && Child.getBoundingClientRect().bottom - Child.getBoundingClientRect().top > 100 && Child.getBoundingClientRect().right - Child.getBoundingClientRect().left > 100).length <= 50)\n TargetedAttrsDOMs = TargetedAttrsDOMs.filter(El => {\n let Count = [...El.querySelectorAll('*')].filter(Child => (Child.getBoundingClientRect().bottom - Child.getBoundingClientRect().top > 25 && Child.getBoundingClientRect().right - Child.getBoundingClientRect().left > 25 && (Child instanceof SVGPathElement && Child.getAttribute('d') !== null) || (Child instanceof HTMLImageElement && Child.src.includes('//i.namu.wiki/i/')))).length\n return 1 <= Count && Count <= 6\n })\n TargetedAttrsDOMs = TargetedAttrsDOMs.filter(El => [...El.querySelectorAll('*')].some(Child => Child instanceof HTMLElement && getComputedStyle(Child, '::after').getPropertyValue('content').includes(':') && Child.getBoundingClientRect().right - Child.getBoundingClientRect().left > 20) === false)\n TargetedAttrsDOMs = TargetedAttrsDOMs.filter(El => [...El.querySelectorAll('*')].every(Child => Child instanceof HTMLElement && !new Date(Child.getHTML()).getTime()))\n console.debug(`[${UserscriptName}]`, TargetedAttrsDOMs)\n TargetedAttrsDOMs.forEach(El => {\n setInterval(() => {\n El.setAttribute('style', 'display: none !important; visibility: hidden !important;')\n }, 250)\n })\n }\n\n window.addEventListener('SpaRendered', () => setTimeout(Handler, 2500))\n window.addEventListener('SpaRendered', Handler)\n}\n\nRunNamuLinkUserscript(Win)"],
5
- "mappings": ";AA+DO,SAAS,2BAA2B,UAA4B,CAAC,GAAe;AAErF,QAAM,OAAO,iBAAiB,OAAO;AAErC,QAAM,gBAAgB,KAAK,OAAO;AAClC,QAAM,gBAAgB,KAAK,OAAO;AAElC,QAAM,eAAe,CAAC,WAA8B;AAClD,WAAO,cAAc,IAAI,YAA+B,eAAe,EAAE,QAAQ,OAAO,CAAC,CAAC;AAAA,EAC5F;AAEA,QAAM,eAAe,CAAC,WAA8B;AAClD,WAAO,cAAc,IAAI,YAA+B,eAAe,EAAE,QAAQ,OAAO,CAAC,CAAC;AAAA,EAC5F;AAEA,MAAI,UAAU,OAAO,SAAS;AAC9B,MAAI,SAAS;AACb,MAAI,WAAW;AAEf,QAAM,oBAAoB,CAAC,UAA4B;AACrD,QAAI,SAAU;AAEd,UAAM,MAAM,OAAO,SAAS;AAC5B,QAAI,QAAQ,QAAS;AAErB,UAAM,OAAO;AACb,cAAU;AAEV,UAAM,MAAM,EAAE;AACd,iBAAa,EAAE,KAAK,MAAM,IAAI,KAAK,MAAM,CAAC;AAE1C,UAAM,YAAY;AAChB,YAAM,OAAO,KAAK,KAAK;AACvB,UAAI,CAAC,MAAM;AACT,YAAI,QAAQ,UAAU,SAAU;AAChC,qBAAa,EAAE,KAAK,KAAK,IAAI,KAAK,CAAC;AACnC;AAAA,MACF;AAEA,YAAM,KAAK,MAAM,uBAAuB;AAAA,QACtC;AAAA,QACA,aAAa,KAAK;AAAA,QAClB,gBAAgB,KAAK;AAAA,QACrB,WAAW,KAAK;AAAA,QAChB,WAAW,KAAK;AAAA,QAChB,QAAQ,KAAK;AAAA,MACf,CAAC;AAED,UAAI,QAAQ,UAAU,SAAU;AAChC,mBAAa,EAAE,KAAK,KAAK,GAAG,CAAC;AAAA,IAC/B,GAAG;AAAA,EACL;AAEA,QAAM,eAAe,CAAC,eAA6C;AACjE,UAAM,WAAW,QAAQ,UAAU,EAAE,KAAK,OAAO;AAEjD,UAAM,UAAU,IAAI,SAA6E;AAC/F,YAAM,MAAM,SAAS,GAAG,IAAI;AAC5B,qBAAe,MAAM,kBAAkB,UAAU,CAAC;AAClD,aAAO;AAAA,IACT;AAEA,WAAO,eAAe,SAAS,YAAY;AAAA,MACzC,OAAO;AAAA,MACP,cAAc;AAAA,MACd,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAEA,eAAa,WAAW;AACxB,eAAa,cAAc;AAE3B,QAAM,aAAa,MAAM,kBAAkB,UAAU;AACrD,SAAO,iBAAiB,YAAY,UAAU;AAE9C,QAAM,eAAe,MAAM,kBAAkB,YAAY;AACzD,MAAI,KAAK,gBAAiB,QAAO,iBAAiB,cAAc,YAAY;AAE5E,iBAAe,MAAM;AACnB,QAAI,SAAU;AAEd,UAAM,MAAM,EAAE;AACd,iBAAa,EAAE,KAAK,MAAM,MAAM,IAAI,OAAO,SAAS,MAAM,OAAO,OAAO,CAAC;AAEzE,UAAM,YAAY;AAChB,YAAM,OAAO,KAAK,KAAK;AACvB,UAAI,CAAC,MAAM;AACT,YAAI,QAAQ,UAAU,SAAU;AAChC,qBAAa,EAAE,KAAK,KAAK,OAAO,SAAS,MAAM,IAAI,KAAK,CAAC;AACzD;AAAA,MACF;AAEA,YAAM,KAAK,MAAM,uBAAuB;AAAA,QACtC;AAAA,QACA,aAAa,KAAK;AAAA,QAClB,gBAAgB,KAAK;AAAA,QACrB,WAAW,KAAK;AAAA,QAChB,WAAW,KAAK;AAAA,QAChB,QAAQ,KAAK;AAAA,MACf,CAAC;AAED,UAAI,QAAQ,UAAU,SAAU;AAChC,mBAAa,EAAE,KAAK,KAAK,OAAO,SAAS,MAAM,GAAO,CAAC;AAAA,IACzD,GAAG;AAAA,EACL,CAAC;AAED,SAAO,MAAM;AACX,eAAW;AACX,WAAO,oBAAoB,YAAY,UAAU;AACjD,QAAI,KAAK,gBAAiB,QAAO,oBAAoB,cAAc,YAAY;AAAA,EACjF;AACF;AAEO,SAAS,sBAAsB,UAAmC;AACvE,MAAI,SAAS,SAAS,cAAc;AAClC,UAAM,OAAO,SAAS,iBAAiB;AACvC,QAAI,SAAS,WAAW,SAAS,QAAS,QAAO;AACjD,QAAI,KAAK,WAAW,OAAO,KAAK,KAAK,WAAW,OAAO,EAAG,QAAO;AAAA,EACnE;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,SAA2B;AACnD,SAAO;AAAA,IACL,MAAM,QAAQ,SAAS,MAAM,SAAS,cAAc,MAAM,KAAK,SAAS;AAAA,IACxE,aAAa,QAAQ,eAAe;AAAA,IACpC,gBAAgB,QAAQ,kBAAkB;AAAA,IAC1C,WAAW,QAAQ,aAAa;AAAA,IAChC,WAAW,QAAQ,aAAa;AAAA,IAChC,gBAAgB,QAAQ,kBAAkB;AAAA,IAC1C,iBAAiB,QAAQ,mBAAmB;AAAA,IAC5C,QAAQ;AAAA,MACN,UAAU,QAAQ,QAAQ,YAAY;AAAA,MACtC,UAAU,QAAQ,QAAQ,YAAY;AAAA,IACxC;AAAA,EACF;AACF;AAEA,eAAe,uBAAuB,MAA2C;AAC/E,QAAM,SAA8C,CAAC;AACrD,MAAI,cAAc,YAAY,IAAI;AAClC,MAAI,OAAO;AAEX,QAAM,WAAW,IAAI,iBAAiB,CAAC,SAAS;AAC9C,UAAM,MAAM,YAAY,IAAI;AAE5B,eAAW,KAAK,MAAM;AACpB,UAAI,KAAK,SAAS,CAAC,EAAG;AAEtB,UAAI,QAAQ;AACZ,UAAI,EAAE,SAAS,YAAa,SAAQ;AACpC,aAAO,KAAK,EAAE,GAAG,KAAK,MAAM,CAAC;AAAA,IAC/B;AAEA,UAAM,SAAS,MAAM,KAAK;AAC1B,WAAO,OAAO,UAAU,OAAO,CAAC,EAAE,IAAI,OAAQ,QAAO,MAAM;AAE3D,UAAM,cAAc,OAAO,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,OAAO,CAAC;AAC9D,QAAI,cAAc,KAAK,UAAW,eAAc;AAAA,EAClD,CAAC;AAED,WAAS,QAAQ,KAAK,MAAM;AAAA,IAC1B,SAAS;AAAA,IACT,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB,CAAC;AAED,QAAM,QAAQ,YAAY,IAAI;AAE9B,SAAO,MAAM,IAAI,QAAiB,CAAC,YAAY;AAC7C,UAAM,OAAO,MAAM;AACjB,UAAI,KAAM;AAEV,YAAM,MAAM,YAAY,IAAI;AAE5B,UAAI,MAAM,eAAe,KAAK,aAAa;AACzC,eAAO;AACP,iBAAS,WAAW;AACpB,gBAAQ,IAAI;AACZ;AAAA,MACF;AAEA,UAAI,MAAM,SAAS,KAAK,WAAW;AACjC,eAAO;AACP,iBAAS,WAAW;AACpB,gBAAQ,KAAK;AACb;AAAA,MACF;AAEA,iBAAW,MAAM,GAAG;AAAA,IACtB;AAEA,eAAW,MAAM,CAAC;AAAA,EACpB,CAAC;AACH;;;AClQO,SAAS,sBAAsB;AACpC,QAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASnB,SAAO,IAAI,gBAAgB,IAAI,KAAK,CAAC,UAAU,GAAG,EAAE,MAAM,kBAAkB,CAAC,CAAC;AAChF;AAEO,SAAS,eAAe,MAAc;AAC3C,QAAM,MAAM,oBAAoB;AAChC,QAAM,UAAU,MAAM,KAAK,EAAE,QAAQ,KAAK,GAAG,MAAM,IAAI,OAAO,GAAG,CAAC;AAClE,SAAO;AAAA,IACL;AAAA,IACA,UAAU;AACR,cAAQ,QAAQ,OAAK,EAAE,UAAU,CAAC;AAClC,UAAI,gBAAgB,GAAG;AAAA,IACzB;AAAA,EACF;AACF;AAEO,SAAS,uBAAuB,OAAO,UAAkC;AAC9E,QAAM,SAAS,uBAAO,OAAO,IAAI;AAEjC,QAAM,SAAS,KAAK;AAAA,IAClB,KAAK,mBAAmB;AAAA,IACxB,WAAW;AAAA,EACb;AAEA,MAAI,OAAO,OAAO;AAClB,SAAO,MAAM;AACX,QAAI,gBAAgB,SAAS;AAC3B,iBAAW,QAAQ,KAAK,YAAY;AAClC,cAAM,OAAO,KAAK;AAClB,YAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,iBAAO,IAAI,KAAK,OAAO,IAAI,KAAK,KAAK;AAAA,QACvC;AAAA,MACF;AAAA,IACF;AACA,WAAO,OAAO,SAAS;AAAA,EACzB;AACA,SAAO;AACT;AAEO,SAAS,kBAAkB,QAAiE;AAKjG,QAAM,OAAO,CAAC;AACd,WAAS,KAAK,MAAM;AAClB,SAAK,KAAK,IAAI;AACd,QAAI,IAAI,KAAK,SAAS;AACtB,WAAO,IAAI,GAAG;AACZ,YAAM,IAAK,IAAI,KAAM;AACrB,UAAI,KAAK,CAAC,EAAE,SAAS,KAAK,CAAC,EAAE,MAAO;AACpC,OAAC,KAAK,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,CAAC;AACtC,UAAI;AAAA,IACN;AAAA,EACF;AAAC;AACD,WAAS,MAAM;AACb,UAAM,MAAM,KAAK,CAAC;AAClB,UAAM,OAAO,KAAK,IAAI;AACtB,QAAI,KAAK,QAAQ;AACf,WAAK,CAAC,IAAI;AACV,UAAI,IAAI;AACR,aAAO,MAAM;AACX,cAAM,IAAI,IAAI,IAAI;AAClB,cAAM,IAAI,IAAI;AACd,YAAI,IAAI;AACR,YAAI,IAAI,KAAK,UAAU,KAAK,CAAC,EAAE,QAAQ,KAAK,CAAC,EAAE,MAAO,KAAI;AAC1D,YAAI,IAAI,KAAK,UAAU,KAAK,CAAC,EAAE,QAAQ,KAAK,CAAC,EAAE,MAAO,KAAI;AAC1D,YAAI,MAAM,EAAG;AACb,SAAC,KAAK,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,CAAC;AACtC,YAAI;AAAA,MACN;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAM,MAAM,OAAO,CAAC;AACpB,QAAI,OAAO,IAAI,QAAQ;AACrB,YAAM,CAAC,MAAM,KAAK,IAAI,IAAI,CAAC;AAC3B,WAAK,EAAE,OAAO,MAAM,YAAY,GAAG,cAAc,EAAE,CAAC;AAAA,IACtD;AAAA,EACF;AAEA,QAAM,MAAM,CAAC;AACb,SAAO,KAAK,QAAQ;AAClB,UAAM,EAAE,MAAM,OAAO,YAAY,aAAa,IAAI,IAAI;AACtD,QAAI,KAAK,CAAC,MAAM,KAAK,CAAC;AAEtB,UAAM,YAAY,eAAe;AACjC,UAAM,MAAM,OAAO,UAAU;AAC7B,QAAI,YAAY,IAAI,QAAQ;AAC1B,YAAM,CAAC,OAAO,MAAM,IAAI,IAAI,SAAS;AACrC,WAAK,EAAE,OAAO,QAAQ,MAAM,OAAO,YAAY,cAAc,UAAU,CAAC;AAAA,IAC1E;AAAA,EACF;AAEA,SAAO;AACT;AAEA,eAAsB,8BAA8B,QAAgC;AAClF,QAAM,UAAU,OAAO,QAAQ,MAAM;AAIrC,QAAM,KAAK,KAAK,IAAI,GAAG,UAAU,uBAAuB,CAAC;AACzD,QAAM,cAAc,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,CAAC,CAAC;AAGnD,QAAM,iBAAiB,QAAQ,UAAU,OAAQ,cAAc;AAC/D,QAAM,gBAAgB,iBAAiB,cAAc;AACrD,QAAM,OAAO,eAAe,aAAa;AAEzC,MAAI;AAEF,UAAM,SAAS,MAAM,KAAK,EAAE,QAAQ,cAAc,GAAG,MAAM,CAAC,CAAC;AAC7D,aAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,aAAO,IAAI,aAAa,EAAE,KAAK,QAAQ,CAAC,CAAC;AAAA,IAC3C;AAGA,UAAM,eAAe,MAAM,QAAQ;AAAA,MACjC,OAAO,IAAI,CAAC,cAAc,QAAQ;AAChC,eAAO,IAAI,QAAiC,CAAC,SAAS,WAAW;AAC/D,gBAAMA,UAAS,KAAK,QAAQ,GAAG;AAC/B,gBAAM,QAAQ,MAAM,MAAM,KAAK,IAAI;AAEnC,gBAAM,QAAQ,CAAC,MAAM;AACnB,gBAAI,EAAE,MAAM,UAAU,MAAO;AAC7B,YAAAA,QAAO,oBAAoB,WAAW,KAAK;AAC3C,YAAAA,QAAO,oBAAoB,SAAS,KAAK;AACzC,oBAAQ,EAAE,KAAK,MAAM;AAAA,UACvB;AACA,gBAAM,QAAQ,CAAC,QAAQ;AACrB,YAAAA,QAAO,oBAAoB,WAAW,KAAK;AAC3C,YAAAA,QAAO,oBAAoB,SAAS,KAAK;AACzC,mBAAO,GAAG;AAAA,UACZ;AAEA,UAAAA,QAAO,iBAAiB,WAAW,KAAK;AACxC,UAAAA,QAAO,iBAAiB,SAAS,KAAK;AACtC,UAAAA,QAAO,YAAY,EAAE,SAAS,cAAc,OAAO,MAAM,CAAC;AAAA,QAC5D,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAEA,UAAM,SAAU,aAAa,WAAW,IACpC,aAAa,CAAC,IACd,kBAAkB,YAAY;AAElC,WAAO,EAAE,QAAQ,QAAQ,WAAW,OAAO,QAAQ,aAAa,eAAe,qBAAqB,GAAG;AAAA,EACzG,UAAE;AACA,SAAK,QAAQ;AAAA,EACf;AACF;;;AClJA,IAAM,MAAM,OAAO,iBAAiB,cAAc,eAAe;AAE1D,SAAS,sBAAsB,eAA8B,iBAAyB,YAAkB;AAC7G,QAAM,qCAAqC,cAAc,SAAS,UAAU;AAE5E,MAAI,qCAAiD,CAAC;AAAA,IACpD;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,gBAAc,SAAS,UAAU,OAAO,IAAI,MAAM,cAAc,SAAS,UAAU,MAAM;AAAA;AAAA,IAErF,MAAM,QAAwC,SAAmB,MAAkD;AACjH,UAAI,kBAAkB,QAAQ,MAAM,oCAAoC,SAAS,IAAI;AACrF,UAAI,mCAAmC,OAAO,uCAAqC,kCAAkC,OAAO,WAAS,MAAM,KAAK,eAAe,CAAC,EAAE,UAAU,CAAC,EAAE,WAAW,GAAG;AAC3L,gBAAQ,MAAM,IAAI,cAAc,+BAA+B,OAAO;AACtE,eAAO,QAAQ,MAAM,QAAQ,MAAM;AAAA,QAAC,GAAG,CAAC,CAAC;AAAA,MAC3C;AACA,aAAO,QAAQ,MAAM,QAAQ,SAAS,IAAI;AAAA,IAC5C;AAAA,EACF,CAAC;AAEH,MAAI,8CAA0D,CAAC;AAAA,IAC7D;AAAA,IACA;AAAA,EACF,GAAG;AAAA,IACD;AAAA,IACA;AAAA,EACF,CAAC;AAED,gBAAc,aAAa,IAAI,MAAM,cAAc,YAAY;AAAA,IAC7D,MAAM,QAA2B,SAAoB,MAAqC;AACxF,UAAI,kBAAkB,QAAQ,MAAM,oCAAoC,KAAK,CAAC,GAAG,IAAI;AACrF,UAAI,4CAA4C,OAAO,gDAA8C,2CAA2C,OAAO,WAAS,MAAM,KAAK,eAAe,CAAC,EAAE,UAAU,CAAC,EAAE,WAAW,GAAG;AACtN,gBAAQ,MAAM,IAAI,cAAc,kBAAkB,KAAK,CAAC,CAAC;AACzD;AAAA,MACF;AAEA,aAAO,QAAQ,MAAM,QAAQ,SAAS,IAAI;AAAA,IAC5C;AAAA,EACF,CAAC;AAED,MAAI,SAAS,eAAe,WAAW;AACrC,WAAO,iBAAiB,oBAAoB,MAAM;AAChD,MAAI,2BAA2B;AAAA,QAC/B,MAAM,MAAM,SAAS,eAAe,MAAM;AAAA,QAC1C,aAAa;AAAA,QACb,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,WAAW;AAAA,QACX,gBAAoB;AAAA,QACpB,iBAAiB;AAAA,MACnB,CAAC;AAAA,IACH,CAAC;AAAA,EACD,OAAO;AAEL,WAAO,iBAAiB,oBAAoB,MAAM;AAChD,MAAI,2BAA2B;AAAA,QAC/B,MAAM,MAAM,SAAS,eAAe,MAAM;AAAA,QAC1C,aAAa;AAAA,QACb,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,WAAW;AAAA,QACX,gBAAoB;AAAA,QACpB,iBAAiB;AAAA,MACjB,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAEA,QAAM,UAAU,YAAY;AAC1B,QAAI,UAAe,uBAAuB,QAAQ;AAClD,UAAM,EAAE,QAAQ,WAAW,aAAa,oBAAoB,IAAI,MAAW,8BAA8B,OAAO;AAChH,QAAI,oBAAmC,CAAC;AACxC,WAAO,OAAO,CAAC,CAAC,EAAE,KAAK,MAAM,SAAS,EAAE,EAAE,QAAQ,CAAC,CAAC,MAAM,KAAK,MAAM;AACnE,wBAAkB,KAAK,GAAG,CAAC,GAAG,SAAS,iBAAiB,IAAI,IAAI,GAAG,CAAC,EAAE,OAAO,CAAC,OAAO,cAAc,WAAW,CAAC;AAAA,IACjH,CAAC;AACD,wBAAoB,kBAAkB,OAAO,QAAM,iBAAiB,EAAE,EAAE,iBAAiB,SAAS,MAAM,MAAM;AAC9G,wBAAoB,kBAAkB,OAAO,QAAM,CAAC,GAAG,GAAG,iBAAiB,GAAG,CAAC,EAAE,KAAK,WAAS,iBAAiB,eAAe,OAAO,MAAM,UAAU,UAAU,CAAC;AACjK,wBAAoB,kBAAkB,OAAO,QAAM,CAAC,GAAG,GAAG,iBAAiB,GAAG,CAAC,EAAE,OAAO,WAAS,iBAAiB,eAAe,MAAM,sBAAsB,EAAE,SAAS,MAAM,sBAAsB,EAAE,MAAM,OAAO,MAAM,sBAAsB,EAAE,QAAQ,MAAM,sBAAsB,EAAE,OAAO,GAAG,EAAE,UAAU,EAAE;AAC/S,wBAAoB,kBAAkB,OAAO,QAAM;AACjD,UAAI,QAAQ,CAAC,GAAG,GAAG,iBAAiB,GAAG,CAAC,EAAE,OAAO,WAAU,MAAM,sBAAsB,EAAE,SAAS,MAAM,sBAAsB,EAAE,MAAM,MAAM,MAAM,sBAAsB,EAAE,QAAQ,MAAM,sBAAsB,EAAE,OAAO,OAAO,iBAAiB,kBAAkB,MAAM,aAAa,GAAG,MAAM,SAAU,iBAAiB,oBAAoB,MAAM,IAAI,SAAS,kBAAkB,CAAG,EAAE;AACtX,aAAO,KAAK,SAAS,SAAS;AAAA,IAChC,CAAC;AACD,wBAAoB,kBAAkB,OAAO,QAAM,CAAC,GAAG,GAAG,iBAAiB,GAAG,CAAC,EAAE,KAAK,WAAS,iBAAiB,eAAe,iBAAiB,OAAO,SAAS,EAAE,iBAAiB,SAAS,EAAE,SAAS,GAAG,KAAK,MAAM,sBAAsB,EAAE,QAAQ,MAAM,sBAAsB,EAAE,OAAO,EAAE,MAAM,KAAK;AACvS,wBAAoB,kBAAkB,OAAO,QAAM,CAAC,GAAG,GAAG,iBAAiB,GAAG,CAAC,EAAE,MAAM,WAAS,iBAAiB,eAAe,CAAC,IAAI,KAAK,MAAM,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC;AACrK,YAAQ,MAAM,IAAI,cAAc,KAAK,iBAAiB;AACtD,sBAAkB,QAAQ,QAAM;AAC9B,kBAAY,MAAM;AAChB,WAAG,aAAa,SAAS,0DAA0D;AAAA,MACrF,GAAG,GAAG;AAAA,IACR,CAAC;AAAA,EACH;AAEA,SAAO,iBAAiB,eAAe,MAAM,WAAW,SAAS,IAAI,CAAC;AACtE,SAAO,iBAAiB,eAAe,OAAO;AAChD;AAEA,sBAAsB,GAAG;",
6
- "names": ["Worker"]
7
- }
@@ -1,10 +0,0 @@
1
- export {};
2
- /*!
3
- * @license MPL-2.0
4
- * This Source Code Form is subject to the terms of the Mozilla Public
5
- * License, v. 2.0. If a copy of the MPL was not distributed with this
6
- * file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
- *
8
- * Contributors:
9
- * - See Git history at https://github.com/FilteringDev/tinyShield for detailed authorship information.
10
- */
@@ -1,10 +0,0 @@
1
- /*!
2
- * @license MPL-2.0
3
- * This Source Code Form is subject to the terms of the Mozilla Public
4
- * License, v. 2.0. If a copy of the MPL was not distributed with this
5
- * file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
- *
7
- * Contributors:
8
- * - See Git history at https://github.com/FilteringDev/tinyShield for detailed authorship information.
9
- */
10
- export { RunNamuLinkUserscript } from './src/index.js';
File without changes