search-SameTitlePage-script
ベースはこれ
/api/code/yosider-scripts/参加しているprojectの同名ページを検索するUserScript/import.js
/api/code/programming-notes/参加している他のprojectに同じページがあったら教えてほしい/run2.js
code:run.js
(async () => {
})();
code:run2.js
const id = "OtherProjects";
export async function execute(extraProjects = []) {
const response = await fetch('/api/projects');
const json = await response.json();
const projects = [...new Set([
...extraProjects,
...json.projects.map(({name}) => name),
])
].filter(project => project !== scrapbox.Project.name); // 現在のprojectは除く
scrapbox.PageMenu.addMenu({
title: id,
onClick: async () => {
const menu = scrapbox.PageMenu(id);
menu.removeAllItems();
menu.emitChange();
const isFound = await Promise.all(projects.map(project => addItem(project, menu)));
if (isFound.some(i => i)) {
menu.addItem({ title: "Open All pages", onClick: () => {
projects.filter((_, i) => isFoundi).map(project => window.open( https://scrapbox.io/${project}/${scrapbox.Page.title}
))
}});
menu.addItem({
title: "Copy All page links", onClick: () => {
const pages = projects.filter((_, i) => isFoundi).map(p => https://scrapbox.io/${p}/${scrapbox.Page.title}) navigator.clipboard.writeText(pages.join("\n"))
}
});
return
};
menu.addItem({ title: 'No page found.', onClick: () => {} });
},
});
}
async function addItem(project, menu) {
const response = await fetch(/api/pages/${project}/${scrapbox.Page.title});
if (!response.ok) return false;
const {lines} = await response.json();
//console.log(lines);
if (lines.length < 3 && !lines1?.text) return false; // タイトルを除いて1行以内かつ1行目が空のとき、空ページだと判断する menu.addItem({
title: /${project}/${scrapbox.Page.title},
onClick: () =>
window.open(
https://scrapbox.io/${project}/${scrapbox.Page.title}
),
});
return true;
}
変更したい点
同名のページがあったらアイコンの色を変える
fizzsearchによる曖昧検索
もちろんソート
仮実装
code:run.js_
var m=!1;var v=r=>Object.fromEntries(...Object.entries(console).map((o,e)=>{if(typeof e!="function")returno,e;switch(o){case"warn":case"error":return[o,(...t)=>e(%c${r},"color: gray",...t)];case"log":case"info":case"debug":return[o,(...t)=>{m!==!0&&(!m||!m.has(r))||e(%c${r},"color: gray",...t)}];case"assert":return[o,(t,...s)=>{m!==!0&&(!m||!m.has(r))||e(t,%c${r},"color: gray",...s)}];case"time":case"timeEnd":return[o,t=>{m!==!0&&(!m||!m.has(r))||e(${r} ${t})}];default:returno,(...t)=>{if(!(m!==!0&&(!m||!m.has(r))))return e(...t)}}}));var u=r=>{let{fetch:o=globalThis.fetch,hostName:e="scrapbox.io",...t}=r;return{fetch:o,hostName:e,...t}};var Ge=r=>typeof r=="object"&&r!==null,Ve=r=>Ge(r)?(r.name===void 0||typeof r.name=="string")&&typeof r.message=="string":!1,Q=r=>{try{let o=typeof r=="string"?JSON.parse(r):r;return Ve(o)?o:!1}catch(o){if(o instanceof SyntaxError)return!1;throw o}};var I=class extends Error{constructor(o){super(${o.status} ${o.statusText} when fetching ${o.url});this.response=o;this.name="UnexpectedResponseError";Error.captureStackTrace&&Error.captureStackTrace(this,I)}},l=async r=>{let o=r.clone(),e=await o.text(),t=Q(e);if(!t)throw new I(o);return{ok:!1,value:t}};var p=r=>connect.sid=${r};var C=r=>r.replaceAll(" ","_").toLowerCase();var w=r=>...r.map((o,e)=>o===" "?"_":!ze.includes(o)||e===r.length-1&&Xe.includes(o)?encodeURIComponent(o):o).join(""),ze='@$&+=:;",',Xe=':;",';var Z=(r,o,e)=>{let{sid:t,hostName:s,followRename:n,projects:a}=u(e??{}),i=new URLSearchParams;i.append("followRename",${n??!0});for(let d of a??[])i.append("projects",d);let c=https://${s}/api/pages/${r}/${w(o)}?${i.toString()};return new Request(c,t?{headers:{Cookie:p(t)}}:void 0)},ee=async r=>{if(!r.ok)return r.status===414?{ok:!1,value:{name:"TooLongURIError",message:"project ids may be too much."}}:l(r);let o=await r.json();return{ok:!0,value:o}},q=async(r,o,e)=>{let{fetch:t}=u(e??{}),s=Z(r,o,e),n=await t(s);return await ee(n)};q.toRequest=Z;q.fromResponse=ee;var te=(r,o)=>{let{sid:e,hostName:t,sort:s,limit:n,skip:a}=u(o??{}),i=new URLSearchParams;s!==void 0&&i.append("sort",s),n!==void 0&&i.append("limit",${n}),a!==void 0&&i.append("skip",${a});let c=https://${t}/api/pages/${r}?${i.toString()};return new Request(c,e?{headers:{Cookie:p(e)}}:void 0)},re=async r=>{if(!r.ok)return l(r);let o=await r.json();return{ok:!0,value:o}},oe=async(r,o)=>{let{fetch:e}=u(o??{}),t=await e(te(r,o));return await re(t)};oe.toRequest=te;oe.fromResponse=re;var ne=(r,o,e,t)=>{let{sid:s,hostName:n}=u(t??{}),a=https://${n}/api/table/${r}/${w(o)}/${encodeURIComponent(e)}.csv;return new Request(a,s?{headers:{Cookie:p(s)}}:void 0)},se=async r=>r.ok?{ok:!0,value:await r.text()}:r.status===404?{ok:!1,value:{name:"NotFoundError",message:"Table not found."}}:l(r),ie=async(r,o,e,t)=>{let{fetch:s}=u(t??{}),n=ne(r,o,e,t),a=await s(n);return await se(a)};ie.toRequest=ne;ie.fromResponse=se;var ae=(r,o)=>{let{sid:e,hostName:t}=u(o??{});return new Request(https://${t}/api/projects/${r},e?{headers:{Cookie:p(e)}}:void 0)},ce=async r=>{if(!r.ok)return l(r);let o=await r.json();return{ok:!0,value:o}},N=async(r,o)=>{let{fetch:e}=u(o??{}),t=ae(r,o),s=await e(t);return ce(s)};N.toRequest=ae;N.fromResponse=ce;var ue=(r,o)=>{let{sid:e,hostName:t}=u(o??{}),s=new URLSearchParams;for(let n of r)s.append("ids",n);return new Request(https://${t}/api/projects?${s.toString()},e?{headers:{Cookie:p(e)}}:void 0)},de=async r=>{if(!r.ok)return l(r);let o=await r.json();return{ok:!0,value:o}},F=async(r,o)=>{let{fetch:e}=u(o??{}),t=await e(ue(r,o));return de(t)};F.toRequest=ue;F.fromResponse=de;var pe=async(r,o)=>{let{sid:e,hostName:t,fetch:s,followingId:n}=u(o??{}),a=new Request(https://${t}/api/pages/${r}/search/titles${n??followingId=${n}:""},e?{headers:{Cookie:p(e)}}:void 0),i=await s(a);if(!i.ok)return i.status===422?{ok:!1,value:{name:"InvalidFollowingIdError",message:await i.text()}}:l(i);let c=await i.json();return{ok:!0,value:{pages:c,followingId:i.headers.get("X-following-id")??""}}};var so=new Map;var le=(r,o,e,t)=>{let{sid:s,hostName:n}=u(t??{}),a=https://${n}/api/code/${r}/${w(o)}/${w(e)};return new Request(a,s?{headers:{Cookie:p(s)}}:void 0)},me=async r=>r.ok?{ok:!0,value:await r.text()}:r.status===404&&r.headers.get("Content-Type")?.includes?.("text/plain")?{ok:!1,value:{name:"NotFoundError",message:"Code block is not found"}}:l(r),fe=async(r,o,e,t)=>{let{fetch:s}=u(t??{}),n=le(r,o,e,t),a=await s(n);return await me(a)};fe.toRequest=le;fe.fromResponse=me;var ge=new TextEncoder().encode("0123456789abcdef");function he(r){let o=new Uint8Array(r.length*2);for(let e=0;e<o.length;e++){let t=re;oe*2=get>>4,oe*2+1=get&15}return o}var xe="md5: data is invalid type",L=64,_=class{#e;#t;#r;#o;#n;#i;#s;#a;constructor(){this.#e=1732584193,this.#t=4023233417,this.#r=2562383102,this.#o=271733878,this.#n=new Uint8Array(L),this.#i=0,this.#s=0,this.#a=0}#u(o){let e=this.#s;e+=o,e>4294967295&&(this.#a+=1),this.#s=e>>>0}#c(o){let e=this.#e,t=this.#t,s=this.#r,n=this.#o,a=y=>oy|oy+1<<8|oy+2<<16|oy+3<<24,i=(y,J)=>y<<J|y>>>32-J,c=a(0),d=a(4),f=a(8),g=a(12),h=a(16),T=a(20),k=a(24),E=a(28),P=a(32),R=a(36),M=a(40),S=a(44),j=a(48),B=a(52),D=a(56),O=a(60);e=t+i(((s^n)&t^n)+e+c+3614090360,7),n=e+i(((t^s)&e^s)+n+d+3905402710,12),s=n+i(((e^t)&n^t)+s+f+606105819,17),t=s+i(((n^e)&s^e)+t+g+3250441966,22),e=t+i(((s^n)&t^n)+e+h+4118548399,7),n=e+i(((t^s)&e^s)+n+T+1200080426,12),s=n+i(((e^t)&n^t)+s+k+2821735955,17),t=s+i(((n^e)&s^e)+t+E+4249261313,22),e=t+i(((s^n)&t^n)+e+P+1770035416,7),n=e+i(((t^s)&e^s)+n+R+2336552879,12),s=n+i(((e^t)&n^t)+s+M+4294925233,17),t=s+i(((n^e)&s^e)+t+S+2304563134,22),e=t+i(((s^n)&t^n)+e+j+1804603682,7),n=e+i(((t^s)&e^s)+n+B+4254626195,12),s=n+i(((e^t)&n^t)+s+D+2792965006,17),t=s+i(((n^e)&s^e)+t+O+1236535329,22),e=t+i(((t^s)&n^s)+e+d+4129170786,5),n=e+i(((e^t)&s^t)+n+k+3225465664,9),s=n+i(((n^e)&t^e)+s+S+643717713,14),t=s+i(((s^n)&e^n)+t+c+3921069994,20),e=t+i(((t^s)&n^s)+e+T+3593408605,5),n=e+i(((e^t)&s^t)+n+M+38016083,9),s=n+i(((n^e)&t^e)+s+O+3634488961,14),t=s+i(((s^n)&e^n)+t+h+3889429448,20),e=t+i(((t^s)&n^s)+e+R+568446438,5),n=e+i(((e^t)&s^t)+n+D+3275163606,9),s=n+i(((n^e)&t^e)+s+g+4107603335,14),t=s+i(((s^n)&e^n)+t+P+1163531501,20),e=t+i(((t^s)&n^s)+e+B+2850285829,5),n=e+i(((e^t)&s^t)+n+f+4243563512,9),s=n+i(((n^e)&t^e)+s+E+1735328473,14),t=s+i(((s^n)&e^n)+t+j+2368359562,20),e=t+i((t^s^n)+e+T+4294588738,4),n=e+i((e^t^s)+n+P+2272392833,11),s=n+i((n^e^t)+s+S+1839030562,16),t=s+i((s^n^e)+t+D+4259657740,23),e=t+i((t^s^n)+e+d+2763975236,4),n=e+i((e^t^s)+n+h+1272893353,11),s=n+i((n^e^t)+s+E+4139469664,16),t=s+i((s^n^e)+t+M+3200236656,23),e=t+i((t^s^n)+e+B+681279174,4),n=e+i((e^t^s)+n+c+3936430074,11),s=n+i((n^e^t)+s+g+3572445317,16),t=s+i((s^n^e)+t+k+76029189,23),e=t+i((t^s^n)+e+R+3654602809,4),n=e+i((e^t^s)+n+j+3873151461,11),s=n+i((n^e^t)+s+O+530742520,16),t=s+i((s^n^e)+t+f+3299628645,23),e=t+i((s^(t|~n))+e+c+4096336452,6),n=e+i((t^(e|~s))+n+E+1126891415,10),s=n+i((e^(n|~t))+s+D+2878612391,15),t=s+i((n^(s|~e))+t+T+4237533241,21),e=t+i((s^(t|~n))+e+j+1700485571,6),n=e+i((t^(e|~s))+n+g+2399980690,10),s=n+i((e^(n|~t))+s+M+4293915773,15),t=s+i((n^(s|~e))+t+d+2240044497,21),e=t+i((s^(t|~n))+e+P+1873313359,6),n=e+i((t^(e|~s))+n+O+4264355552,10),s=n+i((e^(n|~t))+s+k+2734768916,15),t=s+i((n^(s|~e))+t+B+1309151649,21),e=t+i((s^(t|~n))+e+h+4149444226,6),n=e+i((t^(e|~s))+n+S+3174756917,10),s=n+i((e^(n|~t))+s+f+718787259,15),t=s+i((n^(s|~e))+t+R+3951481745,21),this.#e=this.#e+e>>>0,this.#t=this.#t+t>>>0,this.#r=this.#r+s>>>0,this.#o=this.#o+n>>>0}update(o){let e;if(typeof o=="string")e=new TextEncoder().encode(o);else if(typeof o=="object")if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))e=new Uint8Array(o);else throw new TypeError(xe);else throw new TypeError(xe);let t=this.#i,s=L-t;if(e.length<s)this.#n.set(e,t),t+=e.length;else{this.#n.set(e.slice(0,s),t),this.#c(this.#n);let n=s;for(;n+L<=e.length;)this.#c(e.slice(n,n+L)),n+=L;this.#n.fill(0).set(e.slice(n),0),t=e.length-n}return this.#i=t,this.#u(e.length),this}digest(){let o=L-this.#i;o<9&&(o+=L);let e=new Uint8Array(o);e0=128;let t=this.#s<<3,s=this.#a<<3|this.#s>>>29;ee.length-8=t&255,ee.length-7=t>>>8&255,ee.length-6=t>>>16&255,ee.length-5=t>>>24&255,ee.length-4=s&255,ee.length-3=s>>>8&255,ee.length-2=s>>>16&255,ee.length-1=s>>>24&255,this.update(e.buffer);let n=new ArrayBuffer(16),a=new DataView(n);return a.setUint32(0,this.#e,!0),a.setUint32(4,this.#t,!0),a.setUint32(8,this.#r,!0),a.setUint32(12,this.#o,!0),n}toString(o="hex"){let e=this.digest();switch(o){case"hex":return new TextDecoder().decode(he(new Uint8Array(e)));case"base64":{let t=new Uint8Array(e),s="";for(let n=0;n<t.length;++n)s+=String.fromCharCode(tn);return btoa(s)}default:throw new Error("md5: invalid format")}}};var Ee=!1;scrapbox.addListener("lines:changed",()=>Ee=!1);scrapbox.addListener("layout:changed",()=>Ee=!1);var be=r=>{leto,e,t,...s=r;return{title:o,links:s,image:e,exists:t>=0,updated:Math.min(0,t)}},ke=r=>r.title,r.image,r.exists?r.updated:-1,...r.links;var ye=r=>{let o=new Map;for(let e of r){let t=C(e.title);o.set(t,{title:e.title,image:e.image,updated:e.updated,links:e.links,exists:!0});for(let s of e.links){let n=C(s);o.has(n)||o.set(n,{title:s,updated:0,links:[],exists:!1})}}return...o.values().map(e=>ke(e))};var Le=v("scrapbox-storage:remote.ts"),Te=async r=>{let o,e=[],t=download and create Links of "${r}";Le.time(t);do{let n=await pe(r,{followingId:o});if(!n.ok)return n;o=n.value.followingId,e.push(...n.value.pages)}while(o);let s=ye(e);return Le.timeEnd(t),{ok:!0,value:s}};async function*ve(r){let o=[],e=[],t=new Map;for(let n of r)n.id?o.push(n.id):e.push(n.project),t.set(n.project,n.checked);let s=await F(o);if(!s.ok)e=r.map(n=>n.project);else for(let n of s.value.projects)!t.has(n.name)||(yield{ok:!0,value:{...n,checked:t.get(n.name)??0}});for(let n of e){let a=await N(n);yield a.ok?{ok:!0,value:{...a.value,checked:t.get(n)??0}}:{ok:!1,value:{...a.value,project:n}}}}var G=(r,o)=>o.some(e=>r instanceof e),Ie,Ce;function st(){return Ie||(Ie=IDBDatabase,IDBObjectStore,IDBIndex,IDBCursor,IDBTransaction)}function it(){return Ce||(Ce=IDBCursor.prototype.advance,IDBCursor.prototype.continue,IDBCursor.prototype.continuePrimaryKey)}var Ne=new WeakMap,V=new WeakMap,Pe=new WeakMap,W=new WeakMap,H=new WeakMap;function at(r){let o=new Promise((e,t)=>{let s=()=>{r.removeEventListener("success",n),r.removeEventListener("error",a)},n=()=>{e(b(r.result)),s()},a=()=>{t(r.error),s()};r.addEventListener("success",n),r.addEventListener("error",a)});return o.then(e=>{e instanceof IDBCursor&&Ne.set(e,r)}).catch(()=>{}),H.set(o,r),o}function ct(r){if(V.has(r))return;let o=new Promise((e,t)=>{let s=()=>{r.removeEventListener("complete",n),r.removeEventListener("error",a),r.removeEventListener("abort",a)},n=()=>{e(),s()},a=()=>{t(r.error||new DOMException("AbortError","AbortError")),s()};r.addEventListener("complete",n),r.addEventListener("error",a),r.addEventListener("abort",a)});V.set(r,o)}var z={get(r,o,e){if(r instanceof IDBTransaction){if(o==="done")return V.get(r);if(o==="objectStoreNames")return r.objectStoreNames||Pe.get(r);if(o==="store")return e.objectStoreNames1?void 0:e.objectStore(e.objectStoreNames0)}return b(ro)},set(r,o,e){return ro=e,!0},has(r,o){return r instanceof IDBTransaction&&(o==="done"||o==="store")?!0:o in r}};function Re(r){z=r(z)}function ut(r){return r===IDBDatabase.prototype.transaction&&!("objectStoreNames"in IDBTransaction.prototype)?function(o,...e){let t=r.call(A(this),o,...e);return Pe.set(t,o.sort?o.sort():o),b(t)}:it().includes(r)?function(...o){return r.apply(A(this),o),b(Ne.get(this))}:function(...o){return b(r.apply(A(this),o))}}function dt(r){return typeof r=="function"?ut(r):(r instanceof IDBTransaction&&ct(r),G(r,st())?new Proxy(r,z):r)}function b(r){if(r instanceof IDBRequest)return at(r);if(W.has(r))return W.get(r);let o=dt(r);return o!==r&&(W.set(r,o),H.set(o,r)),o}var A=r=>H.get(r);function Me(r,o,{blocked:e,upgrade:t,blocking:s,terminated:n}={}){let a=indexedDB.open(r,o),i=b(a);return t&&a.addEventListener("upgradeneeded",c=>{t(b(a.result),c.oldVersion,c.newVersion,b(a.transaction),c)}),e&&a.addEventListener("blocked",c=>e(c.oldVersion,c.newVersion,c)),i.then(c=>{n&&c.addEventListener("close",()=>n()),s&&c.addEventListener("versionchange",d=>s(d.oldVersion,d.newVersion,d))}).catch(()=>{}),i}var pt="get","getKey","getAll","getAllKeys","count",lt="put","add","delete","clear",X=new Map;function Se(r,o){if(!(r instanceof IDBDatabase&&!(o in r)&&typeof o=="string"))return;if(X.get(o))return X.get(o);let e=o.replace(/FromIndex$/,""),t=o!==e,s=lt.includes(e);if(!(e in(t?IDBIndex:IDBObjectStore).prototype)||!(s||pt.includes(e)))return;let n=async function(a,...i){let c=this.transaction(a,s?"readwrite":"readonly"),d=c.store;return t&&(d=d.index(i.shift())),(await Promise.all([de(...i),s&&c.done]))0};return X.set(o,n),n}Re(r=>({...r,get:(o,e,t)=>Se(o,e)||r.get(o,e,t),has:(o,e)=>!!Se(o,e)||r.has(o,e)}));var mt="continue","continuePrimaryKey","advance",je={},Y=new WeakMap,Be=new WeakMap,ft={get(r,o){if(!mt.includes(o))return ro;let e=jeo;return e||(e=jeo=function(...t){Y.set(this,Be.get(this)o(...t))}),e}};async function*gt(...r){let o=this;if(o instanceof IDBCursor||(o=await o.openCursor(...r)),!o)return;o=o;let e=new Proxy(o,ft);for(Be.set(e,o),H.set(e,A(o));o;)yield e,o=await(Y.get(e)||o.continue()),Y.delete(e)}function De(r,o){return o===Symbol.asyncIterator&&G(r,IDBIndex,IDBObjectStore,IDBCursor)||o==="iterate"&&G(r,IDBIndex,IDBObjectStore)}Re(r=>({...r,get(o,e,t){return De(o,e)?gt:r.get(o,e,t)},has(o,e){return De(o,e)||r.has(o,e)}}));var Oe=v("scrapbox-storage:db.ts"),Fe,U=async()=>(Fe??=await Me("scrapbox-storage",1,{upgrade(r){Oe.time("update DB");for(let o of r.objectStoreNames)r.deleteObjectStore(o);r.createObjectStore("links",{keyPath:"project"}),r.createObjectStore("status",{keyPath:"project"}),Oe.timeEnd("update DB")}}),Fe),$e=async r=>(await U()).put("links",r);var ht=new Map,He=r=>{let o={type:"update",projects:r};Ae(o);let e=new BroadcastChannel(Ue);e.postMessage(o),e.close()},Ae=r=>{for(let o of new Set(r.projects.flatMap(e=>[...ht.get(e)??[]])))o?.(r)},Ue="scrapbox-storage-notify",xt=new BroadcastChannel(Ue);xt.addEventListener("message",r=>Ae(r.data));var x=v("scrapbox-storage:mod.ts"),qe=async(r,o)=>{let e=await U(),t=[],s=[];try{{x.debug("check updates of links...");let i=e.transaction("status","readwrite");await Promise.all(r.map(async c=>{let d=await i.store.get(c);if(d?.isValid===!1)return;let f=d?.checked??0,g=new Date().getTime()/1e3;if(f+o>g||d?.updating&&f+600>g)return;let h={project:c,id:d?.id,isValid:!0,checked:f,updated:d?.updated??0,updating:!0};t.push(h),i.store.put(h)})),await i.done,x.debug(checked. ${t.length} projects maybe need upgrade.)}if(t.length===0)return[];let n=[],a=[];for await(let i of ve(t)){if(!i.ok)switch(s.push({project:i.value.project,isValid:!1}),i.value.name){case"NotFoundError":x.warn("${i.value.project}" is not found.);continue;case"NotMemberError":x.warn(You are not a member of "${i.value.project}".);continue;case"NotLoggedInError":x.warn(You are not a member of "${i.value.project}" or You are not logged in yet.);continue}if(i.value.updated<i.value.checked)x.debug(no updates in "${i.value.name}");else{let c=await Te(i.value.name);if(!c.ok)throw Error(${c.value.name} ${c.value.message});let d={project:i.value.name,links:c.value};a.push(d),x.time(write data of "${i.value.name}"),await $e(d),n.push(i.value.name),x.timeEnd(write data of "${i.value.name}")}s.push({project:i.value.name,isValid:!0,id:i.value.id,checked:new Date().getTime()/1e3,updated:i.value.updated,updating:!1})}return n.length>0&&He(n),a}finally{let n=e.transaction("status","readwrite"),a=n.store;await Promise.all(s.map(i=>a.put(i))),await n.done}},_e=async r=>{let o=[],e=new Date;{let s=(await U()).transaction("links","readonly");await Promise.all(r.map(async n=>{let a=await s.store.get(n);o.push(a??{project:n,links:[]})})),await s.done}let t=new Date().getTime()-e.getTime();return x.debug(Read links of ${r.length} projects in ${t}ms),o};var Ke="OtherProjects";async function ra(r=[]){let o=[...new Set(...r)].filter(t=>t!==scrapbox.Project.name);(async()=>{let t=await qe(...r,600)})(),scrapbox.PageMenu.addMenu({title:Ke,image:"https://gyazo.com/676238d800a673a77be27d8c310e2d24/raw",onClick:async()=>{let t=scrapbox.PageMenu(Ke);t.removeAllItems(),t.emitChange();let s=new Map,n=await _e(...o);for(let{project:c,links:d}of n)for(let f of d){let{title:g,updated:h,image:T}=be(f),k=C(g),E=s.get(k);s.set(k,{title:E?.title??g,updated:Math.max(E?.updated??0,h),metadata:[...E?.metadata??[],{project:c,image:T}]})}let a=s.get(scrapbox.Page.title);(await Promise.all(a?a.metadata.map(c=>Et(c.project,t)):[])).some(c=>c)||t.addItem({title:"No page found.",onClick:()=>{}})}})}async function Et(r,o){return o.addItem({title:/${r}/${scrapbox.Page.title},onClick:()=>window.open(https://scrapbox.io/${r}/${scrapbox.Page.title})}),!0}export{ra as execute}; code:mod.js
const id = "OtherProjects";
export async function execute(extraProjects = []) {
// const response = await fetch('/api/projects');
// const json = await response.json();
const projects = [...new Set([
...extraProjects,
// ...json.projects.map(({ name }) => name),
])
].filter(project => project !== scrapbox.Project.name); // 現在のprojectは除く
const callback = async () => {
};
callback();
scrapbox.PageMenu.addMenu({
title: id,
onClick: async () => {
const menu = scrapbox.PageMenu(id);
menu.removeAllItems();
menu.emitChange();
const result = new Map;
for (const { project, links } of sources) {
for (const compressedLink of links) {
const { title, updated, image } = decode(compressedLink);
const titleLc = toTitleLc(title);
const candidate = result.get(titleLc);
result.set(titleLc, {
title: candidate?.title ?? title,
updated: Math.max(candidate?.updated ?? 0, updated),
metadata: [...(candidate?.metadata ?? []), { project, image }],
});
}
}
// const isFound = await Promise.all(projects.map(project => addItem(project, menu)));
const looked = result.get(scrapbox.Page.title)
const isFound = await Promise.all(looked ? looked.metadata.map(e => addItem(e.project, menu)) : []);
if (isFound.some(i => i)) return;
menu.addItem({ title: 'No page found.', onClick: () => { } });
},
});
}
async function addItem(project, menu) {
menu.addItem({
title: /${project}/${scrapbox.Page.title},
onClick: () =>
window.open(
https://scrapbox.io/${project}/${scrapbox.Page.title}
),
});
return true;
}