我正在使用Adobe CEP(它允许开发人员为Adobe CC产品创建窗口扩展)。我的大部分代码都是现代JavaScript(该平台使用Chromium 57,Node.js 7.7.4)。但是,为了访问DOM,我需要在Adobe ExtendScript中编写一些函数并从普通的JS执行它们。唯一的方法是使用他们提供的csInterface.evalScript(script, callback)
执行脚本。 script
必须是一个字符串,在我的例子中是一个转换为字符串的函数调用。我希望能够通过evalScript
将对象传递给ExtendScript,但是evalScript
只接受并返回一个字符串。
目前,我将每个对象属性作为自己的参数传递。这很笨重,但它确实有效。
我的第一个虽然是JSON.stringify()
,但不幸的是ExtendScript是ECMAScript 3的方言,这意味着没有JSON.parse()
的支持。
我不能只将对象参数连接到脚本函数调用中,因为那时字符串的计算结果为foo([object Object])
。
我已经看到有像eval()
/ uneval()
或Object.toSource()
这样的功能,但Chromium不支持这些功能。
这是一个例子,类似于我目前的方法:
functions.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;
}
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);
});
});
}
正如所料,circle()
称drawCircle()
就好了,我正在制作的文件中出现了一个椭圆。但是,通过串联执行脚本/调用函数会感觉非常错误。总而言之,
dataObject
变成一个字符串并通过drawCircle()
传递给evalScript()
,dataObject
返回drawCircle()
并将其作为对象收回。目前,返回一个对象只会导致"[object Object]"
作为返回值。将对象从Javascript传递到ExtendScript的唯一方法是将其作为带有JSON.stringify()
的JSON字符串发送。
是的,你是对的没有JSON.parse()
支持,但是,你不需要。
您仍然可以发送字符串化对象,并将作为对象到达ExtendScript。
const dataObject = {x: 10, y: 10, name: 'Hello world!'};
const script = "drawCircle(" + JSON.stringify(dataObject) + ")";
然后在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;
}
您需要将此ExtendScript模块复制到与jsx相同的文件夹中
Link to Indiscripts ExtendScript JSON module
然后在jsx的顶部用#include 'json.jsx';
(或//@include 'json.jsx'
来避免linter错误)包含它。这会添加一个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);
}
然后在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));
});
我在最新的CEP Runtime版本(v9)中对此进行了测试。