リンク,被リンクを区別して表示するUserScript
標準の Links 表示では、現在ページがリンクしているページと、現在ページにリンクしているページが混在します(※)。
本スクリプトでは、それらを区別して表示します。
実装
本スクリプトは、ページメニューに「リンク関係」という項目を追加します。
この項目を選択すると現在ページに対するリンクとバックリンクが一覧で表示されます。
表示された項目を選択すると、該当するページへ移動します。
リンクは、現在ページの本文中に明示的に書かれているリンク先です。相互リンクの場合も、ここに含まれます。
バックリンクは、現在ページの本文には書かれていないが、他のページの本文から現在ページへリンクされているものです。
プログラム
仕組み
/api/pages/:project/:titleを使用しています。この API から取得できる links は、現在ページの本文リンクです。
またrelatedPages.links1hopは、リンクと被リンクが混在した関連ページの集合であり、バックリンク候補を絞り込むために使っています。
実装上の限界
被リンクのみを直接取得する API が存在しないため、まず relatedPages.links1hop を候補集合とし、その中の各ページについて、相手ページの links に現在ページが含まれているかを確認することで、バックリンクを判定しています。
このため、relatedPages.links1hop に含まれないページは対象になりません。
また、候補ページ数に応じて追加の API アクセスが発生します。
プログラム本体
code:script.js
(function () {
scrapbox.PageMenu.addMenu({
title: 'リンク関係',
onClick: async () => {
const menu = scrapbox.PageMenu('リンク関係')
menu.removeAllItems()
const project = scrapbox.Project.name
const title = scrapbox.Page.title
// 1) 自ページ取得(links と relatedPages.links1hop を使う)
let self
try {
const res = await fetch(/api/pages/${project}/${encodeURIComponent(title)})
self = await res.json()
} catch (e) {
console.warn('failed to fetch self page', e)
return
}
const outPages = new Set(self.links || [])
// 関連ページ(リンク+被リンクが混在する候補集合)
const candidates = new Set(
(self.relatedPages?.links1hop || []).map(p => p.title)
)
// 2) 分類:リンク(相互リンクもここに含める)
// 3) バックリンク:自分はリンクしていないが、相手が自分にリンクしている
const backlinks = []
for (const page of candidates) {
if (outPages.has(page)) continue // 自分がリンクしてるなら「リンク」側
try {
const res = await fetch(/api/pages/${project}/${encodeURIComponent(page)})
const json = await res.json()
if ((json.links || []).includes(title)) {
backlinks.push(page)
}
} catch (e) {
console.warn('failed to check backlink:', page, e)
}
}
// 4) 表示
addSection(menu, 'リンク', links, project)
addSection(menu, 'バックリンク', backlinks, project)
}
})
function addSection(menu, label, pages, project) {
if (!pages || pages.length === 0) return
menu.addItem({ title: 【${label}】(${pages.length}), onClick: () => {} })
pages.forEach(page => {
menu.addItem({
title: ' ' + page,
onClick: () => {
location.href = /${project}/${encodeURIComponent(page)}
}
})
})
}
})()