generated at
ScrapJupyter
コードブロックをその場で実行できるようにしたやつです
jupyter notebookみたいなのでScrapJupyterという名前にしてみました
機能をボタンでトグルできるようにしたのと、1行目がScrapJupyterだと自動でonになる
debug時に便利

UserScript作るときにとても便利ですmiyamonz
ほんと便利そうですtakkeryosider
開発コンソールで張り付けして実行するのは少し面倒
自分のページをいちいち書き換えるのは非常に面倒
importを使えば多少はましになるけど、reloadしないと新しいコードを実行できないのが面倒


よかったら使ってくださいmiyamonz
と言いたいところだが、evalなので自己責任で
evalってなんですのん??air34n
evil の活用形ですよU
一理あるyosider増井俊之takkerbsahd
eval() の存在自体がevilだ……
いやいやevaluationの略ですよtakker
任意の文字列をJavascriptと解釈して実行する関数です
文字列をJSとして評価(evaluate)して実行することなのですが、これは基本的に危険な行為ですmiyamonz
ユーザが入力した文字列をもしevalしたら、ユーザや第三者が悪さするかもしれないので
自分用に使うということですねU
一番安全なのはdynamic importなのですが、一度しか実行できないのが問題ですねtakker
あとimportだとファイル指定しないといけないmiyamonz
code:js って名前無しのブロックを指定できない問題があります
data URIでいけたりしませんかね?takker
いまスマホからスクボ書いているので当方では試せませんが
後で試してみます
だめでした

あとFunction()を悪用するevalのやつで置き換えようと思いますmiyamonz
もう少し詳しごく説明願えますか?takker
どういう目的でなにをしようとしているのかがよくわからないです
普通のjsのevalだとスコープの問題があって、
js
hoge = 1
これをevalしても、window.hogeに代入されないんですよねmiyamonz
明示的に window.hoge = 1 とかけば入れられはする
Functionでくくるやつはできるんじゃなかったのかなと思ってて
window に自動で追加することはできなかったはずですtakker
コードブロックをひとまとめにして変数のscopeをつなげるなら、増井俊之さんのこの方法があります
まじかー…miyamonz

と思ってたらこれでできた
(1,eval)('hoge = 1')
mjd 増井俊之
Function要らないん?
まじかtakker
まじ要らなかった 増井俊之

ブロックごとに実行できるのが便利なこともありますね 増井俊之
ScrapCalcとどう融合すればいいのかな
共存できるから融合する必要ないか
グローバル変数経由で共有できそうですねmiyamonz
後で試してみます
文中に変数をScrapCalcで入れつつ、長い計算やアルゴリズムをコードブロックで書いて実行、とか良さそう
あらゆるコードブロックに実行ボタンがついてしまう?
ScrapJupyter と書いたページだけてことか
コードブロックごとに指定できる方がいいかも?
現状jsだけで、かつ右のメニューのボタンを押さないと出てきませんmiyamonz
行頭に ScrapJupyter は、ボタンを押すのが面倒なときに使います
たとえばデバッグ時のリロードとか
on/offしなくてもあらゆるJSブロックに実行可能ボタンつけたい 増井俊之
自己責任だし、実行できるの自分だけだし
ここらへんを変えればよいはずですmiyamonz
const autoEnable = () => toggle(scrapbox.Page?.lines[1]?.text === title)
const autoEnable = () => toggle(true)
ScrapExecというのを作ってしまいました... 増井俊之
コードブロックは fetch してます
ファイル名があったらfetchで楽できるんですよねmiyamonz
ScrapJupyterで名前ないjsファイル扱いたくて無理やり文字列結合したのを思い出した

QuickJS-ecmascriptenでSandboxを作るのが一番堅牢そうtakker

お試しコーナー
js
alert(`Hello, Scrapbox!`);
ts
type User = { name: string; }; const res = await fetch("/api/users/me"); const { name }: User = await res.json(); alert(`Hello, ${name}!`);
js
必ず失敗するコード alert("failed");
js
throw Error("Unknown error has occurred.");
このprojectにいるmemberのリストを表示する
ts
type Project = { users: { name: string; }; }; const res = await fetch(`/api/projects/${scrapbox.Project.name}`); const { users }: Project = await res.json(); alert(`Project members list\n${users.map(({name}) => `\t${name}`).sort().join("\n")}`);
projectのページを閲覧数順に並び替える
ts
type PageList = { pages: { title: string; views: number; linked: number; pageRank: number; }[]; }; const res = await fetch(`/api/pages/${scrapbox.Project.name}?sort=views`); const {pages} = await res.json(); alert(`Analysis:\n\ntitle\tviews\tpage rank\tlinked\n${pages.map(page => `${page.title}\t${page.views}\t${page.pageRank}\t${page.linked}`).join("\n")}`)
Pin留めページはソート方法によらずに常に先頭に並べられるみたいtakker

UserScript