Projectを横断してリンクを置換するUserScript
https://gyazo.com/4543a17e3436d7dcebc50e99eb39bf16
↑Gyazo GIFがなぜかガクガクしてしまったので、別途GIFを作った
https://gyazo.com/ab4f4583e92efa03b516a64f2c17a08f.mp4
使い方
code:script.js
import { replace, getLink } from "./mod.js";
scrapbox.PopupMenu.addButton({
title: (text) => getLink(text) ? "update link" : "",
onClick: (text) => replace(
text,
),
});
以下の修正が必要
実装したいこと
現状だと、置換後のリンクと同名のタイトルがあるとエラーになる
置換対象のprojectを選択できるようにする?
UIが複雑になりそう
現在のprojectも対象にしたい
各自でreplace()の引数に入れてください
2024-07-05
微妙に正規表現が違うせいで、popup menu上は検知されているのに押しても置換windowが表示されないことがしょっちゅうあってまあまあストレスだった
重い腰を上げて、ようやくなおした
dependencies
code:mod.ts
import {
disconnect,
makeSocket,
patch,
replaceLinks,
useStatusBar,
} from "../scrapbox-userscript-std/mod.ts";
import type {
ErrorLike,
import { getLinks } from "../複数のリンクをまとめて置換するUserScript/mod.ts";
export async function replace(text: string, projects: string[]) {
const link = getLinks(text)0; if (!link) return;
const newLink = window.prompt(
`Replace "${link}" to this in ${
projects.map((project) => "/${project}").join(", ")
}`,
link,
)
?.replace?.(/[\\\n]/g, " ") ?? ""; if (newLink === "") return;
const { render, dispose } = useStatusBar();
const socket = await makeSocket();
try {
render(
{ type: "spinner" },
{
type: "text",
text: Replacing links in ${projects.length} projects...,
},
);
let count = 0;
const replacedNums = await Promise.all(projects.map(async (project) => {
const result = await Promise.all([ // 本当はhasBackLinksOrIcons === trueのときのみ置換したい
replaceLinks(project, link, newLink),
patch(project, link, (lines, { persistent }) => {
if (!persistent) return;
return [
newLink,
...lines.map((line) => line.text).slice(1),
];
}, { socket }),
]);
if (!result.ok) {
render(
{ type: "exclamation-triangle" },
{
type: "text",
text: ${result.value.name} ${result.value.message},
},
);
throw toError(result.value);
}
count++;
render(
{ type: "spinner" },
{
type: "text",
text: Replacing links in ${projects.length - count} projects...,
},
);
return result.value;
}));
const replaced = replacedNums.reduce((acc, cur) => acc + cur, 0);
render(
{ type: "check-circle" },
{ type: "text", text: Successfully replaced ${replaced} links. },
);
} finally {
await disconnect(socket);
setTimeout(dispose, 1000);
}
}
function toError(e: ErrorLike) {
const error = new Error();
error.name = e.name;
error.message = e.message;
return error;
}
code:mod.js
async function S(e){let t="https://scrapbox.io/api/users/me",n=await fetch(t,e?.sid?{headers:{Cookie:E(e.sid)}}:void 0);if(!n.ok)throw b("UnexpectedError",Unexpected error has occuerd when fetching "${t}");return await n.json()}var E=e=>connect.sid=${e};async function A(e){return window.__csrf?window.__csrf:(await S(e?{sid:e}:void 0)).csrfToken}function me(e){return e!=null}function fe(e){return me(e)?(e.name===void 0||typeof e.name=="string")&&typeof e.message=="string":!1}function T(e){try{let t=typeof e=="string"?JSON.parse(e):e;return fe(t)?t:!1}catch(t){if(t instanceof SyntaxError)return!1;throw t}}function b(e,t){let n=new Error;return n.name=e,n.message=t,n}var P=e=>e.replaceAll(" ","_").toLowerCase();var B=e=>...e.map((t,n)=>t===" "?"_":!ge.includes(t)||n===e.length-1&&he.includes(t)?encodeURIComponent(t):t).join(""),ge='@$&+=:;",',he=':;",';async function F(e,t,n){let r=https://scrapbox.io/api/pages/${e}/${B(t)}?followRename=${n?.followRename??!0},o=await fetch(r,n?.sid?{headers:{Cookie:E(n.sid)}}:void 0);if(!o.ok){let a=T(await o.text());if(!a)throw b("UnexpectedError",Unexpected error has occuerd when fetching "${r}");return{ok:!1,value:a}}let s=await o.json();return{ok:!0,value:s}}async function _(e,t){let n=https://scrapbox.io/api/projects/${e},r=await fetch(n,t?.sid?{headers:{Cookie:E(t.sid)}}:void 0);if(!r.ok){let s=T(await r.json());if(!s)throw b("UnexpectedError",Unexpected error has occuerd when fetching "${n}");return{ok:!1,value:s}}let o=await r.json();return{ok:!0,value:o}}async function K(e,t,n,r){let o=https://scrapbox.io/api/pages/${e}/replace/links,s=r?.sid,a=r?.csrf??await A(s),i=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json;charset=utf-8","X-CSRF-TOKEN":a,...s?{Cookie:E(s)}:{}},body:JSON.stringify({from:t,to:n})});if(!i.ok){let u=T(await i.text());if(!u)throw b("UnexpectedError",Unexpected error has occuerd when fetching "${o}");return{ok:!1,value:u}}let{message:c}=await i.json();return{ok:!0,value:parseInt(c.match(/\d+/)?.0??"0")}}var W=(e,t)=>{if(!(e instanceof HTMLDivElement))throw new TypeError("${t}" must be HTMLDivElememt but actual is "${e}")};var z=()=>xe(document.getElementsByClassName("status-bar")?.0,"div.status-bar"),xe=(e,t)=>{if(!!e)return W(e,t),e};function X(){let e=z();if(!e)throw new Error("div.status-bar can't be found");let t=document.createElement("div");return e.append(t),{render:(...n)=>{t.textContent="";let r=Y(...n);r&&t.append(r)},dispose:()=>t.remove()}}function Y(...e){let t=e.flatMap(r=>{switch(r.type){case"spinner":returnve();case"check-circle":returnTe();case"exclamation-triangle":returnLe();case"text":returnH(r.text);case"group":{let o=Y(...r.items);return o?o:[]}}});if(t.length===0)return;if(t.length===1)return t0;let n=document.createElement("span");return n.classList.add("item-group"),n.append(...t),n}function H(e){let t=document.createElement("span");return t.classList.add("item"),t.append(e),t}function ve(){let e=document.createElement("i");return e.classList.add("fa","fa-spinner"),H(e)}function Te(){let e=document.createElement("i");return e.classList.add("kamon","kamon-check-circle"),H(e)}function Le(){let e=document.createElement("i");return e.classList.add("fas","fa-exclamation-triangle"),H(e)}var Ie="4.2.0";async function v(){let t=(await Me())("https://scrapbox.io",{reconnectionDelay:5e3,transports:["websocket"]});return await new Promise((n,r)=>{let o=s=>r(s);t.once("connect",()=>{t.off("disconnect",o),n()}),t.once("disconnect",o)}),t}function Me(){let e=https://cdnjs.cloudflare.com/ajax/libs/socket.io/${Ie}/socket.io.min.js;if(document.querySelector(script[src="${e}"]))return Promise.resolve(window.io);let t=document.createElement("script");return t.src=e,new Promise((n,r)=>{t.onload=()=>n(window.io),t.onerror=o=>r(o),document.head.append(t)})}function C(e,t=9e4){function n(o,s){let a;return new Promise((i,c)=>{let u=p=>{clearTimeout(a),c(new Error(p))};e.emit(o,s,p=>{clearTimeout(a),e.off("disconnect",u),p.error&&c(new Error(JSON.stringify(p.error))),"data"in p?i(p?.data):i(void 0)}),a=setTimeout(()=>{e.off("disconnect",u),c(new Error(Timeout: exceeded ${t}ms))},t),e.once("disconnect",u)})}async function*r(...o){let s,a=()=>new Promise(c=>s=c),i=c=>{s?.(c)};for(let c of o)e.on(c,i);try{for(;;)yield await a()}finally{for(let c of o)e.off(c,i)}}return{request:n,response:r}}function G(){return v()}async function N(e){if(e.connected)return;let t=new Promise(n=>e.once("connect",()=>n()));e.connect(),await t}async function L(e){if(e.disconnected)return;let t=new Promise(n=>{let r=o=>{o==="io client disconnect"&&(n(),e.off("disconnect",r))};e.on("disconnect",r)});e.disconnect(),await t}var R;async function j(){if(R!==void 0)return R;let e=await S();if(e.isGuest)throw new Error("this script can only be executed by Logged in users");return R=e.id,R}var V=new Map;async function D(e){let t=V.get(e);if(t!==void 0)return t;let n=await _(e);if(!n.ok){let{name:o,message:s}=n.value;throw new Error(${o} ${s})}let{id:r}=n.value;return V.set(e,r),r}function J(e){return e.padStart(8,"0")}function Z(e){let t=Math.floor(new Date().getTime()/1e3).toString(16),n=Math.floor(16777214*Math.random()).toString(16);return${J(t).slice(-8)}${e.slice(-6)}0000${J(n)}}function ee(e,t){let n=e.length>t.length,r=n?t:e,o=n?e:t,s=r.length+1,a=r.length+o.length+3,i=new Array(a);i.fill(-1);let c=[];function u(d,w,k){let y=Math.max(w,k),O=y-d;for(;O<r.length&&y<o.length&&rO===oy;)++O,++y;return id+s=c.length,c.push([{x:O,y},id+(w>k?-1:1)+s]),y}let p=new Array(a);p.fill(-1);let m=-1,l=o.length-r.length;do{++m;for(let d=-m;d<=l-1;++d)pd+s=u(d,pd-1+s+1,pd+1+s);for(let d=l+m;d>=l+1;--d)pd+s=u(d,pd-1+s+1,pd+1+s);pl+s=u(l,pl-1+s+1,pl+1+s)}while(pl+s!==o.length);let x=[],h=il+s;for(;h!==-1;)x.push(ch0),h=ch1;return{from:e,to:t,editDistance:l+m*2,buildSES:function*(){let d=0,w=0;for(let{x:k,y}of Ce(x))for(;d<k||w<y;)y-k>w-d?(yield{value:ow,type:n?"deleted":"added"},++w):y-k<w-d?(yield{value:rd,type:n?"added":"deleted"},++d):(yield{value:rd,type:"common"},++d,++w)}}}function*te(e){let t=[],n=[];function*r(){if(t.length>n.length){for(let o=0;o<n.length;o++)yield ne(to,no);for(let o=n.length;o<t.length;o++)yield to}else{for(let o=0;o<t.length;o++)yield ne(to,no);for(let o=t.length;o<n.length;o++)yield no}t=[],n=[]}for(let o of e)switch(o.type){case"added":t.push(o);break;case"deleted":n.push(o);break;case"common":yield*r(),yield o;break}yield*r()}function ne(e,t){return{value:e.value,oldValue:t.value,type:"replaced"}}function*Ce(e){for(let t=e.length-1;t>=0;t--)yield et}function*re(e,t,{userId:n}){let{buildSES:r}=ee(e.map(({text:a})=>a),t),o=0,s=e0.id;for(let a of te(r())){switch(a.type){case"added":yield{_insert:s,lines:{id:Z(n),text:a.value}};continue;case"deleted":yield{_delete:s,lines:-1};break;case"replaced":yield{_update:s,lines:{text:a.value}};break}o++,s=eo?.id??"_end"}}var Pe=e=>({type:"title",text:e.rows0.text}),Ne=e=>{let{rows:t,...n}=e,{indent:r=0,text:o=""}=t??{},s=o.replace(/^\s*code:/,"");return{indent:r,type:"codeBlock",fileName:s,content:n.map(a=>a.text.substring(r+1)).join(` )}},f=(e,{parseOnNested:t,parseOnQuoted:n,patterns:r})=>(o,s,a)=>{var i,c,u,p,m,l;if(!t&&s.nested)return(i=a==null?void 0:a())!==null&&i!==void 0?i:[];if(!n&&s.quoted)return(c=a==null?void 0:a())!==null&&c!==void 0?c:[];for(let x of r){let h=x.exec(o);if(h===null)continue;let d=o.substring(0,h.index),w=o.substring(h.index+((p=(u=h[0])===null||u===void 0?void 0:u.length)!==null&&p!==void 0?p:0)),k=e((m=h[0])!==null&&m!==void 0?m:"",s);return[...I(d,s),...k,...I(w,s)]}return(l=a==null?void 0:a())!==null&&l!==void 0?l:[]},g=e=>[{type:"plain",raw:e,text:e}],De=f(g,{parseOnNested:!0,parseOnQuoted:!0,patterns:[/^()(.*)()$/]}),Oe=/^>.*$/,Se=(e,t)=>t.context==="table"?g(e,t):[{type:"quote",raw:e,nodes:I(e.substring(1),{...t,quoted:!0})}],He=f(Se,{parseOnNested:!1,parseOnQuoted:!1,patterns:[Oe]}),Re=/^\? .+$/,je=(e,t)=>t.context==="table"?g(e,t):[{type:"helpfeel",raw:e,text:e.substring(2)}],$e=f(je,{parseOnNested:!1,parseOnQuoted:!1,patterns:[Re]}),Ue=/\[\[https?:\/\/[^\s\]]+\.(?:png|jpe?g|gif|svg)\]\]/i,Ae=/\[\[https?:\/\/(?:[0-9a-z-]+\.)?gyazo\.com\/[0-9a-f]{32}\]\]/,Be=(e,t)=>{if(t.context==="table")return g(e,t);let n=e.substring(2,e.length-2),r=/^https?:\/\/([0-9a-z-]\.)?gyazo\.com\/[0-9a-f]{32}$/.test(n);return[{type:"strongImage",raw:e,src:r?${n}/thumb/1000:n}]},Fe=f(Be,{parseOnNested:!1,parseOnQuoted:!0,patterns:[Ue,Ae]}),_e=/\[[^[\]]*\.icon(?:\*[1-9]\d*)?\]/;function oe(e){return(t,n)=>{if(e==="strongIcon"&&n.context==="table")return g(t,n);let r=e==="icon"?t.substring(1,t.length-1):t.substring(2,t.length-2),o=r.lastIndexOf(".icon"),s=r.substring(0,o),a=s.startsWith("/")?"root":"relative",i=r.substring(o+5,r.length),c=i.startsWith("*")?parseInt(i.substring(1),10):1;return new Array(c).fill({}).map(()=>({path:s,pathType:a,type:e,raw:t}))}}var Ke=oe("icon"),We=f(Ke,{parseOnNested:!1,parseOnQuoted:!0,patterns:[_e]}),ze=/\[\[[^[\]]*\.icon(?:\*\d+)?\]\]/,qe=oe("strongIcon"),Qe=f(qe,{parseOnNested:!1,parseOnQuoted:!0,patterns:[ze]}),Xe=/\[\[(?:[^[]|\[[^[]).*?\]*\]\]/,Ye=(e,t)=>t.context==="table"?g(e,t):[{type:"strong",raw:e,nodes:I(e.substring(2,e.length-2),{...t,nested:!0})}],Ge=f(Ye,{parseOnNested:!1,parseOnQuoted:!0,patterns:[Xe]}),Ve=/\[\$ .+? \]/,Je=/\[\$ [^\]]+\]/,Ze=(e,t)=>t.context==="table"?g(e,t):[{type:"formula",raw:e,formula:e.substring(3,e.length-(e.endsWith(" ]")?2:1))}],et=f(Ze,{parseOnNested:!1,parseOnQuoted:!0,patterns:[Ve,Je]}),tt=/\[[!"#%&'()*+,\-./{|}<>_~]+ (?:\[[^[\]]+\]|[^\]])+\]/,nt=(e,t)=>{if(t.context==="table")return g(e,t);let n=e.indexOf(" "),r=e.substring(1,n),o=e.substring(n+1,e.length-1),s=new Set(r);if(s.has("*")){let a=r.split("*").length-1;s.delete("*"),s.add(*-${Math.min(a,10)})}return[{type:"decoration",raw:e,rawDecos:r,decos:Array.from(s),nodes:I(o,{...t,nested:!0})}]},rt=f(nt,{parseOnNested:!1,parseOnQuoted:!0,patterns:[tt]}),ot=/.*?/,st=(e,t)=>t.context==="table"?g(e,t):[{type:"code",raw:e,text:e.substring(1,e.length-1)}],it=f(st,{parseOnNested:!1,parseOnQuoted:!0,patterns:[ot]}),at=/^[$%] .+$/,ct=(e,t)=>{var n;if(t.context==="table")return g(e,t);let r=(n=e[0])!==null&&n!==void 0?n:"",o=e.substring(2);return[{type:"commandLine",raw:e,symbol:r,text:o}]},pt=f(ct,{parseOnNested:!1,parseOnQuoted:!1,patterns:[at]}),ut=/\[\s+\]/,dt=(e,t)=>t.context==="table"?g(e,t):[{type:"blank",raw:e,text:e.substring(1,e.length-1)}],lt=f(dt,{parseOnNested:!1,parseOnQuoted:!0,patterns:[ut]}),mt=/\[https?:\/\/[^\s\]]+\.(?:png|jpe?g|gif|svg)(?:\?[^\]\s]+)?(?:\s+https?:\/\/[^\s\]]+)?\]/i,ft=/\[https?:\/\/[^\s\]]+\s+https?:\/\/[^\s\]]+\.(?:png|jpe?g|gif|svg)(?:\?[^\]\s]+)?\]/i,gt=/\[https?:\/\/(?:[0-9a-z-]+\.)?gyazo\.com\/[0-9a-f]{32}(?:\/raw)?(?:\s+https?:\/\/[^\s\]]+)?\]/,ht=/\[https?:\/\/[^\s\]]+\s+https?:\/\/(?:[0-9a-z-]+\.)?gyazo\.com\/[0-9a-f]{32}(?:\/raw)?\]/,xt=e=>/^https?:\/\/[^\s\]]+\.(png|jpe?g|gif|svg)(\?[^\]\s]+)?$/i.test(e)||wt(e),wt=e=>/^https?:\/\/([0-9a-z-]\.)?gyazo\.com\/[0-9a-f]{32}(\/raw)?$/.test(e),yt=(e,t)=>{if(t.context==="table")return g(e,t);let n=e.search(/\s/),r=n!==-1?e.substring(1,n):e.substring(1,e.length-1),o=n!==-1?e.substring(n,e.length-1).trimLeft():"",[s,a]=xt(o)?[o,r]:[r,o];return[{type:"image",raw:e,src:/^https?:\/\/([0-9a-z-]\.)?gyazo\.com\/[0-9a-f]{32}$/.test(s)?${s}/thumb/1000:s,link:a}]},Et=f(yt,{parseOnNested:!0,parseOnQuoted:!0,patterns:[mt,ft,gt,ht]}),bt=/\[https?:\/\/[^\s\]]+\s+[^\]]*[^\s]\]/,kt=/\[[^[\]]*[^\s]\s+https?:\/\/[^\s\]]+\]/,vt=/\[https?:\/\/[^\s\]]+\]/,Tt=/https?:\/\/[^\s]+/,Lt=(e,t)=>{if(t.context==="table")return g(e,t);let n=e.startsWith("[")&&e.endsWith("]")?e.substring(1,e.length-1):e,r=/^https?:\/\/[^\s\]]/.test(n),o=(r?/^https?:\/\/[^\s\]]+/:/https?:\/\/[^\s\]]+$/).exec(n);if((o==null?void 0:o[0])===void 0)return[];let s=r?n.substring(o[0].length):n.substring(0,o.index-1);return[{type:"link",raw:e,pathType:"absolute",href:o[0],content:s.trim()}]},It=f(Lt,{parseOnNested:!0,parseOnQuoted:!0,patterns:[bt,kt,vt,Tt]}),se=/\[([^\]]*[^\s])\s+([NS]\d+(?:\.\d+)?,[EW]\d+(?:\.\d+)?(?:,Z\d+)?)\]/,ie=/\[([NS]\d+(?:\.\d+)?,[EW]\d+(?:\.\d+)?(?:,Z\d+)?)(?:\s+([^\]]*[^\s]))?\]/,Mt=e=>{let[t="",n="",r=""]=e.split(","),o=parseFloat(t.replace(/^N/,"").replace(/^S/,"-")),s=parseFloat(n.replace(/^E/,"").replace(/^W/,"-")),a=/^Z\d+$/.test(r)?parseInt(r.replace(/^Z/,""),10):14;return{latitude:o,longitude:s,zoom:a}},Ct=(e,t)=>{var n;if(t.context==="table")return g(e,t);let r=(n=e.match(se))!==null&&n!==void 0?n:e.match(ie);if(r===null)return[];let o=e.startsWith("[N")||e.startsWith("[S"),[,s="",a=""]=o?r:[r[0],r[2],r[1]],{latitude:i,longitude:c,zoom:u}=Mt(s),p=a!==""?https://www.google.com/maps/place/${encodeURIComponent(a)}/@${i},${c},${u}z:https://www.google.com/maps/@${i},${c},${u}z;return[{type:"googleMap",raw:e,latitude:i,longitude:c,zoom:u,place:a,url:p}]},Pt=f(Ct,{parseOnNested:!1,parseOnQuoted:!0,patterns:[se,ie]}),Nt=/\[\/?[^[\]]+\]/,Dt=e=>{let t=e.substring(1,e.length-1);return[{type:"link",raw:e,pathType:t.startsWith("/")?"root":"relative",href:t,content:""}]},Ot=f(Dt,{parseOnNested:!0,parseOnQuoted:!0,patterns:[Nt]}),St=/(?:^|\s)#\S+/,Ht=(e,t)=>{if(t.context==="table")return g(e,t);if(e.startsWith("#"))return[{type:"hashTag",raw:e,href:e.substring(1)}];let n=e.substring(0,1),r=e.substring(1);return[...g(n,t),{type:"hashTag",raw:r,href:r.substring(1)}]},Rt=f(Ht,{parseOnNested:!0,parseOnQuoted:!0,patterns:[St]}),jt=(e,t,n)=>{var r;return e===""?[]:(r=n==null?void 0:n())!==null&&r!==void 0?r:[]},$t=(...e)=>(t,n)=>e.reduceRight((r,o)=>()=>o(t,n,r),()=>De(t,n))(),I=$t(jt,He,$e,it,pt,et,lt,rt,Fe,Qe,Ge,Et,It,We,Pt,Ot,Rt),Ut=e=>{let{rows:[t,...n]}=e,{indent:r=0,text:o=""}=t??{},s=o.replace(/^\s*table:/,"");return{indent:r,type:"table",fileName:s,cells:n.map(a=>a.text.substring(r+1)).map(a=>a.split(" ").map(i=>I(i,{nested:!1,quoted:!1,context:"table"})))}},At=e=>{let{indent:t,text:n}=e.rows[0];return{indent:t,type:"line",nodes:I(n.substring(t),{nested:!1,quoted:!1,context:"line"})}},ae=e=>{switch(e.type){case"title":return Pe(e);case"codeBlock":return Ne(e);case"table":return Ut(e);case"line":return At(e)}},ce=e=>e.split( ).map(t=>{var n,r,o;return{indent:(o=(r=(n=/^\s+/.exec(t))===null||n===void 0?void 0:n[0])===null||r===void 0?void 0:r.length)!==null&&o!==void 0?o:0,text:t}}),Bt=(e,t)=>{var n,r;return(e.type==="codeBlock"||e.type==="table")&&t.indent>((r=(n=e.rows[0])===null||n===void 0?void 0:n.indent)!==null&&r!==void 0?r:0)},pe=(e,t)=>{let n=e[e.length-1];return n!==void 0&&Bt(n,t)?(n.rows.push(t),e):(e.push({type:/^\s*code:/.test(t.text)?"codeBlock":/^\s*table:/.test(t.text)?"table":"line",rows:[t]}),e)},ue=(e,t)=>{var n;if((n=t.hasTitle)!==null&&n!==void 0?n:!0){let[r,...o]=e;return r===void 0?[]:[{type:"title",rows:[r]},...o.reduce(pe,[])]}return e.reduce(pe,[])};function de(e,t,{userId:n,head:r}){let o=t.flatMap(p=>p.split(
)),s=[...re(e,o,{userId:n})];(e[0].text!==o[0]||!r.persistent)&&s.push({title:o[0]});let a=e.slice(1,6).map(p=>p.text),i=o.slice(1,6);a.join("")!==i.join("")&&s.push({descriptions:i});let[c,u]=Ft(o.join(
));return(r.links.length!==c.length||!r.links.every(p=>c.includes(p)))&&s.push({links:c}),r.image!==u&&s.push({image:u}),s}function Ft(e){let t=ce(e),n=ue(t,{hasTitle:!0}).flatMap(i=>{switch(i.type){case"codeBlock":case"title":return[];case"line":case"table":return[ae(i)]}}),r=new Map,o=[],s=null,a=i=>{switch(i.type){case"hashTag":if(r.has(P(i.href)))return;r.set(P(i.href),!1),o.push(i.href);return;case"link":if(i.pathType!=="relative"||r.get(P(i.href)))return;r.set(P(i.href),!0),o.push(i.href);return;case"image":case"strongImage":{s??=i.src.endsWith("/thumb/1000")?i.src.replace(/\/thumb\/1000$/,"/raw"):i.src;return}case"strong":case"quote":case"decoration":{for(let c of i.nodes)a(c);return}default:return}};for(let i of _t(n))a(i);return[o,s]}function*_t(e){for(let t of e)switch(t.type){case"codeBlock":case"title":continue;case"line":for(let n of t.nodes)yield n;continue;case"table":{for(let n of t.cells)for(let r of n)for(let o of r)yield o;continue}}}async function M(e,t){let n=await F(e,t);if(!n.ok)throw new Error(You have no privilege of editing "/${e}/${t}".);let{commitId:r,persistent:o,image:s,links:a,lines:i,id:c,pin:u}=n.value;return{commitId:r,pageId:c,persistent:o,image:s,links:a,pin:u,lines:i}}async function $(e,t,n){return t.length===0?{commitId:n.parentId}:await e("socket.io-request",{method:"commit",data:{kind:"page",...n,changes:t,cursor:null,freeze:!0}})}async function U(e,t,{project:n,title:r,retry:o=3,parentId:s,...a}){try{s=(await $(e,t,{parentId:s,...a})).commitId}catch{console.log("Faild to push a commit. Retry after pulling new commits");for(let c=0;c<o;c++){let{commitId:u}=await M(n,r);s=u;try{s=(await $(e,t,{parentId:s,...a})).commitId,console.log("Success in retrying");break}catch{continue}}throw Error("Faild to retry pushing.")}return s}async function le(e,t,n,r){let[o,s,a]=await Promise.all([M(e,t),D(e),j()]),i=o,c=r?.socket,u=c??await v();await N(u);try{let{request:p}=C(u);for(let m=0;m<3;m++)try{let l=n(i.lines,i),x=l instanceof Promise?await l:l;if(!x)return;x.length===0&&await U(p,[{deleted:!0}],{projectId:s,pageId:i.pageId,parentId:i.commitId,userId:a,project:e,title:t});let h=de(i.lines,x,{userId:a,head:i});await $(p,h,{parentId:i.commitId,projectId:s,pageId:i.pageId,userId:a});break}catch{if(m===2)throw Error("Faild to retry pushing.");console.log("Faild to push a commit. Retry after pulling new commits");try{i=await M(e,t)}catch(x){throw x}}}finally{c||await L(u)}}async function rs(e,t){let n=Kt(e);if(!n)return;let r=window.prompt(Replace "${n}" to this in ${t.map(i=>"/${i}").join(", ")},n)?.replace?.(/[\[\]\n]/g," ")??"";if(r==="")return;let{render:o,dispose:s}=X(),a=await G();try{o({type:"spinner"},{type:"text",text:Replacing links in ${t.length} projects...});let i=0,u=(await Promise.all(t.map(async p=>{let[m]=await Promise.all([K(p,n,r),le(p,n,(l,{persistent:x})=>{if(!!x)return[r,...l.map(h=>h.text).slice(1)]},{socket:a})]);if(!m.ok)throw o({type:"exclamation-triangle"},{type:"text",text:${m.value.name} ${m.value.message}}),Wt(m.value);return i++,o({type:"spinner"},{type:"text",text:Replacing links in ${t.length-i} projects...}),m.value}))).reduce((p,m)=>p+m,0);o({type:"check-circle"},{type:"text",text:Successfully replaced ${u} links.`})}finally{await L(a),setTimeout(s,1e3)}}function Kt(e){return e.match(/\[([^\!"#%&'()\*\+,\-\.\/\{\|\}<>_~[^\\]*)\]/)?.1}function Wt(e){let t=new Error;return t.name=e.name,t.message=e.message,t}export{Kt as getLink,rs as replace};