AiScriptについて調べる
フォームクリアプラグインを作る
スマホ版のPWAで投稿フォームのテキスト全文を消すのに、フォームクリアのメニューがなかったのでプラグインで追加したく思いAiScriptの調査開始。サンプルのプラグインのコードを少し変更するだけで動作するフォームクリアプラグインは作成できた。
フォームクリアプラグインのソースコード
/// @ 0.12.4
### {
name: "フォームクリア"
version: "0.0.1"
author: "ツッナ"
}
Plugin:register_post_form_action('フォームクリア', @(note, rewrite) {
rewrite('text', '')
})
このコードを設定のプラグインのインストールのコンソールに貼り付けてインストールすればインストール完了。
情報源など
このページでは投稿フォームにふぐパンチボタンを追加するハンズオンが紹介されている。
ふぐパンチボタンはフォームのテキストエリアの内容を"フグパンチ"で書き換える処理になっているので、"フグパンチ"を空文字にして、ついでに条件分岐もなくしてやれば完成。
なお、私は最初に以下のページのPlugin:register_post_form_action(title, fn)
の見本をプラグインフォームに直接貼り付けてインストールしようとしてエラーになった。メタ情報部分の記述は必須の模様。
インストール済みのパネルでプラグイン名等を使用するためだと思われる。
また、AiScriptのメタデータ構文というものらしく、グローバル領域専用で使える模様。
その他気になった点
-
Plugin:register_post_form_action
関数の第二引数はコールバック関数(とやら)らしい。- コールバック関数の第一引数
note
はMisskey側のオブジェクトを受け取っているような挙動-
note
が具体的にどのようなプロパティ(パブリック変数?)を持っているかはドキュメントの記載を見つけられていない - Misskey側のこのあたりのオブジェクトをAiScriptに渡しているんじゃないかと推測している
- packages/backend/src/models/Note.ts
- どうやってそのオブジェクトやらパラメータをAiScriptに渡しているのかはわからない。理由は私の知見不足。
- そのうえTypeScript未経験なので余計になんもわからん。
-
rewrite
関数も同様にMisskey側に定義されているのではないかと推測しています - このあたりも調査してコードレベルで記事にしたい所存
-
- コールバック関数の第一引数
- MisskeyのAiScript独自定義パラメータ等は以下に条件文として定義されているのでこのあたりな気がする
-
Ui:C:*
類 packages/frontend/src/scripts/aiscript/ui.ts -
Mk:*
類 packages/frontend/src/scripts/aiscript/api.ts -
Plugin:*
類 がどこにあるのかはまだ見つけられていない。
-
- PCのブラウザ側からプラグインをインストールしたところスマホのPWAアプリ側ではプラグインが有効にはなっていなかった。次の項目については調査が必要。
- UIの設定を保存して読み込めば共通化されるのか
- ドライブにテキストを保存してコードを貼り付けるのか
- Misskey API等を効果的に使えば楽にインストール・配布ができるのか
AiScript関連の情報
Misskey側
- Misskey Hubの開発者向け情報
- Misskeyのリポジトリ内のAiScriptディレクトリ
AiScript側
- AiScript(言語自体)のリポジトリ
- AiScriptのドキュメントディレクトリ
- https://github.com/aiscript-dev/aiscript/tree/master/docs
- builtin-props.md:組み込みプロパティ(個人的には標準関数的な解釈。変数じゃなく処理も持っているので)
- ここにlenやto_strのような関数の記述がある
- get-started.md:スタートガイド/基本的文法など
- ここをざっと見れば制御構文、変数宣言の記法等をざっくり把握できる
- 詳細な文法等(個人的に把握しておきたい部分)
- literals.md:変数等の宣言、定義詳細について。
- syntax.md:具体例を上げた詳細な記法説明。
- std.md:標準関数。入出力や日付、システム系の関数がある認識。
VSCodeでAiScriptをシンタックスハイライトしたい
VSCodeのMarketplaceにはaiscript-devから配布されているシンタックスハイライト等開発補助プラグインはなさそうな感じ。
なので公式のリポジトリaiscript-dev/aiscript-vscodeのHow-to-Installに従って、release pageから.vsix
ファイルをダウンロードして、vscodeに直接拡張機能をインストールする。
aiscript-vscode-x.x.xx.vsix
をダウンロードして任意の場所に保存。
1. release pageの[Assets]の部分をクリックして開いて、2. vscode上で[Extensions]→[...]→[Install from VSIX...]を選択して、ダウンロードした.vsixファイルを選択する
デバッグはMisskey本体のスクラッチパッドから。本来はローカルに鯖立てするか、コンソール実行可能なように環境を整備したほうが良いのだろうけれど、今回は面倒なのでスキップ。
AiScriptで@Str:Concat(str1, str2)
とかstr1.concat(str2)
、あるいはstr1 + str2
みたいなことできへんかなぁとMisskeyでぼやいていたら有識者の方にご教示いただいた。ありがとうございます。原文ママ転記します。
var new_str = `{str_a}普通の文字列{str_b}`
Misskey用 突然の死ジェネレータプラグイン
いったん突然の死ジェネレータプラグインが完成した。普通に使う分には問題なさそう。
半角英数記号と半角カナの考慮も少し入れているけれど細かい部分はそこまでちゃんと作れていないと思うので、大まかに囲った後は手で文字を修正してくださいな。
実装
/// @ 0.16.0
### {
name: "突然の死"
version: "0.0.1"
author: "ツッナ"
description: "フォームに入力済みの文字列を突然の死フォーマットで囲います。"
}
/*
引数`form_text`に渡された文字列の周囲を突然の死の記号で囲った文字列を返す関数。
form_text: str
記号で囲う対象文字列。フォームのテキストエリアに入力済みの文字が渡されることを想定。
return: str
突然の死のフォーマットで囲った文字列。Str:lfで改行し複数行の文字列を返す。
*/
@surround_with_symbols(form_text) {
var contents = []
// 複数行ある場合に長い方の文字列長を選択するための処理
let lines = form_text.split(Str:lf)
var num_of_brackets = -1
each let line, lines {
let current = get_num_of_brackets(line)
num_of_brackets = Math:max(num_of_brackets, current)
contents.push(`> {line} <`)
}
// 突然の死の囲い記号を長い文字列長基準で構成する
var header = `_人{["人"].repeat(num_of_brackets).join()}人_`
var footer = ` ̄Y^{["Y^"].repeat(num_of_brackets).join()}Y ̄`
contents.unshift(header)
contents.push(footer)
return contents.join(Str:lf)
}
/*
フォームに入力済みの文字列長を計測して突然の死の囲い記号の幅を返す関数。
input_line: str
入力フォームに記入済みの1行文の文字列。
half_char_width: num(浮動小数点数値)
半角英数記号と半角カナのマルチバイト文字に対する文字幅。
初期値0.5で2文字でマルチバイト文字1文字分とする。
return: num(整数値)
入力文字から得られた突然の死の囲い記号の必要数。
*/
@get_num_of_brackets(input_line) {
// strの文字列を10進数でutf-16コード化
let charcodes = input_line.to_charcode_arr()
var total_len = 0.0
each let c, charcodes {
if (is_multibyte_char(c)) {
total_len += 1.0
} else {
total_len += 0.5
}
}
return Math:trunc(total_len)
}
/*
引数に与えられた10進数表記のutf-16の文字コードが半角英数記号または半角カナの範囲かを判定する関数。
charcode: num
事前に`str.to_charcode_arr()`で10進数値化されたutf-16文字コードの数値配列の1要素。
return: bool
半角英数記号または半角カナに適合した場合falseを返す。
それ以外の場合をすべてマルチバイト幅文字と判定してtrueを返す。
*/
@is_multibyte_char(charcode) {
// 半角文字判定
if (charcode >= 33 && charcode <= 126) { return false } // 半角英数字の範囲(Unicode: 0x21 から 0x7E)
if (charcode >= 65377 && charcode <= 65439) { return false } // 半角カナの範囲(Unicode: U+FF61 から U+FF9F)
// 上記以外(マルチバイト幅の文字)の場合trueを返す
return true
}
Plugin:register_post_form_action('突然の死', @(note, rewrite) {
rewrite('text', surround_with_symbols(note.text))
})
気になったポイント
- 関数の引数初期値代入構文が使えない?
- 半角文字の加算値を0.5を初期値に持った引数にしようと思ったのですけれど、スクラッチパッドとプラグインではうまく動かせなかった。
- 簡単な初期値構文を持つスクリプトを書いて要検証。
- 半角文字の加算値を0.5を初期値に持った引数にしようと思ったのですけれど、スクラッチパッドとプラグインではうまく動かせなかった。
- メタデータ
###{}
内のdescription
を改行させることはできない?- descriptionの説明文を区切りの良いところで改行したかったけれど、
Str:lf
を`で囲ったリテラルも\n
も改行として使えなかった。 - descriptionのパラメータを2つ記述してみたら後の分で上書きされた(そらそう)
- 回避策はないかもしれないやつ?
- descriptionの説明文を区切りの良いところで改行したかったけれど、
- 1文字単位で文字をutf-16の文字コード(10進数)に変換する関数がなさそう?
- 個人的な実装の好み的に、
@is_multibyte_char()
の中でstrをcharcodeに変換する処理を書いたほうが良いかなと思ったけれど、str.to_charcode_arr()
までしか見つけられなかったので@get_num_of_brackets()
でコード化する実装になった。 - 単一文字でコードに変換したい、みたいのは実装で回避できる問題だから不要って判断なのかもしれない。
- 個人的な実装の好み的に、
配布方法
プラグイン・テーマを配布する でリソース配布用API(URL?)を作成する方法が紹介されている。
実際この方法をするなら以下記事を参考にしてドライブにファイルをアップロードしてPlayとかからインストールボタンを作成するのが一番手軽そうではある。
MisskeyのPluginやThemeをMisskeyの機能のみを活用して配布する #misskey - Qiita
ただそこまでする必要もないかなとも思うので、
- zennの説明兼配布用記事を作成する
- Misskey Pagesを作成して共有する
の2つで、Misskeyでノートを共有投稿までにしようと思う。
ノートの詳細メニューからページに直接ノートを埋め込むプラグインをつくる
ノートの詳細メニューにプラグインを追加するコード。
参考:Plugin:register_note_action(title, fn)
Plugin:register_note_action('このノートをページに追加する', @(note) {
let all_pages = Mk:api('users/pages', {
userId: USER_ID
})
})
Misskey APIの挙動調査
使いたいエンドポイント