如何将对象从 Javascript (Adobe CEP) 传递给 Adob​​e ExtendScript?

Jas*_*erl 2 javascript extendscript ecmascript-3

我正在使用Adobe CEP(它允许开发人员为 Adob​​e CC 产品创建窗口扩展)。我的大部分代码是现代 JavaScript(该平台使用 Chromium 57、Node.js 7.7.4)。 但是,为了访问 DOM,我需要在 Adob​​e ExtendScript 中编写一些函数并从普通 JS 中执行它们。唯一的方法是使用他们提供的csInterface.evalScript(script, callback). script必须是一个字符串,在我的例子中是一个转换为字符串的函数调用。我希望能够通过 将对象传入和传出 ExtendScriptevalScript,但evalScript只接受和返回一个字符串。

目前,我将每个对象属性作为它自己的参数传递。这很笨拙,但它有效。

我的第一个虽然是JSON.stringify(),但不幸的是 ExtendScript 是 ECMAScript 3 的方言,这意味着JSON.parse()支持.

我不能只是将对象参数连接到脚本函数调用中,因为这样字符串的计算结果为foo([object Object]).

我见过像eval()/uneval()或这样的函数Object.toSource(),但 Chromium 不支持这些函数。

这是一个示例,类似于我当前的方法:

函数.js (ES3/ExtendScript)

function drawCircle(x, y, name) {
    // pick a layer
    var layer = app.activeDocument.layers[0];

    var diameter = 10;
    var top = y + diameter / 2;
    var left = x - diameter / 2;

    // draw ellipse in layer
    var circle = layer.pathItems.ellipse(top, left, diameter, diameter);

    circle.name = name;
    circle.filled = true;

    return true;
}
Run Code Online (Sandbox Code Playgroud)

app.js (ES6)

const csInterface = new CSInterface();    // provided by Adobe
async function circle() {
    const dataObject = {x: 10, y: 10, name: 'Hello world!'};

    // the script to call
    // evaluates to drawCircle(10,10,'Hello world!');
    const script = "drawCircle(" + dataObject.x + "," + dataObject.y + ",'" + dataObject.name + "');";

    return new Promise((resolve, reject) => {
        csInterface.evalScript(script, (result) => {
            resolve(result);
        });
    });
}
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,circle()调用drawCircle()很好,并且我正在处理的文档中出现一个椭圆。但是,通过串联执行脚本/调用函数感觉非常错误。所以总结一下,

  1. 我想要一些(更整洁的)方式dataObject变成字符串并将其传递给drawCircle()via evalScript()
  2. 我想dataObjectdrawCircle()它返回并作为一个对象接收它。目前,返回一个对象只会导致"[object Object]"返回值。

Har*_*rry 6

Javascript -> 扩展脚本

将对象从 Javascript 传递到 ExtendScript 的唯一方法是将其作为带有JSON.stringify().

是的,您没有JSON.parse()支持是对的,但是,您不需要

您仍然可以发送字符串化的对象,并将作为对象到达 ExtendScript 。

const dataObject = {x: 10, y: 10, name: 'Hello world!'};
const script = "drawCircle(" + JSON.stringify(dataObject) + ")";
Run Code Online (Sandbox Code Playgroud)

然后在 ExtendScript 中,你可以做这样的事情:

function drawCircle(obj) {
  var layer = app.activeDocument.layers[0];

  var radius = 10;
  var top = obj.y + 5;
  var left = obj.x - 5;

  var circle = layer.pathItems.ellipse(top, left, radius, radius);

  circle.name = obj.name;
  circle.filled = true;

  return true;
}
Run Code Online (Sandbox Code Playgroud)

扩展脚本 -> Javascript

您将需要这个 ExtendScript 模块,复制到与您的 jsx 相同的文件夹中

链接到 Indiscripts ExtendScript JSON 模块

然后将它与#include 'json.jsx';(或//@include 'json.jsx'避免 linter 错误)一起包含在 jsx 的顶部。这将添加一个 JSON 全局函数,该函数提供两种方法:JSON.eval()JSON.lave().

我们需要的方法是lave()允许您将对象字符串化回 Javascript。将其视为JSON.stringify().

function drawCircle(obj) {
  var layer = app.activeDocument.layers[0];

  var radius = 10;
  var top = obj.y + 5;
  var left = obj.x - 5;

  // draw ellipse in layer
  var circle = layer.pathItems.ellipse(top, left, radius, radius);

  circle.name = obj.name;
  circle.filled = true;

  return JSON.lave(circle);
}
Run Code Online (Sandbox Code Playgroud)

然后在 javascript 中,您可以再次解析为一个对象:

const dataObject = {x: 10, y: 10, name: 'Hello world!'};
const script = "drawCircle(" + JSON.stringify(dataObject) + ")";

csInterface.evalScript(script, (result) => {
  console.log(JSON.parse(result));
});
Run Code Online (Sandbox Code Playgroud)

我在最新的 CEP 运行时版本 (v9) 中对此进行了测试。