InDesign на автоматі
Ми продовжуємо цикл статей про скрипти у видавничих пакетах Adobe. Раніше були розглянуті основні підходи у скриптингу для Illustrator, на черзі - автоматизація робочих процесів InDesign.
Ми продовжуємо цикл статей про скрипти у видавничих пакетах Adobe. Раніше були розглянуті основні підходи у скриптингу для Illustrator, на черзі — автоматизація робочих процесів InDesign.
Якщо інтенсивніше працювати вже неможливо, почни працювати розумніше.
Афоризм з Інтернету
Стаття присвячена форматуванню тексту згідно з прийнятими правилами друкарні (розстановка нерозривних прогалин та інших спецсимволів), що є актуальним для всіх верстальників. Пропоноване рішення працює швидко, легко налаштовується та є гарною альтернативою комерційним розробкам.
Проблеми пошуку/заміни в Indesign Оскільки я займаюся версткою видань економічної спрямованості, що рясніють цифрами та скороченнями, а можливості InDesign у частині пошуку та заміни досить скромні (незважаючи на значних розмірів діалогове вікно), виникла гостра необхідність обійти обмеження програми . Проблема в тому, що InDesign не дозволяє змінювати фрагменти гнучкої маски (наприклад, замінювати слова, що починаються з певних символів) — лише чітко визначений фрагмент на інший. Наприклад, не можна замінити поєднання "цифра-тире-цифра" - на "цифра-нерозривне тире-цифра", "цифра-пробіл" - на "цифра-нерозривний пробіл". Прикладів таких корисних замін безліч…
Знак питання говорить про те, що символ може бути присутнім, але не обов'язково (тобто результатом пошуку за шаблоном «шиї?» у «довгошиї» буде «ше» та «шиї»), «плюс» — у тексті має бути хоча б один збіг попереднього символу ("ше+" дасть "ше", "шиї" і "шиї"). Дія «зірочки»схоже на "плюс", але охоплення ширше: "ше *" знайде, крім "ше" і "шиї", також "ш" і "шиї". Символ "" - аналог операції "або": [коїт] еквівалентно пошуку "кіт" і "кит". Щоб шукати «ко» та «іт» одночасно, потрібно (як варіант) використовувати дужки: (ко)(іт). "Кришка" має різний сенс залежно від місцезнаходження. Якщо на початку шаблону шуканий фрагмент шукається тільки на початку рядка, всередині діапазону — діапазон бути присутнім не повинен (тобто по [^а-я] знайдеться все, крім знаків алфавіту, а [^0-9] знайде все, що не є цифрою).
Слеш зарезервований для спеціальних випадків; один із них — пошук спецзнаків \t, \r, \n (знак табуляції, символ абзацу та новий рядок). Перед ними ставлять ще один знак "\", тобто рядок пошуку буде \\t і \r, відповідно. Точка використовується для пошуку будь-якого знака («довжина +» знайде не тільки все слово «довшешої», але і всі слова до кінця рядка). При пошуку зручно користуватися угрупованням (укладати в дужки частини пошукового виразу), що дає додаткову гнучкість під час операцій заміни.
Ми розглянули знаки для пошуку. Заміна має власну специфіку. Для подальшого використання знайдених фрагментів тексту призначені комбінації від $1 до $9, де цифра вказує порядковий номер виразу в дужках у рядку пошуку. Таким чином, пошуку комбінації «цифра-тире-цифра» буде відповідати вираз ([0-9])-([0-9]), або - (\d)-(\d) (спецсимвол d - скорочення від digital) , а заміна в ній дефісу на тирі буде виглядати як $1-$2. Всі вирази, що замінюються оточуються лапками і з'єднуються в ланцюжок через «+». На цьому ми закінчуємо з теорією та переходимо до практики.
![]() |
| Насправді можливості регулярних виразів ще потужніші, ніж описано встатті. Ті, хто цікавиться, можуть познайомитися з ними на сайті http://www.regular-expressions.info/reference.html |
Давайте складемо список необхідних операцій пошуку-заміни:
- Кілька поспіль пробілів, що йдуть, замінити на один.
- Між числами поставити нерозривне тире.
- Навколо тире – лише нерозривні прогалини.
- Пробіл після цифри – нерозривний (наприклад, "3 кг").
- кв.м і куб.м - м і м.
- Декілька поспіль великих букв (часто використовуються для позначення форми власності підприємства) не відривати від наступного слова (наприклад, АТЗТ "Пластмаси").
- Крім того, у списках для їх відбиття по лівому краю після пробілу вставлятимемо символ Indent Here.
1. Для заміни двох і більше прогалин на один потрібно ще трохи розширити наші знання в регулярних виразах. Для пошуку текстового фрагмента заданої довжини в них передбачена конструкція «», що визначає мінімально та максимально допустиму довжину пошукового фрагмента. У нашому випадку досить скласти конструкцію — невказаний другий аргумент говорить про те, що максимум не обмежений, що і потрібно. Змінюємо одну прогалину (« »).
2. Для реалізації другої умови підійде рядок (\d)-(\d), але для розширення функціональності її краще замінити на (\d) ?-— ?(\d). Це дозволить розширити охоплення: будемо шукати числа, після яких може бути пробіл (у матеріалі, що подається на верстку, трапляється всяке), потім стоїть або «-» або «-», після чого знову ж таки можлива пробіл і, нарешті, знову йде цифра. Таким чином, ми залучаємо в діапазон пошуку значно більшу кількість варіантів написання, і заміна буде більш універсальною. Дужки потрібні для збереження результатів пошуку при наступномузаміні.
3. Так само для третьої заміни змінюємо звичайні прогалини навколо тире на нерозривні (їхній 16-річний код «A0» випереджається ключем \х).
У четвертому кроці для заміни пробілу після числа на нерозривний використовуємо комбінацію "\d" - рядок заміни буде "$1"+"\xA0". Але після чисел можуть стояти множники (тис., млн, млрд), тому для коректної обробки зв'язки «число-множник-розмірність» можна скористатися таким ланцюжком дій: спочатку прив'яжемо до цифр розмірності, а потім самі множники. В результаті для пошуку отримаємо:
Незалежно від того, чи стоїть після множника точка та/або пробіл, ми коректно відпрацьовуватимемо всі комбінації. У цьому полягає головна краса регулярних висловів — вони дають надзвичайну гнучкість у пошуку необхідних фрагментів. Рядок заміни в такому випадку матиме вигляд:
Нагадаю, \xA0 - 16-річне значення нерозривної пробілу, а \. - точка (знак "\" перед нею стоїть, щоб не було плутанини з "." - підстановним знаком для будь-якого символу). До речі, щоб поєднання «мі», «мі» оброблялися коректно (після цифри залишалася звичайна прогалина), виключимо з діапазону захоплення поєднання «м, що йде перед цифрою». В результаті find1 зміниться на ([^м])(\d) , а replace1 - на "$1"+"$2"+"\xA0".
5. Наступний крок - скорочення типу АТ, ЗАТ, АТЗТ та ін. Щоб не відривати форму власності від самої назви, достатньо вказати мінімальну довжину шуканої конструкції - 2. Пошук ведемо тільки серед великих літер (А-Я). В результаті для пошуку отримаємо: ([А-Я]) (""), уточнення ("") внесено для більшої гнучкості після апробації на реальних текстах, враховує наявність лапок у назві організацій.
6. Наступний крок не відноситься безпосередньо до теми пошуку/заміни, але спрощує роботу зі списками. Передбачимоавтоматичне додавання символу лівої межі тексту (Indent here) по пробілу, наступному відразу за відбивним знаком списку, тобто шукаємо вираз ^[\x95\u2013\x2D]. Знак «^» забезпечує пошук тільки на початку рядків, 95, 2013, 2014 і 22 - варіанти відбиття (куля, табуляція, довге тире або дефіс). Заміна - на "$1" + "2002" + "x07", де "u002" + "x07" - коди пропуску фіксованої ширини і "Indent here", відповідно. Визначення значень всіх спецсимволів через додатковий скрипт та виділення було описано раніше.
7. Останній крок - переведення виразів «кв.м», «куб.м» у прийняту форму (мі, м). Розіб'ємо його на два етапи: спочатку проводимо заміну «кв.» та «куб.» на відповідні цифри, потім переводимо в надрядковий індекс. З урахуванням різноманітних модифікацій написання (з точкою і без, з пропуском і між словами) отримаємо рядок пошуку кв [\. ?](м)[\. ?]. Наступний крок — пошук виразів «мі» та «мі» та заміна стилю форматування для цифри.
Отже, основну роботу виконано. Залишилося лише оформити наші записи у вигляді скрипту. Регулярні вирази Javascript задаються між двома косими рисами (слешами), а ключ «g» означає багаторазову заміну (global). Також передбачено ключ «i» - ігнорування регістру (тобто змінювати і малі, і великі), але нам він не знадобиться. Пошук будемо проводити по черзі у кожному абзаці виділеного текстового фрагмента. Отже, можемо записати для блоку базових перетворень:
Інші операції пошуку/заміни:
![]() |
| Результат роботи скрипта |
Проводимо заміни по черзі у кожному виділеному абзаці, для чого скористаємося методом replace, застосованим до властивості contents (вміст у вигляді рядка) абзацу.
Після закінчення замінюємоколишній вміст абзацу новим:
Загальні зауваження Ось і весь скрипт. При запуску для об'ємних публікацій результатів доведеться трохи почекати, але якщо текст перед верскою вичитується, деякі операції заміни можна виключити (наприклад, пошук багаторазових прогалин), що позитивно позначиться на швидкості роботи. Серед плюсів запропонованого рішення – компактність та легкість додавання власних правил обробки тексту.
Шукаємо та міняємо засобами InDesign
У пакеті передбачено підтримку операцій пошуку/заміни через метод search.
Серед його параметрів — рядок, чутливість до регістру, текст, що замінює, атрибути пошукового фрагмента і замінює (у т. ч. їх форматування).
Для зручності атрибути задаються у вигляді окремих наборів Find Preference та Change Preference (з точки зору InDesign – окремі об'єкти), у яких перераховуються всі необхідні параметри. У тому числі — будь-які допустимі параметри абзацу, зокрема стиль окремого символу (character). Таким чином, сформувавши необхідну кількість наборів, можна по черзі проводити пошук та заміну.
Як це робити
До речі, відладчик у новій версії потужніший, користуватися ним зручніше, тому рекомендую саме Creative Suite 2.
2. При активному тестуванні може виникнути ситуація, коли скрипт починає збоїти, тобто видавати помилку там, де її насправді немає. Як правило, це відбувається при повторному застосуванні до одного документа. Пам'ять засмічується історією ваших помилок, тому бажано тестовий файл перед повторним запуском скрипту закрити (у цьому випадку пам'ять очищається) і знову відкрити. Звичайно, при інтенсивному тестуванні це дратує, а визначити, що скрипт дійснопрацює некоректно, вже неможливо. Тому візьміть за правило знову відкривати файл через кілька запусків скрипта. Якщо ж скрипт взагалі починає «спотикатися на рівному місці», перезавантажте відладчик і, бажано, сам хост-додаток.
І на останок. Перед запуском скрипта у налагоджувачі перевірте, який хост-додаток вибрано як робочий (панель Target Application). За замовчуванням налаштовувач налаштований на ExtendScript ToolKit, тому будьте пильні.
![]() |
| ExtendScript Editor - зручний інструмент пошуку проблемних ділянок коду |
Дві поради
1. Замість перерахування всіх операцій пошуку/заміни (r = r.replace(find, replace)), можна скористатися можливостями масивів: записувати рядки пошуку/заміни відразу як елементи масиву, а потім у циклі перебирати їх, що скоротить обсяг коду та підвищить його читабельність.
Видаляємо невикорисні стилі
Щоб охопити весь вміст смуги (в т. ч. «заякорені» текстові блоки Anchor, згідно з об'єктною моделлю, що не входять до складу текстового кадру, якому вони належать), шукатимемо абзаци через властивість allPageItems. Воно дає доступ до всього вмісту смуги.
Створюємо посилання на об'єкти:
Створюємо рядок для накопичення у ньому всіх використаних у документі стилів:
У циклі переглядаємо вміст кожної сторінки, відфільтровуємо лише текстові кадри та зберігаємо всі використані стилі:
Якщо стиль не знайдено, видаляємо його та враховуємо це у лічильнику:


