TAWAMIラボ

2023/01/19 ExtendScript

ExtendScriptについて知ってることをまとめた

InDesignにもとうとうUXPスクリプトの波がやってきて(※)、Illustratorにも間もなく来るんじゃないかということで、完全にオワコン(終わったコンテンツ)化する前にExtendScriptのことをまとめとこうと思い記事にしました。

※ InDesignのUXPスクリプト(.idjs)についてはUndoModeの指定ができないので、今のところあまり実用的ではないかなと思っています。しかしExtendScriptでできなかったhttps接続ができるようになったことから、Google Spread Sheetと連携するなど新しい試みをされている方もおられます。


資料とか

ExtendScriptに関する最も基本的な資料は、Adobe公式の「JavaScript Tools Guide CC.pdf」なのですが、今現在これをダウンロードできる場所はadobe.com内には見当たりません。(このことからもExtendScriptのオワコンぶりがよく分かります)

したたか企画さんのIllustratorスクリプトに関するまとめによれば、CEP関係のGitHubに残っているようです。ExtendScript Toolkitがインストールできる環境であれば、インストールしたフォルダのSDKフォルダ内にもあります。また、ググるとブラウザで見やすくしたものなども見つかります。(いずれも英語です)

日本語の資料としては、どなたが書かれたのか分からないのですが、http://scui.web.fc2.com/ でかなり詳細な調査がなされています。

また、ExtendScriptでダイアログボックス等を生成する機能である「ScriptUI」に関して、昔からあった詳細な資料「Beginning ScriptUI」を最近、ゆうさんが日本語に翻訳されました

ただしScriptUIはバージョン毎、アプリケーション毎に微妙に実装が異なり、必ずしも書いてある通りにはいきません。たとえばフォントの種類やサイズの変更は今は(CC2015あたりから?)できなくなっていたはずです。


言語仕様とか

ExtendScriptはJavaScriptの一種とされていますが、ウェブブラウザ等で使われているJavaScriptはどんどん進化してる一方、ExtendScriptはCS4→CS5のときほんのちょっと変わった(Math.maxが3つ以上の引数をとれるようになったりした)くらいなので、最近のJavaScript(ES6)では当たり前の機能でも、ExtendScript(ES3相当)では使えない場合が多々あります。
たとえばlet, const宣言(※)やアロー関数が使えない、ArrayのメソッドにindexOf、mapなどが無いとか。

また、古いJavaScript(ES3)になら正しく準拠しているかと言えば、そうとも言えません。

ということで、以下はExtendScriptとJavaScriptの違いを挙げていきます。(ほとんどは昔のブログの焼き直しです)

※ const宣言は一応あるが、ES6とは仕様が異なる。(後述)


ExtendScript独自の構文

  • #include #includepath #target #targetengine

ハッシュタグじゃなくプリプロセッサディレクティブというやつです。
参考:Adobe ExtendScriptのプリプロセッサディレクティブ - chalcedony_htnの日記
   #includeはどこに書いてもよく、コードの断片でもいい|ぼんぷろぐ

#の代わりに //@ を使うこともできます。こっちだとJavaScriptの構文チェッカーに怒られなくて済みます。

  • """でヒアドキュメント

"""(ダブルクォーテーションが3つ)で囲むとヒアドキュメント(改行などがそのまま有効な文字列)になります。

  • const宣言

変数名の前にconstをつけて定数宣言ができます。varとの違いは書き換えようとするとエラーが出ること。ブロック単位のスコープを作らないという点でES6のconstと異なります。

  • for each-in ループ

for-inがオブジェクトのプロパティ名でループするのに対し、for each-inはオブジェクトのプロパティの値でループします。

var obj={a:1,b:2,c:3},a1=[],a2=[]; for (var i in obj){ a1.push(i); } alert(a1); // a,b,c for each(var i in obj){ a2.push(i); } alert(a2); // 1,2,3

・演算子のオーバーロード

オブジェクトの四則演算や比較演算などを自分で定義することができます。
参考:Indiscripts :: Operator Overloading with ExtendScript


ExtendScript独自の機能

  • Reflectionオブジェクト

すべてのオブジェクトがreflectというプロパティを持っています。
中身はオブジェクト自身に関する情報が入ったReflectionオブジェクトで、reflect.nameでオブジェクトの種類を判別したり、reflect.propertiesやreflect.methodsでプロパティ名やメソッド名の一覧を得ることができます。

  • $オブジェクト

$.writelnでコンソールに情報を書き出すなど、主にデバッグで使われるオブジェクトです。

  • File, Folderオブジェクト

ファイル、フォルダの読み書きができるほか、execute()でファイルを(エクスプローラー上でダブルクリックしたのと同じように)開くこともできます。タイムスタンプを書き換えないファイルの移動ができないのが辛いところ。

  • Socketオブジェクト

通信用のオブジェクトです。httpsに対応していないため出来ることは限定的です。

  • BridgeTalkオブジェクト

あるアプリケーション(たとえばInDesign)から別のアプリケーション(たとえばPhotoshop)にスクリプトを送って実行させたりできます。

  • UnitValueオブジェクト

長さの値を単位付きで保持するオブジェクトです。四則演算や別の単位への変換ができます。pt、mmなど多くの単位に対応していますがHA(歯)が使えないのがInDesign使いには厳しい。

  • ScriptUI

ダイアログ(閉じるまでアプリを操作不能にするウィンドウ)やパレット(アプリより前面に表示され、アプリを操作不能にはしないウィンドウ)が作れます。

  • ExternalObjectオブジェクト

C++などで作った機能を呼び出すことができます。


ExtendScript 独自ではないけど一般的なJavaScriptには無い機能

  • E4X

XMLを扱うための機能。昔のFirefoxには実装されていたらしい。

  • watch, unwatch

オブジェクトのプロパティを変更しようとしたときなどに関数を実行する機能です。


一般的なJavaScriptと仕様が異なる点

  • 入れ子の三項演算子の実行順序

a?b:c?d:eは、JavaScriptではa?b:(c?d:e)の意味になりますが、ExtendScriptでは (a?b:c)?d:eの意味になります。
a?b?c:d:eは、JavaScriptでは a?(b?c:d):e の意になりますが、ExtendScriptでは構文エラーになります。
こいつはJavaScriptのライブラリを取り込みたいときの障害になることがしばしばあります。

  • 関数を即時実行したときのthis

関数を即時実行したときのthisはJavaScriptではグローバルオブジェクトになりますが、ExtendScriptでは実行した関数自身になります。

  • Function()を使ってもクロージャになる

関数はfunction式やfunction宣言で定義すると、定義を行ったスコープのクロージャになりますが、Functionコンストラクタを使って定義した場合はそうならない(グローバルスコープのクロージャになる)というのがJavaScriptの仕様です。しかしExtendScriptではfunction式などと同じくクロージャになります。

  • =の左辺と右辺が評価される順番

JavaScriptでは左辺→右辺、ExtendScriptでは右辺→左辺の順で評価されます。
参考:https://twitter.com/indiscripts/status/937164479040811009

  • undefined < X がtrue

undefined < X は、Xがどんな値でもほとんど常にtrueになります。例外はおそらくXがundefinedのときと、演算子のオーバーロードをしたオブジェクトのときだけ。

  • Math.random()が割といいかげん

ExtendScriptのMath.randomが作る値は65536通りしかありません。そして、Math.random()*65536は常に整数です。
65536通りって案外少ない数で、たとえば100個の乱数を取得したとすると、その中で値が被ってしまう確率が7%もあります。


コメントを残す

メールアドレスが公開されることはありません。