Home About Contact
JavaScript , Node.js , ExtendScript , Underscore.js , Rollup.js

ExtendScript で Underscore.js を使う(その1) Rollup.js 編

Node.js で ExtendScript する話(パート3) ES6 Javascript 記述を使いたい で node.js を使ってモジュールを解決しつつ、アロー関数や const let などのES6 Javascript 記述を使って書けるようになった。 そこで、次に Underscore.js を利用した ExtendScript をコーディングすることを考えます。

実のところ単に Underscore.js を使うだけならば、ExtendScript 標準の @include ディレクティブを使うことで普通に利用できます。 しかしこの方法では、 (1)Underscore.js のファイルを常に本体のファイルとともに配布する必要があり面倒、 (2)Underscore.js を使う側のアプリケーションコードで、ES3レベルの Javascript しか記述できない、 という2つの問題があります。 Node.js + Rollup.js + Babel を使う方式でこの問題を解決しましょう。

myunderscore プロジェクト

例によって、ここで使用するツールのバージョンを確認しておきます。

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.7
BuildVersion:   19H1323

$ node -v
v14.17.6

$ make -v
GNU Make 3.81

プロジェクトとディレクトリを作成し、必要なツールをインストールする:

$ mkdir myunderscore
$ cd myunderscore
$ npm init -y
$ npm install rollup@2.56.3 --save-dev
$ npm install @babel/core@7.2.2 --save-dev
$ npm install @babel/cli@7.2.3 --save-dev
$ npm install @babel/preset-env@7.2.3 --save-dev
$ npm install underscore@1.13.1 --save-dev

ここまでのところで、一旦 package.json を確認します:

{
  "name": "myunderscore",
  "version": "1.0.0",
  "type": "module",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/cli": "^7.2.3",
    "@babel/core": "^7.2.2",
    "@babel/preset-env": "^7.2.3",
    "rollup": "^2.56.3",
    "underscore": "^1.13.1"
  }
}

ESM スタイルのモジュールを使うには "type": "module" を指定しておく必要があるとのこと。 自動で生成された package.json にそれを手動で書き加えています。

方針は以下のようにします。

はじめに main.js を実装します:

import _ from './node_modules/underscore/underscore-esm.js';

var console = {};
console.log = function(message){
	$.writeln(message);
};

var result = _.map([1, 2, 3], function(num){ return num * 3; });
console.log(result);

Underscore による処理内容は、リストの各要素を3倍したリストを返すコードです。

これを rollup して main.jsx を生成します。

./node_modules/.bin/rollup main.js --file main.jsx

main.jsx を見ると Underscore がバンドルされていることがわかります。 早速作動するか確かめてみます。

おっと、実行する前に、 InDesign でこのコードを実行する指定 @target InDesign を書き加えます。

echo "//@target InDesign" >> main.jsx

コードの準備ができたので、例によって .vscode/launch.json をプロジェクトに加えて、code . して VSCode を起動、ExtendScript Debugger で実行です。

.vscode/launch.json の内容はこれ:

{
    "version": "1.0.0",
    "configurations": [
        {
            "type": "extendscript-debug",
            "request": "launch",
            "name": "main.jsx",
            "program": "${workspaceFolder}/main.jsx",
            "stopOnEntry": false
        }
    ]
}

VSCode + ExtendScript Debugger で main.jsx を実行します。

VSCode main.jsx

3,6,9 の結果が出ています。うまくいきました。

次に main.js を ES6 の Javascript 記述方法にてリファクタリングします。

import _ from './node_modules/underscore/underscore-esm.js';

const console = {};
console.log = function(message){
	$.writeln(message);
};

//var result = _.map([1, 2, 3], function(num){ return num * 3; });
const result = _.map([1, 2, 3], num => num * 3);
console.log(result);

ではこれを babel でトランスパイルしましょう。

まず、 babel.config.json を以前のプロジェクトからコピーします。 そして、 rollup して babel して @target InDesign を加えるまでの一連の処理を行う Makefile を用意します。

Makefile:

main.jsx: tmp.jsx
	node_modules/.bin/babel --compact=false $< > $@
	echo "//@target InDesign" >> $@

.INTERMEDIATE: tmp.jsx
tmp.jsx: main.js
	./node_modules/.bin/rollup $< --file $@

clean:
	$(RM) main.jsx

このプロジェクトのファイルとディレクトリ構成を確認しておきましょう。

.
├── Makefile
├── babel.config.json
├── main.js
├── node_modules/
├── package-lock.json
└── package.json

では make して main.jsx を生成します。その後、VSCode + ExtendScript Debugger で実行します。

VSCode main.jsx

先ほどと同じ 3,6,9 結果が出ました。 うまくいきました。

まとめ

これで Underscore.js を利用した ExtendScript コードを ES6 の Javascript 記述を使って書くことができるようになりました。

追伸

この内容を整理しなおした電子書籍 Node.js による InDesign ExtendScript モダン開発入門を出しました。