他のプロジェクトにページを送るUserScript
現在開いているページのJSONデータをexportして、指定したプロジェクトにPOSTしてimportするUserScript
importするので自分がproject ownerであるプロジェクトにしか送れない
日の回数制限あるし動作重いので、頻用はオススメしないですyosider.icon
用途
private projectの下書きページをpublic projectにアップロードする
publicプロジェクトのページをテロメアごとprivateプロジェクトにコピーする
https://gyazo.com/880af28d69fb9851d4993c55062f109f
特徴
同名のページが既にある場合、追記ではなく上書きされる
送り元ページのテロメアが維持される
公開したことを示すタグを送り元ページにつける機能
タグよりも送り先のURLを貼るべき?
そうした
公開してはいけないことを示すタグがついていたら公開しない事故防止機能
課題
ページのタイトル変更を検知できない
古いタイトルのページを手動で消す必要
古いリンクを手動で修正する必要
ScrapboxのPOST系APIの上限がある!
送り先プロジェクトを選べるようにする
ワンクリックで出来たほうが良いかと思い送り先を定数にしたが、そんなにポイポイ実行する感じでもないのでワンクリックじゃなくていい気がしてきた
scrapbox.PageMenu.addItem()を使う
リンク先のページもimportできると便利?
cf. /takker/telomereを維持して別projectにページをexportするUserScript
想定外の上書きが起こらないようにしたい
cf.
/shoya140/Scrapboxの下書きプロジェクトを作る
/customize/特定のページのみを含んだexport用dataを生成するbookmarklet
importする場合は、以下のscript.jsを自分のページにコピーして引数を編集してください
UserScriptの危険性
(誤)アイコン画像URLはCORBによりgyazo.com/xxxを使えない(泣)
サムネイルのi.gyazo.com/xxx.pngなど、画像を直接指すURL(最後が.pngとかで終わるURL)は使える
サムネイルは https://gyazo.com/ で画像を開いて画像アドレスをコピーすると取得できる
(正)gyazo.com/xxx/rawなら良い
code:import.js
import {sendPage} from '/api/code/programming-notes/他のプロジェクトにページを送るUserScript/sendpage.js'
sendPage({
project: 'your project',
privateTag: 'private',
image: 'https://gyazo.com/d68f429b8e8a1dd68504506262bcd05c/raw',
useSendingMark: true,
useReferenceMark: false,
});
objectで変数を受け取るようにしたほうがわかりやすいと思いますtakker.icon
なるほど、こうすれば名前付き引数みたいにできるのかyosider.icon
した
引数
project:送り先プロジェクトの(URL上の)名前
privateTag:非公開のページに付けるタグ(#は除く, 不要なら'')
image:アイコン画像URL
useSendingMark:送り元ページに送り先へのリンクをつけるか(sent to [$target])
useReferenceMark:送り先ページに送り元へのリンクをつけるか(from [$src])
更新履歴
2021-01-04 公開したことを示すタグ(publicTag)を廃止し、代わりに送り先ページへのリンクをつけるようにした
2021/1/5
ファイル名を変更
送り先ページへのリンクの前に"sent to"をつけるようにした
TODO: 選べるようにする done
2021/1/12
引数link_toを追加して、送り先ページへのリンクをつけるか選べるようにした
送り元のページ末尾にsent to [$target]
引数link_fromを追加して、送り元ページへのリンクをつけるか選べるようにした
送り先のページ末尾にfrom [$src]
pageTitleに/が入っている場合に対応
その他いろいろrefactoring
2021/1/25
refactoring
関数で抜き出して、indentを浅くした
2021/1/26
objectで変数を受け取るように変更
引数名を変更
targetProjectName→project
targetUserName→廃止
link_to→useSendingMark
lint_from→useReferenceMark
定数を変更
既存のsending marker, reference markerを探すのに正規表現を使用するようにした
本文中に(markerではない形で)送り先ページへのリンクがある場合に消されなくなった
引数分割束縛を使用
以下ソースコード
code:script.js
export const sendPage = ({image, ...rest}) => scrapbox.PageMenu.addMenu({
title: send to ${rest.project},
image: image,
onClick: () => _sendPage({...rest}),
});
code:script.js
async function _sendPage({project, privateTag, useSendingMark, useReferenceMark}) {
このくらいの変数であれば、直に書いたほうがわかりやすい気もするtakker.icon
まあそうかyosider.icon
page title以外消しました
code:script.js
const pageTitle = scrapbox.Page.title;
const ePageTitle = encodeURIComponent(scrapbox.Page.title);
code:script.js
const response = await fetch(/api/pages/${scrapbox.Project.name}/${ePageTitle});
let json = await response.json();
// ページにprivateTagがついている場合はエラー
if (privateTag && json.links.includes(privateTag)) {
const msg = This page contains #${privateTag}!\nAborted.;
alert(msg);
throw new Error(msg);
}
この処理の意図がわからないですtakker.icon解決済み
code:script.js
// 送り先ページへのリンクを含む行があれば消してから送る
const len = json.lines.length; // 送り先ページへのリンクの有無の判定に使う
//json.lines = json.lines.filter(line => !line.text.includes([/${project}/${pageTitle}]));
const regExp = new RegExp((?:sent\\sto|from)\\s\\[\\/${project}\\/${pageTitle.replace(/[.*+?^=!:${}()|[\]\/\\]/g, '\\$&')}\\]);
json.lines = json.lines.filter(line => !regExp.test(line.text.trim()));
やっていること
code:sb
line 1
line 2 /${project}/${pageTitle} end
line 3
/${project}/${pageTitle}
line 4
を
code:sb
line 1
line 3
line 4
に変換してからexportする
何を目的としてやっているのかがいまいち推測できない
以前に送ったページを再度送る(上書きする)ときに、sent toとかfromの行が既にある場合、その行を消すための処理ですyosider.icon
消さないと送り先にもsent toとか書かれてしまうため
下のlen == json.lines.lengthの部分で、もしtrueなら、sent toとかfromの行がまだ無かったと考えてsent toを書いています
本文中に/${project}/${pageTitle}が現れていたらそれも消えてしまう
未対応
なるほどtakker.icon
応急処置として、削除する行をsent toだけに絞るとよさそう
code:js
json.lines = json.lines.filter(line => !line.text.includes(sent to[/${project}/${pageTitle}]));
一応fromの場合もありますyosider.icon
正規表現でいろいろ指定するのもあり
code:js
const regExp = new RegExp((?:sent\\sto|from)\\s\\[\\/${project}\\/${pageTitle.replace(/[.*+?^=!:${}()|[\]\/\\]/g, '\\$&')}\\]);
json.lines = json.lines.filter(line => !regExp.test(line.text.trim()));
たぶんこれでうまく行く(未確認)
sent toorfromの後にスペースが…
いれました
なぜかマッチしない…yosider.icon
RegExp内では\を二重にしないといけなかったみたいtakker.icon
↓をconsoleに貼り付けて確認しました
code:js
(()=>{
const project = 'takker';
const pageTitle = 'foo/bar\\baz';
const regExp = new RegExp((?:sent\\sto|from)\\s\\[\\/${project}\\/${pageTitle.replace(/[.*+?^=!:${}()|[\]\/\\]/g, '\\$&')}\\]);
console.log(regExp);
})();
/icons2/へえ〜.icon
こういう風にコードにたくさん書き込みしていくと可読性が下がる気がしてしまう…
jsonExportはpagesだけで十分ですtakker.icon
ほかは必要ありません
消しましたyosider.icon
code:script.js
const jsonExport = { pages: json };
let formdata = new FormData();
formdata.append(
'import-file',
new Blob(JSON.stringify(jsonExport), { type: 'application/json' })
);
await fetch(/api/page-data/import/${project}.json, {
method: 'POST',
headers: { 'X-CSRF-TOKEN': window._csrf },
body: formdata,
});
テンプレート文字列って入れ子にできたんだtakker.icon
知らなかった
へーsta.icon
code:script.js
// 送り先ページを開く
// 送り元ページへのリンクが必要ならつける
if (useReferenceMark) {
window.open(https://scrapbox.io/${project}/${ePageTitle}?body=${encodeURIComponent(from /${scrapbox.Project.name}/${pageTitle}\n)});
} else {
window.open(https://scrapbox.io/${project}/${ePageTitle});
}
// 送り先ページへのリンクが必要ならつける
if (useSendingMark && len == json.lines.length) { // リンクの行を消す前と行数が同じならリンクが無いとする
window.open(https://scrapbox.io/${scrapbox.Project.name}/${ePageTitle}?body=${encodeURIComponent(sent to /${project}/${pageTitle}\n)}, "_self");
}
}
Scrapboxでプログラミング
公開停止すべき…?yosider.icon
他のプロジェクトにページを送るUserScript#5ffc832de5172d0000d369dbのコードが問題かもtakker.icon
/forum-jp/プロジェクトの削除にもう一段階確認が欲しい#5ff1ae511280f000001541baで伏せた方法に必要な鍵がこのコードなんですよね
つまりこの部分さえわかれば、任意のprojectを削除するよう仕向けるコードを挿入することができるようになります
流石にやばいので、/villagepump/Scrapboxの裏技では伏せていたんです
少なくともproject削除にreCAPTUREかなにかが実装されるまでは伏せておくつもりでした
/forum-jp/プロジェクトの削除にもう一段階確認が欲しい#5ff2c43c97c2910000994ddf
ちなみにtakker.iconが見つけた方法はこれとはちょっと違ってたりする
/ras/非公式なscrapboxのAPIを叩く#5db25d0cd0d23600004de7ad こちらとかですか…?yosider.icon
この人が書いてるからいいかなと思って公開している部分もある
この人知らなかったtakker.icon
一年前にもうわかっていたことだったのか
やはりscrapbox projectは見つけにくい
それがいいんだけど
yosider.iconもこのUserScriptを書くときには知らなくて、index.jsから頑張って探した
相当労力かかってそうtakker.icon
でも検索使えるから、それほどでもない?
/emoji/yes.icon
X-CSRF-TOKENの取得方法です
window._csrfなんてあるの知らなかったので別の回りくどい方法を使っていました
tokenの存在は/nishio/ScrapboxのJSONをマージしたいから知ったyosider.icon
そのページあったの忘れてたtakker.icon
#下書きプロジェクト #ブログ
#export
#UserScript UserScript.icon