ExtensionとCEPとNODEと…

皆様、ご存知の通りCreativeCloud以降のアプリケーションにはHTML5系で構成されたエクステンションが利用可能です。そして、このHTMLを取り扱うエンジンはChirome Embeded Framework 3が導入されています。つまり、CC以降の機能拡張のコアとなるCommon Extensibility PlatformのコアはChiromeだということです。更に言いますと、搭載されているJavascriptエンジンはGoogleのV8エンジンであり、CC2014以降のCEP(ver.5以降)では、おまけとしてNODE.jsが組み込まれています。つまり、NPMの膨大なライブラリが利用可能ということです。
しかしながら、制限事項もございます。まず、クラスタは使えません。そして、こちらが結構致命的ですが、NODEのNative Extensionまわりに不具合があります。例えばPCRE等のネイティブモジュールを含むものに関してですが、スクリプトエンジンがエラーで停止してしまいます。これはCEPの開発チームのLeaによると、現行のNODE.jsとCEPが搭載するV8エンジンのバージョンが異なることに起因するものらしいです。要するに乗っかってるChromeが古すぎるということなのです。これに関してはAIが起動時にエラーを吐く(バックグランドで吐いていますからおおよその方は気づきもしませんが)などの不具合をしょうじているものだったりします。しかしながら、Javascriptモジュールに関しては動くんじゃね?ってアナウンスがありましたので、どの程度の事ができるのかしっかりと検証したいと思います。

今回のパネルは、Webサービスと連動して投げ込まれたデータを自動的に組版するというものです。では中身を見て行きましょう。
オート組版メインですのでUIはデータの確認を出来るようにしているだけです。具体的にはidを割り振ったdivタグの領域を用意してポストされたデータを処理後は書き込むだけです。

HTML
<!doctype html>
<html>
<head>
<meta charset=”utf-8″>
<link rel=”stylesheet” href=”css/styles.css”/>
<link id=”hostStyle” rel=”stylesheet” href=”css/theme.css”/>
<title>Node Test</title>
</head>
<body class=”ps-cs6″>
    

     http://js/libs/CSInterface.js
     http://js/libs/jquery-2.0.2.min.js
     http://js/themeManager.js
     http://js/main.js
</body>
</html>

Chromeベースのレンダリングエンジンですから普通にjquery.jsとかも使えます。一つ前のバージョンではAngularJSとか使ったりしていましたが、現在はNODEでおおよその事ができます。UIに関して言えばExtendscriptのようなプロプライエタリな代物に比べると、リソースも多く学びやすく組み易いものとなっています。
気になる所はCCアプリとのアピアランスの統一なのですが、CSInterfaceクラスにはアプリケーション自体のアピアランスの変更を検知するnotifierが存在しますので、それらを利用してパネルの外観を変更します。この辺りはExtensionBuilder for BracketではプロジェクトにthemeManager.jsを組み込んでくれたりしますのでそのまま利用すると楽ちんだったりします。
ここで、まじめに組み込み処理を行った場合のエクステンション構造を掲載しておきましょう。

css/styles.css
css/theme.css
CSXS/manifest.xml
icons/aiRotater_default.png
index.html
js/libs/CSInterface-4.0.0.js
js/libs/jquery-2.0.2.min.js
js/main.js
js/themeManager.js
jsx/hostscript.jsx
locale/en_US/messages.properties
locale/ja_JP/messages.properties

ご覧のとおりHTMLでーページを作成した時のものとそう変わらないのが見て取れると思います。ここでは行われていませんがjs/libsにvulcan.jsなどを追加してエクステンション間通信等をサポート等することができたりします。その他、NODEまわりやNPM関連は以下で解説します。
まず、今回のエクステンションのメイン部分を見て行きましょう。
以下に示すのはJavascriptファイルの内容です。

js
(function () {
     ‘use strict’;
     var csInterface = new CSInterface();
     var sys = require (‘sys’),
     net = require(‘net’),
     url = require(‘url’),
     http = require(‘http’),
     fs = require(‘fs’),
     qs = require(‘querystring’);

     http.createServer(function (req, res) {
          if(req.method==’POST’) {
                    var body=”;
                    req.on(‘data’, function (data) {
                              body+=data;
                              });
                    req.on(‘end’,function(){
                         var dt =  qs.parse (body);
                         csInterface.evalScript(“testFunc(‘” + dt.str + “‘)”);
                         res.writeHead(200, {‘Content-Type’: ‘text/plain’});
                         document.getElementById(“message”).innerHTML += dt.str + “<br />”;
                         });
          }
          else if(req.method==’GET’) {
               var url_parts = url.parse(req.url,true);
               res.writeHead(200, {‘Content-Type’: ‘text/plain’});
               res.end(‘GET method requested.\n’);
               //console.log(“GET method requested.”);
               }
          }).listen(1337, ‘0.0.0.0’);
     document.getElementById(“message”).innerHTML
          += ‘<b>Server running at http://127.0.0.1:1337/</b><br />’;
     }());

csInterfaceの初期化以下に続くrequireメソッドはNODEが利用するパッケージを読み込むためのものです。コードはHTTPサーバを構成し、POSTメソッドおよびGETメソッドに対してのレスポンスと、それに伴う処理を記述しています。NODEのコードの特徴がよく出ているものです。基本的にノンブロッキングなので、かえってくるイベントに応じたファンクションを記述し、それぞれ対応する事になります。例えば、

http.createServer(function (req, res) {

このcreateServerメソッドの引数はコールバック関数であり、HTTPリクエストが入ってきた時に行われる処理を記述するものです。次にデータの送受信は全てが一度に行われるわけではありません。通常、状況に応じてパケット単位で通信されますのでデータを

body+=data;

で受けます。request自体はhttp.IncomingMessageインスタンスで、最後にcloseイベントが発生します。これは「data」ではなく「end」が返されることによって判別します。
通常、フォームからPOSTされるデータは「application/x-www-form-urlencoded」ですからデコードやパース処理が必須です。こちらも「querystring」APIが用意されていて、

var dt = qs.parse (body);

というかんじでさらりと処理できます。
今回のポスト元のソースは

<form method=”post” action=”http://127.0.0.1:1337&#8243; accept-charset=”UTF-8″>
<input type=”text” name=”str” />
<input type=”submit” value=”post” />
<input type=”reset” value=”cancel” />
</form>

ですから「dt.str」に ポストデータが入っています。一方、GETメソッドの場合はヘッダのみでボディがありませんのでヘッダとコンテンツボディを適当に返しているのみです。
以上のようにNODEを利用するとすごく簡単にWEBサーバを構築できます。
さて、evalScriptで実行されるファンクションは以下の様なものです。

jsx
function testFunc(str){
     app.activeDocument.textFrames[0].contents += str+”\n”
     }

ここらへんが力尽きた感がいっぱいで恐縮ですが、頂いたデータをそのままテキストフレームのコンテンツとして書き込んでいます。
実際にはPOSTするデータをJSONで構築して、コンテンツを調整するようにすると取り回しがとっても楽になるでしょう。

それから、Extension Builder 3は2年近く更新されていない代物です。特にデバッグ等に便利かとういと、そうでもなかったりしますので、わたし自身使ってませんし、人に進めることもないです。セットアップの労力に見合ったものが得られませんので。
わたしがエクステンションを作る時に利用するのは殆どテキストエディタ1本です。UIを作りこむとかの場合はDWとBracketを使ったりします。初心者の方にはCreative Cloud Extension Builderという某社のエバンジェリストの方が作ったBracketの機能拡張をおすすめしています。

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google フォト

Google アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中