Скрипты: взятие элемента в Индизайне или Иллюстраторе

Вступление

Внутри Иллюстратора и Индизайна работают скрипты. Язык их написания называется ExtendScript, это синтаксис JavaScript 1999 года с добавлением объектов из сответствующей программы. То есть в Иллюстраторе есть объекты линий, кистей, стилей и всего прочего, что используется в Иллюстраторе, а в Индизайне есть стили абзацев, объектов, символов и всего остального, что вы видите в панельках Индизайна.

Есть большая часть объектов, работа с которыми одинаковая в Иллюстраторе и Индизайне: файлы, диалоговые окна и элементы интерфейса. То есть можно взять скрипт диалогового окна и выполнить его и в Иллюстраторе, и в Индизайне. Удобно? Вроде да.

Но вот работа с элементами каждой из отдельной программы отличается совершенно. Об этом и захотелось тут написать.

Проблема

Точнее хочется показать эту разницу на одном простом примере: метод взятия элемента из массива. Например, взятие цвета из палитры цветов. Или взятие шрифта из массива шрифтов. Казалось бы: достаточно простая операция: обратиться к массиву объектов и вернуть элемент по его имени, или вернуть null при его отсутствии.

Но это было бы слишком просто, чтобы это сделали в такой мощной корпорации как Adobe!

Иллюстратор — Adobe Illustrator

В Иллюстраторе есть прекрасный метод getByName(), но его прекрасность заканчивается его названием. Если выполнить его и не будет найден элемент с таким именем, то будет выброшено исключение и скрипт остановится. Что? Да! Вот просто любой ваш скрипт вылетит с такой ошибкой.

Illustrator

Самое интересное, что если у вас в документе будет 2 объекта с нужным именем, ошибки никакой не будет. Он просто вернёт первый. Почему тогда такая серьёзная ошибка?

Поэтому приходится писать свой метод взятия: оборачиваем стандартный метод в try...catch и при ошибке возвращаем null. Вот так:

/**
 * Illustrator
 */
function getItemByName(items, itemName) {
    try {
        return items.getByName(itemName);
    } catch (e) {
        return null;
    }
}

Индизайн — Adobe InDesign

В Индизайне есть не менее прекрасный метод itemByName. Но ведёт он себя совершенно по-другому: если не будет найден элемент с нужным именем, то вы получите... нужный объект, но он будет невалидный! Вот так вот лихо они сделали.

Будет это объект нужного класса? Да. Будут у него все нужные параметры? Да. Будет он работать? Нет! Ребята в команде скриптов Индизайна заморочились и добавили специальный параметр isValid у всех объектов, который возвращает либо истину, либо ложь.

Поэтому нормальный метод, который берёт нужный элемент по имени, в Индизайне будет выглядеть вот так:

/**
 * InDesign
 */
function getItemByName(items, itemName) {
    const item = items.itemByName(itemName);

    return item.isValid ? item : null;
}

Резюме

Если были описаны два подхода взятия элемента из массива, то нужно указать на правильность одного или второго? Но я не вижу в обоих подходах хоть какого-то удобства.

Иллюстратовский метод совершенно дикий, потому что прерывает скрипт. Если у меня критическая необходимость наличия элемента с нужным именем, то я и сам выкину ошибку, да ещё и озаглавлю её нормально: Цвет с именем «MetroLine1» не найден.

Индизайновский метод не менее дик, и привёл к тому, что весь код теперь завален проверками валидность объектов.

Так что просто копируйте мои методы и используйте их.