参加している他のprojectに同じページがあったら教えてほしい
project横断検索でもできるが、タイトルをコピーして検索→横断検索→projectに移動→pageに移動とやや手間 ページを作るときだけじゃなくていいか
自分が参加しているprojectだけじゃなく、各自でprojectを指定できるようにしたほうがいい?
参加していないprojectも入れるなら、同じタイトルのページを取得するより、似たタイトルのページを検索した方がいい?
実装
PageMenuのボタンを押したら、検索して同名ページへのリンク一覧をItemとして出すとか?
指定したプロジェクトの同名ページをfetchし、status codeが200ならmenuにappendする?
code:run.js_(js)
for (const project of projects) {
.then((response) => {
console.log(response.ok)
if(response.ok==true){
}
}
)
}
参加しているプロジェクトだと、ページが存在せずともtrueになって開いてしまう
404じゃないからか
status codeを利用しないで処理しよう
window.open()
きれいに1つずつ開けない気がする
2つ以上開いてしまうことがある
code:run.js__(js)
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するか?
code:run.js
scrapbox.PageMenu.addMenu({
title: "OtherProjects",
});
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}
),
});
}
});
}
できたぁ〜〜dnin.icon*3
今度は押したときに実行するようにするか
手直ししてみたtakker.icon
response.okと行数で判断する
押すたびにページを取得し直す
fetchを待たない
参加しているprojectすべてから検索する
https://gyazo.com/0e17f17bf495aaa983a08e8e12bd441e https://gyazo.com/0e17f17bf495aaa983a08e8e12bd441e.mp4
試し方
code:js
(async () => {
const {execute} = await import('/api/code/programming-notes/参加している他のprojectに同じページがあったら教えてほしい/run2.js');
})();
code:run2.js
const id = "OtherProjects";
export async function execute(extraProjects = []) {
const response = await fetch('/api/projects');
const json = await response.json();
code:run2.js
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)) return;
menu.addItem({ title: 'No page found.', onClick: () => {} });
},
});
}
forEachはPromiseを待ってくれないことを利用?yosider.icon
forloopでも同じことできます
code:.js
for (const project of projects) {
addItem(project);
}
特に待つ必要もないので、awaitしなかっただけですtakker.icon
/icons/なるほど.iconyosider.icon
ヒットするページでクリックした後、ヒットしないページでクリックすると、前のページでの結果が残ったままになるyosider.icon
仕様なのか…?
emitChange()を追加したら直った
調査していただき感謝ですtakker.icon
変だなあと思いつつ放置してた
確かに直感とは違う挙動ではある
1つもヒットしなかったら「見つかりませんでした」的なことを表示するにはどうしたらいいんだろうyosider.icon
すぐ思いつくのは、DOMの数を数える方法
もしかしたらitemsを数えるためのmethodがあるかもしれない
smartphoneからcodingすることになるとは考えもしなかったtakker.icon
つよすぎyosider.icon
ちょっとした修正なら簡単(狂気)takker.icon
動いたyosider.icon
consoleに404が何個も出てしまうのが気になるかもyosider.icon
extraProjectにページが存在しない時に出る
code: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 && !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;
}
JavaScript.icon
MDN.icon
Qiita.icon