generated at
Porterっぽい編集バーを生やすUserScript.min
script.js
var I=(...e)=>{let t=e.flatMap(o=>{if(typeof o=="string")return[T(o)];if(Array.isArray(o.type))return[F(o.type)];switch(o.type){case"text":return[T(o.text)];case"group":{let s=I(...o.items);return s?[s]:[]}default:return[F(o.type)]}});if(t.length===0)return;if(t.length===1)return t[0];let r=document.createElement("span");return r.classList.add("item-group"),r.append(...t),r},T=e=>{let t=document.createElement("span");return t.classList.add("item"),t.append(e),t},F=e=>{if(Array.isArray(e)){let t=document.createElement("span");t.classList.add("fa-stack");let r=M(e[0]);r.classList.add("fa-stack-1x");let o=M(e[1]);return o.classList.add("fa-stack-1x"),t.append(r,o),T(t)}return T(M(e))},M=e=>{let t=document.createElement("i");switch(e){case"spinner":t.classList.add("fa","fa-spinner");break;case"check-circle":case"gyazo":case"ocr":case"trim":t.classList.add("kamon",`kamon-${e}`);break;case"markdown":case"google":t.classList.add("fab",`fa-${e}`);break;case"copy":case"clipboard":t.classList.add("far",`fa-${e}`);break;default:t.classList.add("fas",`fa-${e}`);break}return t};var E=e=>e==null,L=e=>typeof e=="string",k=e=>typeof e=="number";var de=e=>typeof e=="object"&&e!==null,le=e=>de(e)?(e.name===void 0||typeof e.name=="string")&&typeof e.message=="string":!1,m=e=>{try{let t=typeof e=="string"?JSON.parse(e):e;return le(t)?t:!1}catch(t){if(t instanceof SyntaxError)return!1;throw t}};var A=(e,t)=>{if(!Array.isArray(e))throw new TypeError(`"${t}" must be an array but actual is "${e}"`)};var j=(e,t)=>{if(!(e instanceof HTMLDivElement))throw new TypeError(`"${t}" must be HTMLDivElememt but actual is "${e}"`)};var K=(e,t)=>{if(!(e instanceof HTMLTextAreaElement))throw new TypeError(`"${t}" must be HTMLTextAreaElement but actual is "${e}"`)};var x=()=>{let e=document.getElementById("text-input");if(!!e)return K(e,"textarea#text-input"),e};var _=()=>me(document.getElementsByClassName("status-bar")?.[0],"div.status-bar"),me=(e,t)=>{if(!!e)return j(e,t),e};var fe=e=>{if(E(e))return;if(k(e))return v(e)?.id;if(L(e))return e.startsWith("L")?e.slice(1):e;if(e.classList.contains("line"))return e.id.slice(1);let t=e.closest(".line");if(t)return t.id.slice(1)};var v=e=>{if(E(e))return;if(k(e))return C()[e];let t=fe(e);return t?C().find(r=>r.id===t):void 0};var ge=e=>e instanceof HTMLDivElement&&e.classList.contains("line");var C=()=>(A(scrapbox.Page.lines,"scrapbox.Page.lines"),scrapbox.Page.lines),R=e=>{if(E(e))return;if(k(e)||L(e))return v(e)?.text;if(!(e instanceof HTMLElement))return;if(ge(e))return v(e)?.text;if(e.classList.contains("char-index"))return e.textContent??void 0;if(e.classList.contains("line")||e.getElementsByClassName("lines")?.[0])return C().map(({text:o})=>o).join(` `);let t=[],r=v(e);if(!E(r)){for(let o of he(e))t.push(we(o));return r.text.slice(Math.min(...t),Math.max(...t)+1)}};function*he(e){let t=e.getElementsByClassName("char-index");for(let r=0;r<t.length;r++)yield t[0]}var xe=e=>e instanceof HTMLSpanElement&&e.classList.contains("char-index"),we=e=>{if(!xe(e))throw Error("A char DOM is required.");let t=e.className.match(/c-(\d+)/)?.[1];if(E(t))throw Error('.char-index must have ".c-{\\d}"');return parseInt(t)};var u=(e,t)=>{let{noModifiedKeys:r=!1,...o}=t??{},s={bubbles:!0,cancelable:!0,keyCode:Ee[e],...r?{}:{...o}},n=x();if(!n)throw Error("#text-input must exist.");n.dispatchEvent(new KeyboardEvent("keydown",s)),n.dispatchEvent(new KeyboardEvent("keyup",s))},Ee={Backspace:8,Tab:9,Enter:13,Delete:46,Escape:27," ":32,PageUp:33,PageDown:34,End:35,Home:36,ArrowLeft:37,ArrowUp:38,ArrowRight:39,ArrowDown:40,a:65,A:65,b:66,B:66,c:67,C:67,d:68,D:68,e:69,E:69,f:70,F:70,g:71,G:71,h:72,H:72,i:73,I:73,j:74,J:74,k:75,K:75,l:76,L:76,m:77,M:77,n:78,N:78,o:79,O:79,p:80,P:80,q:81,Q:81,r:82,R:82,s:83,S:83,t:84,T:84,u:85,U:85,v:86,V:86,w:87,W:87,x:88,X:88,y:89,Y:89,z:90,Z:90,0:48,1:49,2:50,3:51,4:52,5:53,6:54,7:55,8:56,9:57,F1:113,F2:114,F3:115,F4:116,F5:117,F6:118,F7:119,F8:120,F9:121,F10:122,F11:123,F12:124,":":186,"*":186,";":187,"+":187,"-":189,"=":189,".":190,">":190,"/":191,"?":191,"@":192,"`":192,"[":219,"{":219,"\\":220,"|":220,"]":221,"}":221,"^":222,"~":222,_:226};var S=e=>new Promise(t=>setTimeout(()=>t(),e));function*f(e,t){for(let r=e;r<t;r++)yield r}var G=(e=1)=>{for(let t of f(0,e))u("z",{ctrlKey:!0})},X=(e=1)=>{for(let t of f(0,e))u("z",{shiftKey:!0,ctrlKey:!0})};var q=(e=1)=>{for(let t of f(0,e))u("ArrowRight",{ctrlKey:!0})},Y=(e=1)=>{for(let t of f(0,e))u("ArrowLeft",{ctrlKey:!0})};var z=(e=1)=>{for(let t of f(0,e))u("ArrowUp",{ctrlKey:!0})},W=(e=1)=>{for(let t of f(0,e))u("ArrowDown",{ctrlKey:!0})},J=(e=1)=>{for(let t of f(0,e))u("ArrowRight",{altKey:!0})},V=(e=1)=>{for(let t of f(0,e))u("ArrowLeft",{altKey:!0})};var Q=(e=1)=>{for(let t of f(0,e))u("ArrowUp",{altKey:!0})},Z=(e=1)=>{for(let t of f(0,e))u("ArrowDown",{altKey:!0})},P=async e=>{let t=x();if(!t)throw Error("#text-input is not ditected.");t.focus(),t.value=e;let r=new InputEvent("input",{bubbles:!0});t.dispatchEvent(r),await S(1)};var ee=()=>{let e=_();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=te(...r);o&&t.append(o)},dispose:()=>t.remove()}},te=(...e)=>{let t=e.flatMap(o=>{switch(o.type){case"spinner":return[be()];case"check-circle":return[Le()];case"exclamation-triangle":return[ke()];case"text":return[N(o.text)];case"group":{let s=te(...o.items);return s?[s]:[]}}});if(t.length===0)return;if(t.length===1)return t[0];let r=document.createElement("span");return r.classList.add("item-group"),r.append(...t),r},N=e=>{let t=document.createElement("span");return t.classList.add("item"),t.append(e),t},be=()=>{let e=document.createElement("i");return e.classList.add("fa","fa-spinner"),N(e)},Le=()=>{let e=document.createElement("i");return e.classList.add("kamon","kamon-check-circle"),N(e)},ke=()=>{let e=document.createElement("i");return e.classList.add("fas","fa-exclamation-triangle"),N(e)};var y=()=>{let e=x();if(!e)throw Error("#text-input is not found.");let t=Object.keys(e).find(n=>n.startsWith("__reactFiber"));if(!t)throw Error('#text-input must has the property whose name starts with "__reactFiber"');let r=e[t].return.return.stateNode._stores,o=r.find(n=>n.constructor.name==="Cursor");if(!o)throw Error('#text-input must has a "Cursor" store.');let s=r.find(n=>n.constructor.name==="Selection");if(!s)throw Error('#text-input must has a "Selection" store.');return{cursor:o,selection:s}};var{cursor:B,selection:H}=y(),re=e=>{let{className:t,display:r,onClick:o,context:s="page"}=e,n=document.createElement("div");t&&n.classList.add(t),oe(s)||(n.style.display="none");let p=(...i)=>{if(i.length===1&&i[0]===""){n.style.display="none";return}n.textContent="";let h=I(...i);h&&n.append(h)},a=typeof r=="function"?r({cursor:B,selection:H}):r;return p(...Array.isArray(a)?a:[a]),n.addEventListener("touchstart",i=>{i.preventDefault(),i.stopPropagation(),o({cursor:B,selection:H,setDisplay:p})}),{status:n,context:s,update:()=>{if(oe(s)?n.removeAttribute("style"):n.style.display="none",typeof r=="function"){let i=r({cursor:B,selection:H});p(...Array.isArray(i)?i:[i])}}}},oe=e=>e!=="stream"?scrapbox.Layout===e:scrapbox.Layout==="list"&&location.pathname.startsWith("/stream");var ne=()=>{let e=document.createElement("style");e.textContent=`.status-bar.left { position: absolute; top: 0; left: 0; right: unset; // max-width: 80vw; // なぜか左端が切れてしまうので無効化 overflow-x: auto; overflow-y: hidden; } .status-bar.left:empty { display: none; } .status-bar.left > div { border-left: unset; } .status-bar.left > div { border-right: 1px solid var(--tool-light-color, #a9aaaf); } .status-bar.left > div:first-of-type { border-top-left-radius: unset; } .status-bar.left > div:last-of-type { border-top-right-radius: 3px; }`,document.head.append(e);let t=document.createElement("div");return t.classList.add("status-bar","left"),document.getElementsByClassName("footer")[0].append(t),t};var O=new Set,{cursor:ve,selection:Ne}=y(),Ie=ne();var g=e=>{let t=re(e);return O.add(t),Ie.append(t.status),()=>{t.status.remove(),O.delete(t)}},D=()=>{for(let{update:e}of O)e()};ve.addChangeListener(()=>D());Ne.addChangeListener(()=>D());scrapbox.addListener("layout:changed",D);var se=async(e,t)=>{try{let r=t.hasSelection(),o=r?t.getRange().start.line:e.getPosition().line,s=r?t.getSelectedText():R(o);if(!s)return;await navigator.clipboard.writeText(s),r||t.setRange({start:{line:o,char:0},end:{line:o,char:s.length}}),e.focus(),u("Delete")}catch(r){console.error(r),alert(`Faild to cut: ${JSON.stringify(r)}`)}};var d=e=>{let{fetch:t=globalThis.fetch,hostName:r="scrapbox.io",...o}=e;return{fetch:t,hostName:r,...o}};var c=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,c)}};var ie=async e=>{let{sid:t,hostName:r,fetch:o}=d(e??{}),s=`https://${r}/api/users/me`,n=await o(s,t?{headers:{Cookie:l(t)}}:void 0);if(!n.ok)throw new c({path:new URL(s),...n,body:await n.text()});return await n.json()};var l=e=>`connect.sid=${e}`,b=async e=>window._csrf?window._csrf:(await ie(e)).csrfToken;var ae=async(e,t)=>{let{sid:r,hostName:o,fetch:s,csrf:n}=d(t??{}),p=`https://${o}/api/embed-text/url?url=${encodeURIComponent(e.toString())}`,a=await s(p,{method:"POST",headers:{"Content-Type":"application/json;charset=utf-8","X-CSRF-TOKEN":n??await b(t),...r?{Cookie:l(r)}:{}},body:JSON.stringify({timeout:3e3})});if(!a.ok){if(a.status===422)return{ok:!1,value:{name:"InvalidURLError",message:(await a.json()).message}};let i=await a.text(),h=m(i);if(!h)throw new c({path:new URL(p),...a,body:i});return{ok:!1,value:h}}let{title:w}=await a.json();return{ok:!0,value:w}};var ce=async(e,t)=>{let{sid:r,hostName:o,fetch:s,csrf:n}=d(t??{}),p=`https://${o}/api/embed-text/twitter?url=${encodeURIComponent(e.toString())}`,a=await s(p,{method:"POST",headers:{"Content-Type":"application/json;charset=utf-8","X-CSRF-TOKEN":n??await b(t),...r?{Cookie:l(r)}:{}},body:JSON.stringify({timeout:3e3})});if(!a.ok){if(a.status===422)return{ok:!1,value:{name:"InvalidURLError",message:(await a.json()).message}};let i=await a.text(),h=m(i);if(!h)throw new c({path:new URL(p),...a,body:i});return{ok:!1,value:h}}let w=await a.json();return{ok:!0,value:w}};var pe=/(https?:\/\/\S+)/,U=e=>pe.test(e),ue=async e=>{if(!U(e))return e;let{render:t,dispose:r}=ee();t({type:"spinner"},{type:"text",text:"convert URLs..."});let o=0;try{let s=await Promise.all(e.split(pe).map(async n=>{if(!/^https?:\/\/\S+/.test(n))return n;let p;try{p=new URL(n)}catch(i){if(i instanceof TypeError)return n;throw i}if(Me(p)){let i=await ce(p);return i.ok?(o++,Ce(p,i.value)):n}let a=await ae(p);if(!a.ok)return n;o++;let w=a.value.replace(/\s/g," ").replaceAll("[","[").replaceAll("]","]");return`[${p} ${w}]`}));return t({type:"check-circle"},{type:"text",text:`Converted ${o} URLs.`}),s.join("")}catch(s){throw t({type:"exclamation-triangle"},{type:"text",text:s instanceof Error?`${s.name} ${s.message}`:"Unknown error! (see developper console)"}),console.error(s),s}finally{setTimeout(()=>r(),1e3)}},Me=e=>/^https:\/\/(?:www\.|mobile\.|m\.|)twitter\.com\/([A-Za-z0-9_]*)\/(?:status|statuses)\/\d+/.test(e.toString()),$=e=>e.replace(/\b/gm,"").replace(/[\s\r\n\u2028\u2029]+/gm," ").replace(/\s*[[\]`]\s*/g," ").trim(),Ce=(e,t)=>[`[${$(t.screenName)}(@${$(t.userName)}) ${e.origin}${e.pathname}]`,...t.description.split(` `).map(r=>`> ${$(r)}`),...t.images.length>0?[`> ${t.images.map(r=>`[${r}]`)}`]:[]].join(` `);g({display:{type:"caret-left"},onClick:({cursor:e,selection:t})=>{e.focus(),t.getSelectedText()===""?V():Y()}});g({display:{type:"caret-right"},onClick:({cursor:e,selection:t})=>{e.focus(),t.getSelectedText()===""?J():q()}});g({display:{type:"caret-up"},onClick:({cursor:e,selection:t})=>{e.focus(),t.getSelectedText()===""?Q():z()}});g({display:{type:"caret-down"},onClick:({cursor:e,selection:t})=>{e.focus(),t.getSelectedText()===""?Z():W()}});g({display:{type:"cut"},onClick:async({cursor:e,selection:t})=>await se(e,t)});g({display:({selection:e})=>U(e.getSelectedText())?"URL":"",onClick:async({selection:e})=>{let t=e.getSelectedText(),r=await ue(t);t!==r&&await P(r)}});g({display:{type:"undo"},onClick:()=>G()});g({display:{type:"redo"},onClick:()=>X()});