url2link-script
code:mod.ts
import {
convert as convertURL,
hasURL,
} from "/api/code/takker/URLを外部リンク記法に変換するUserScript_(TamperMonkeyなし)/mod.ts";
addButton({
display: ({ selection }) => hasURL(selection.getSelectedText()) ? "URL" : "",
onClick: async ({ selection }) => {
const text = selection.getSelectedText();
const converted = await convertURL(text);
if (text === converted) return;
await insertText(converted);
},
});
code:script.js
var P=e=>typeof e=="object"&&e!==null,S=e=>P(e)?(e.name===void 0||typeof e.name=="string")&&typeof e.message=="string":!1,d=e=>{try{let t=typeof e=="string"?JSON.parse(e):e;return S(t)?t:!1}catch(t){if(t instanceof SyntaxError)return!1;throw t}};var y=(e,t)=>{if(!(e instanceof HTMLDivElement))throw new TypeError("${t}" must be HTMLDivElememt but actual is "${e}")};var L=()=>C(document.getElementsByClassName("status-bar")?.0,"div.status-bar"),C=(e,t)=>{if(!!e)return y(e,t),e};var k=()=>{let e=L();if(!e)throw new Error("div.status-bar can't be found");let t=document.createElement("div");return e.append(t),{render:(...r)=>{t.textContent="";let o=T(...r);o&&t.append(o)},dispose:()=>t.remove()}},T=(...e)=>{let t=e.flatMap(o=>{switch(o.type){case"spinner":return$();case"check-circle":returnF();case"exclamation-triangle":returnA();case"text":returnh(o.text);case"group":{let n=T(...o.items);return n?n:[]}}});if(t.length===0)return;if(t.length===1)return t0;let r=document.createElement("span");return r.classList.add("item-group"),r.append(...t),r},h=e=>{let t=document.createElement("span");return t.classList.add("item"),t.append(e),t},$=()=>{let e=document.createElement("i");return e.classList.add("fa","fa-spinner"),h(e)},F=()=>{let e=document.createElement("i");return e.classList.add("kamon","kamon-check-circle"),h(e)},A=()=>{let e=document.createElement("i");return e.classList.add("fas","fa-exclamation-triangle"),h(e)};var c=e=>{let{fetch:t=globalThis.fetch,hostName:r="scrapbox.io",...o}=e;return{fetch:t,hostName:r,...o}};var s=class extends Error{constructor(t){super(${t.status} ${t.statusText} when fetching ${t.path.toString()});this.name="UnexpectedResponseError";this.status=t.status,this.statusText=t.statusText,this.body=t.body,this.path=t.path,Error.captureStackTrace&&Error.captureStackTrace(this,s)}};var v=async e=>{let{sid:t,hostName:r,fetch:o}=c(e??{}),n=https://${r}/api/users/me,a=await o(n,t?{headers:{Cookie:u(t)}}:void 0);if(!a.ok)throw new s({path:new URL(n),...a,body:await a.text()});return await a.json()};var u=e=>connect.sid=${e},m=async e=>window._csrf?window._csrf:(await v(e)).csrfToken;var N=async(e,t)=>{let{sid:r,hostName:o,fetch:n,csrf:a}=c(t??{}),p=https://${o}/api/embed-text/url?url=${encodeURIComponent(e.toString())},i=await n(p,{method:"POST",headers:{"Content-Type":"application/json;charset=utf-8","X-CSRF-TOKEN":a??await m(t),...r?{Cookie:u(r)}:{}},body:JSON.stringify({timeout:3e3})});if(!i.ok){if(i.status===422)return{ok:!1,value:{name:"InvalidURLError",message:(await i.json()).message}};let l=await i.text(),g=d(l);if(!g)throw new s({path:new URL(p),...i,body:l});return{ok:!1,value:g}}let{title:f}=await i.json();return{ok:!0,value:f}};var M=async(e,t)=>{let{sid:r,hostName:o,fetch:n,csrf:a}=c(t??{}),p=https://${o}/api/embed-text/twitter?url=${encodeURIComponent(e.toString())},i=await n(p,{method:"POST",headers:{"Content-Type":"application/json;charset=utf-8","X-CSRF-TOKEN":a??await m(t),...r?{Cookie:u(r)}:{}},body:JSON.stringify({timeout:3e3})});if(!i.ok){if(i.status===422)return{ok:!1,value:{name:"InvalidURLError",message:(await i.json()).message}};let l=await i.text(),g=d(l);if(!g)throw new s({path:new URL(p),...i,body:l});return{ok:!1,value:g}}let f=await i.json();return{ok:!0,value:f}};var R=/(https?:\/\/\S+)/,E=e=>R.test(e),I=async e=>{if(!E(e))return e;let{render:t,dispose:r}=k();t({type:"spinner"},{type:"text",text:"convert URLs..."});let o=0;try{let n=await Promise.all(e.split(R).map(async a=>{if(!/^https?:\/\/\S+/.test(a))return a;let p;try{p=new URL(a)}catch(l){if(l instanceof TypeError)return a;throw l}if(_(p)){let l=await M(p);return l.ok?(o++,G(p,l.value)):a}let i=await N(p);if(!i.ok)return a;o++;let f=i.value.replace(/\s/g," ").replaceAll("","[").replaceAll("","]");return[${p} ${f}]}));return t({type:"check-circle"},{type:"text",text:Converted ${o} URLs.}),n.join("")}catch(n){throw t({type:"exclamation-triangle"},{type:"text",text:n instanceof Error?${n.name} ${n.message}:"Unknown error! (see developper console)"}),console.error(n),n}finally{setTimeout(()=>r(),1e3)}},_=e=>/^https:\/\/(?:www\.|mobile\.|m\.|)twitter\.com\/(A-Za-z0-9_*)\/(?:status|statuses)\/\d+/.test(e.toString()),w=e=>e.replace(/\b/gm,"").replace(/\s\r\n\u2028\u2029+/gm," ").replace(/\s*[\]\s*/g," ").trim(),G=(e,t)=>[${w(t.screenName)}(@${w(t.userName)}) ${e.origin}${e.pathname},...t.description.split( ).map(r=>> ${w(r)}),...t.images.length>0?[> ${t.images.map(r=>[${r}])}]:[]].join(
`);addButton({display:({selection:e})=>E(e.getSelectedText())?"URL":"",onClick:async({selection:e})=>{let t=e.getSelectedText(),r=await I(t);t!==r&&await insertText(r)}});