マルチプロジェクト版ランダムジャンプUserScript
概要
ランダム表示のマルチプロジェクト版
1. プロジェクトのリストのCSVファイル群の中から、ランダムにひとつを選択する
2. CSVファイルからプロジェクトをランダムにひとつ取り出す
3. プロジェクトの中から、ページをランダムにページを選ぶ
4. ページを表示する
ファイル仕様(暫定)
テーブル表記
Scrapboxのテーブル記法
1カラム目がプロジェクト名
プロジェクト名は、 [/$ProjectName]
という書式
ファイルを分割して表記も可能
2カラム目以降は無視される
2カラム目以降には何を書いてもよい
たいていは、1カラム目のプロジェクト名の補足説明になる
テーブルには、有効な プロジェクト名がふたつ以上必要
ファイル名
ファイル名は任意
projects.csv(全部小文字)を推奨
API ではファイル名は大文字、小文字を区別するので
注意が必要大文字、小文字の混ざったファイルは作らないことを推奨
書式のエラー処理
基本的にエラーは無視する
書式外のカラムは無視される
スクリプト
script.js const choice = (arr) => arr[Math.floor(Math.random()*arr.length)]
const sources = [
'/api/table/villagepump/おもしろいScrapboxみつけた/projects.csv',
'/api/table/villagepump/マルチプロジェクト版ランダムジャンプUserScript/projects.csv',
'/api/table/suto3/suto3/projects.csv'
]
script.js const lists = new Promise((resolve, reject) => {
// 情報源をひとつ選ぶ
const projects_url = choice(sources)
現状では
情報源を選ぶ
という形式になっているけど、ランダム選択をやるのが二度手間なので
情報源から全てのプロジェクト名を取り出してリストを作る
リストの中からプロジェクトをランダムに選ぶ
に変えてもいいかもしれないです
これでどうだろう?
fetch_project_url.jslet project_lists=[];
const fetch_project_url= (source) =>
fetch(source)
.then(response => response.text())
.then(text => text.split('\n')
.map(line => line.split(','))
// column 1にプロジェクトリンクが入っているもののみ取り出す
.filter(cells => /^\[\/[^\s\]\/]*\]$/.test(cells[0]))
// [/project]からprojectを抜き出す
.map(cells => cells[0].replace(/^\[\/([^\s\]\/]*)\]$/,'$1')))
// 非同期にprojectをリストに追加する
.then(project_names => project_lists.push(...project_names));
sources.forEach(source => fetch_project_url(source));
あとは project_lists
から適宜取り出す
ふむふむ
ページタイトルの読み込みはこれを使うのはどうだろう
手前味噌ですが
script.js //const projects_url = '/api/table/suto3/suto3/projects.csv' // debug
console.log(projects_url)
fetch(projects_url)
.then(response => response.text())
.then(text =>
text.split('\n')
.map(line => line.replace(/^,/,"")) // 行頭のコンマがあった場合は削除
.join('\n') )
.then(resolve)
.catch(reject)
})
script.js scrapbox.PageMenu.addItem({
title: 'ランダムジャンプ',
onClick: async () => {
await lists.then((text) => {
const urls = text.split("\n")
.map( line => {
console.log(line)
const regexp = /^\[\/.*\]$/gm
const res = line.split(',')
// 書式チェック
if (regexp.test(res[0])) {
const url = res[0].replace(/\[|\]/g,"")
//console.log(url)
return url
} else {
console.log('NG')
return
}
})
.filter(line => line)
//console.log(urls)
const project = choice(urls)
//console.log(project)
const limit = 100
let skip = 0
const url =`/api/pages${project}?limit=${limit}&skip=${skip}`
fetch(url)
.then((response) => response.json())
.then((json) => {
//console.log(json)
const pagetitle = choice(json.pages.map(page => page.title))
console.log(pagetitle)
window.open(`https://scrapbox.io${project}/${pagetitle}`)
}).catch(err => {
console.error('fetch failed', err)
})
})
}
})
既知の問題点
吹いたw
テーブル内部では、使えない記法がある
アイコン記法
外部リンク
など
検索除外のしくみがない
/api/pages/$projectname/$page/text
を
正規表現で走査して弾くとか?
データチェックとかエラーチェックとか
ジャンプ先のプロジェクトから再ジャンプができない