generated at
参加している他のprojectに同じページがあったら教えてほしい
already existsみたいなやつを、自分が参加している他のprojectにも拡張したいyosider
同じタイトルのページを別のprojectでもう作ってたっけ?という時に、あるならすぐに飛びたい
project横断検索でもできるが、タイトルをコピーして検索→横断検索→projectに移動→pageに移動とやや手間
ページを作るときだけじゃなくていいか
自分が参加しているprojectだけじゃなく、各自でprojectを指定できるようにしたほうがいい?
自分が参加しているprojectだけなら、/scrapboxlab/api/projectsですべて取得できます
参加していないprojectも入れるなら、同じタイトルのページを取得するより、似たタイトルのページを検索した方がいい?
(WIP)external-completion的なことをリンクだけじゃなくタイトルについてもやる的な

実装
PageMenuのボタンを押したら、検索して同名ページへのリンク一覧をItemとして出すとか?
指定したプロジェクトの同名ページをfetchし、status codeが200ならmenuにappendする?

run.js_(js)
const projects = ["villagepump","hub", "shokai","nishio","rashitamemo"]; for (const project of projects) { fetch("https://scrapbox.io/api/pages/" + project + `/${scrapbox.Page.title}`) .then((response) => { console.log(response.ok) if(response.ok==true){ window.open("https://scrapbox.io/"+ project + `/${scrapbox.Page.title}`) } } ) }
参加しているプロジェクトだと、ページが存在せずともtrueになって開いてしまう
404じゃないからか
status codeを利用しないで処理しよう

window.open()
きれいに1つずつ開けない気がする
2つ以上開いてしまうことがある

run.js__(js)
const projects = ["villagepump", "hub", "shokai", "nishio", "rashitamemo"]; for (const project of projects) { fetch(`https://scrapbox.io/api/pages/${project}/${scrapbox.Page.title}`) .then((body) => body.json()) .then((data) => { console.log(data.lines.length); if (data.lines.length != 1) { window.open(`https://scrapbox.io/${project}/${scrapbox.Page.title}`); } }); }
linesが0なら開かない
お、ロジックはできたぞ
エラーがいろいろ出ているが
page menuにappendするか?

run.js
const projects = ["villagepump", "hub", "shokai", "nishio", "rashitamemo"]; scrapbox.PageMenu.addMenu({ title: "OtherProjects", image: "https://gyazo.com/676238d800a673a77be27d8c310e2d24/raw", }); for (const project of projects) { fetch(`/api/pages/${project}/${scrapbox.Page.title}`) .then((body) => body.json()) .then((data) => { console.log(data.lines.length); if (data.lines.length != 1) { scrapbox.PageMenu("OtherProjects").addItem({ title: () => `/${project}/${scrapbox.Page.title}`, onClick: () => window.open( `https://scrapbox.io/${project}/${scrapbox.Page.title}` ), }); } }); }
できたぁ〜〜dnindnindnin
今度は押したときに実行するようにするか
手直ししてみたtakker
response.ok と行数で判断する
押すたびにページを取得し直す
fetch を待たない
参加しているprojectすべてから検索する
試し方
js
(async () => { const {execute} = await import('/api/code/programming-notes/参加している他のprojectに同じページがあったら教えてほしい/run2.js'); execute(["villagepump", "hub", "shokai", "nishio", "rashitamemo"]); })();

run2.js
const id = "OtherProjects"; export async function execute(extraProjects = []) { const response = await fetch('/api/projects'); const json = await response.json();

[...new Set([])] 配列の重複を除去するために使っている
run2.js
const projects = [...new Set([ ...extraProjects, ...json.projects.map(({name}) => name), ]) ].filter(project => project !== scrapbox.Project.name); // 現在のprojectは除く scrapbox.PageMenu.addMenu({ title: id, image: "https://gyazo.com/676238d800a673a77be27d8c310e2d24/raw", 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)) return; menu.addItem({ title: 'No page found.', onClick: () => {} }); }, }); }
forEachはPromiseを待ってくれないことを利用?yosider
for loopでも同じことできます
.js
for (const project of projects) { addItem(project); }
特に待つ必要もないので、 await しなかっただけですtakker
なるほどyosider
ヒットするページでクリックした後、ヒットしないページでクリックすると、前のページでの結果が残ったままになるyosider
scrapbox.PageMenu.addItem()ではされている
仕様なのか…?
scrapbox.PageMenu(:id).emitChange()なんてあったのか。知らんかった
emitChange()を追加したら直った
調査していただき感謝ですtakker
変だなあと思いつつ放置してた
確かに直感とは違う挙動ではある
1つもヒットしなかったら「見つかりませんでした」的なことを表示するにはどうしたらいいんだろうyosider
Promise.all()で全ての fetch が終わるのを待ったあと、itemsの数を数えればできそう
すぐ思いつくのは、DOMの数を数える方法
もしかしたらitemsを数えるためのmethodがあるかもしれない
smartphoneからcodingすることになるとは考えもしなかったtakker
つよすぎyosider
ちょっとした修正なら簡単(狂気)takker
動いたyosider
consoleに404が何個も出てしまうのが気になるかもyosider
extraProjectにページが存在しない時に出る
run2.js
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 && !lines[1]?.text) return false; // タイトルを除いて1行以内かつ1行目が空のとき、空ページだと判断する menu.addItem({ title: `/${project}/${scrapbox.Page.title}`, onClick: () => window.open( `https://scrapbox.io/${project}/${scrapbox.Page.title}` ), }); return true; }

JavaScript
MDN
Qiita