Как передать объект в Adobe ExtendScript из Javascript (Adobe CEP)? - PullRequest
0 голосов
/ 07 апреля 2019

Я работаю с Adobe CEP (он позволяет разработчикам создавать оконные расширения для продуктов Adobe CC). Большая часть моего кода - современный JavaScript (платформа использует Chromium 57, Node.js 7.7.4). Однако , чтобы получить доступ к DOM, мне нужно написать некоторые функции в Adobe ExtendScript и выполнить их из обычного JS. Единственный способ - выполнить скрипт, используя предоставленные им csInterface.evalScript(script, callback). script должна быть строкой, которая в моем случае является вызовом функции, преобразованной в строку. Я хочу иметь возможность передавать объект в и из ExtendScript через evalScript, но 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() просто отлично, и эллипс появляется в документе, над которым я работаю. Однако выполнение сценария / вызов функции путем конкатенации кажется очень неправильным . Итак, в итоге,

  1. Я бы хотел какой-нибудь (аккуратный) способ превратить dataObject в строку и передать ее в drawCircle() через evalScript(),
  2. и я хотел бы вернуть dataObject из drawCircle() и получить его обратно как объект. В настоящее время возвращение объекта приводит только к "[object Object]" в качестве возвращаемого значения.

1 Ответ

1 голос
/ 08 апреля 2019

Javascript -> ExtendScript

Единственный способ передать объекты из Javascript в ExtendScript - это отправить его в виде строки JSON с JSON.stringify().

Да, вы правы насчет отсутствия поддержки 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 -> Javascript

Вам понадобится этот модуль ExtendScript, скопированный в ту же папку, что и ваш jsx

Ссылка на незашифрованный модуль ExtendScript JSON

Затем включите его с #include 'json.jsx'; (или //@include 'json.jsx', чтобы избежать ошибок линтера) в верхней части вашего 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);
}

Затем в 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).

...