generated at
他のプロジェクトにページを送るUserScript
現在開いているページのJSONデータをexportして、指定したプロジェクトにPOSTしてimportするUserScript
importするので自分がproject ownerであるプロジェクトにしか送れない
日の回数制限あるし動作重いので、頻用はオススメしないですyosider
用途
private project下書きページpublic projectにアップロードする
publicプロジェクトのページをテロメアごとprivateプロジェクトにコピーする
特徴
同名のページが既にある場合、追記ではなく上書きされる
送り元ページのテロメアが維持される
公開したことを示すタグを送り元ページにつける機能
タグよりも送り先のURLを貼るべき?
そうした
公開してはいけないことを示すタグがついていたら公開しない事故防止機能
課題
ページのタイトル変更を検知できない
古いタイトルのページを手動で消す必要
古いリンクを手動で修正する必要
送り先プロジェクトを選べるようにする
ワンクリックで出来たほうが良いかと思い送り先を定数にしたが、そんなにポイポイ実行する感じでもないのでワンクリックじゃなくていい気がしてきた
リンク先のページもimportできると便利?
想定外の上書きが起こらないようにしたい

cf.

importする場合は、以下の script.js 自分のページにコピーして引数を編集してください
(誤)アイコン画像URLはCORBにより gyazo.com/xxx を使えない(泣)
サムネイルの i.gyazo.com/xxx.png など、画像を直接指すURL(最後が .png とかで終わるURL)は使える
サムネイルは https://gyazo.com/ で画像を開いて画像アドレスをコピーすると取得できる
(正) gyazo.com/xxx/raw なら良い
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
なるほど、こうすれば名前付き引数みたいにできるのかyosider
した
引数
project:送り先プロジェクトの(URL上の)名前
privateTag:非公開のページに付けるタグ(#は除く, 不要なら'')
image:アイコン画像URL
useSendingMark:送り元ページに送り先へのリンクをつけるか( sent to [$target] )
useReferenceMark:送り先ページに送り元へのリンクをつけるか( from [$src] )

更新履歴
2021-01-04 公開したことを示すタグ( publicTag )を廃止し、代わりに送り先ページへのリンクをつけるようにした
ファイル名を変更
送り先ページへのリンクの前に"sent to"をつけるようにした
TODO: 選べるようにする done
引数 link_to を追加して、送り先ページへのリンクをつけるか選べるようにした
送り元のページ末尾に sent to [$target]
引数 link_from を追加して、送り元ページへのリンクをつけるか選べるようにした
送り先のページ末尾に from [$src]
pageTitle / が入っている場合に対応
その他いろいろrefactoring
refactoring
関数で抜き出して、indentを浅くした
objectで変数を受け取るように変更
引数名を変更
targetProjectName→project
targetUserName→廃止
link_to→useSendingMark
lint_from→useReferenceMark
定数を変更
既存のsending marker, reference markerを探すのに正規表現を使用するようにした
本文中に(markerではない形で)送り先ページへのリンクがある場合に消されなくなった

以下ソースコード
script.js
export const sendPage = ({image, ...rest}) => scrapbox.PageMenu.addMenu({ title: `send to ${rest.project}`, image: image, onClick: () => _sendPage({...rest}), });

script.js
async function _sendPage({project, privateTag, useSendingMark, useReferenceMark}) {

このくらいの変数であれば、直に書いたほうがわかりやすい気もするtakker
まあそうかyosider
page title以外消しました
script.js
const pageTitle = scrapbox.Page.title; const ePageTitle = encodeURIComponent(scrapbox.Page.title);

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解決済み
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()));
やっていること
sb
line 1 line 2 [/${project}/${pageTitle}] end line 3 [/${project}/${pageTitle}] line 4
sb
line 1 line 3 line 4
に変換してからexportする
何を目的としてやっているのかがいまいち推測できない
以前に送ったページを再度送る(上書きする)ときに、 sent to とか from の行が既にある場合、その行を消すための処理ですyosider
消さないと送り先にも sent to とか書かれてしまうため
下の len == json.lines.length の部分で、もし true なら、 sent to とか from の行がまだ無かったと考えて sent to を書いています
本文中に/${project}/${pageTitle}が現れていたらそれも消えてしまう
未対応
なるほどtakker
応急処置として、削除する行を sent to だけに絞るとよさそう
js
json.lines = json.lines.filter(line => !line.text.includes(`sent to[/${project}/${pageTitle}]`));
一応 from の場合もありますyosider
正規表現でいろいろ指定するのもあり
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 to or from の後にスペースが…
いれました
なぜかマッチしない…yosider
RegExp内では \ を二重にしないといけなかったみたいtakker
↓をconsoleに貼り付けて確認しました
js
(()=>{ const project = 'takker'; const pageTitle = 'foo/bar\\baz'; const regExp = new RegExp(`(?:sent\\sto|from)\\s\\[\\/${project}\\/${pageTitle.replace(/[.*+?^=!:${}()|[\]\/\\]/g, '\\$&')}\\]`); console.log(regExp); })();
へえ〜

jsonExport pages だけで十分ですtakker
ほかは必要ありません
消しましたyosider
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
知らなかった
へーsta
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"); } }


公開停止すべき…?yosider
/forum-jp/プロジェクトの削除にもう一段階確認が欲しい#5ff1ae511280f000001541baで伏せた方法に必要な鍵がこのコードなんですよね
つまりこの部分さえわかれば、任意のprojectを削除するよう仕向けるコードを挿入することができるようになります
流石にやばいので、/villagepump/Scrapboxの裏技では伏せていたんです
少なくともproject削除にreCAPTUREかなにかが実装されるまでは伏せておくつもりでした
ちなみにtakkerが見つけた方法はこれとはちょっと違ってたりする
この人が書いてるからいいかなと思って公開している部分もある
この人知らなかったtakker
一年前にもうわかっていたことだったのか
やはりscrapbox projectは見つけにくい
それがいいんだけど
yosiderもこのUserScriptを書くときには知らなくて、 index.js から頑張って探した
相当労力かかってそうtakker
でも検索使えるから、それほどでもない?
yes
X-CSRF-TOKENの取得方法です
window._csrf なんてあるの知らなかったので別の回りくどい方法を使っていました
tokenの存在は/nishio/ScrapboxのJSONをマージしたいから知ったyosider
そのページあったの忘れてたtakker