Здоровий глузд

Про дизайн, міста та дизайн у містах, кодінг та автоматизацію

Конвеєр: автоматизоване нарізання PDF на різні файли

В роботі над дизайном багатьох макетів буває дуже зручно їх всі робити в одному файлі: можна простіше копіювати елементи та стилі, мати єдину базу символів, бачити загальну картинку одразу на всіх макетах тощо.

Багато макетів різних розмірів у Adobe Illustrator
Багато макетів різних розмірів у Adobe Illustrator

Але редактори погано пристосовані для збереження потім таких робочих файлів, що йтимуть на виробництво. Процес збереження купи файлів починає нагадувати нудну справу, в якій ви вибираєте що зберігати, якось розділяєте на окремі файли та при збереженні у різні формати правильно називаєте все. Така безглузда трата робочого часу і це нууудно 🥱. І в такій ручній роботі точно виникатимуть помилки, тож доведеться починати наново.

У ІнДизайні є можливість зберігати PDF посторінково. Але можливості обмежені й потім все одно треба перейменовувати файли, як треба. У Ілюстраторі взагалі така опція є тільки для збереження окремих артбордів для екранів (у RGB), тож для друку це не підходить. І вирішувати це можна сторонніми скриптами, як-то скрипт для збереження файлу у різні формати, який ми робили для своєї роботи.

Але це не вирішує задачу, коли у вас частина макетів двосторонні й ці різні сторони мають зберегтись, наприклад, в один PDF на кілька сторінок.

А якщо вже після збереження потрібно буде внести якісь зміни, то весь цей нудний процес треба робити спочатку і добре якщо не для всіх файлів.

Конвеєр та алгоритм

Мені цікаво шукати і організовувати дизайн-конвеєр під такі задачі, оскільки вони точно повторюватимуться, тож автоматизація дає шалену економію часу, який можна витратити на цікавіші речі.

Колись писав про масове перейменування файлів, які перед цим нарізав в Акробаті на окремі файли. Але це все одно довго, треба ще швидше.

Спочатку потрібно подумати над наявними можливостями й алгоритмом. Кожен редактор може за раз зберігати всі або діапазон сторінок у суцільний PDF-файл. Тож якщо мати інструкцію, яка скаже які сторінки мають піти в який файл і як ці файли назвати. Така інструкція — своєрідна «маска», яку можна застосувати для файлу.

1-2=filename01
3=filename02
4-5=filename03
6-8 10=filename04
…

де:

  • 1-2 — сторінки документа (може містити одну цифру, діапазон через дефіс, перелік окремих сторінок через пробіл, також доступні параметри початку і кінця документа start-10 чи 57-end )
  • = — технічний розділювач (у назвах файлах його не повинно бути)
  • filename01 — назва вашого майбутнього PDF-файлу, в який в який увійдуть сторінки з діапазону (без розширення .pdf)

bash + PDFtk

Для цього bash (потрібна версія 4 і вище, перевіряється у терміналі через bash -v, встановлюється через brew install bash) та PDF Toolkit (PDFtk).

За допомогою ChatGPT в кілька ітерацій зробив скрипт, що бере вказаний PDF-файл, окремо бере текстову «маску» у TXT, як масив назв, в яких

#!/bin/bash

input_file="Tustan-Signs-All.pdf"
data_file="range.txt"

# Read page ranges and custom names from the external file into a single array
readarray -t page_data < "$data_file"

# Loop through the array and split the PDF
for data in "${page_data[@]}"; do
    IFS="=" read -r range custom_name <<< "$data"
    output_file="${custom_name// /_}.pdf"  # Replace spaces with underscores in the custom name
    pdftk "$input_file" cat $range output "$output_file"
    echo "$output_file — Done"
done

Для більшої універсальності я виніс вказання файлів, як аргументів у командному рядку. Тож тепер можна скопіювати скрипт у потрібну теку та запустити командою:

bash splitter-pro.sh filename.pdf mask.txt

де:

  • filename.pdf — назва вашого PDF-файлу
  • mask.txt — текстовий файл з «маскою»

Сам скрипт виглядає так ($1 — перший аргумент, тобто PDF-файл; $2 — другий аргумент, тобто TXT-файл):

#!/bin/bash

input_file=$1
data_file=$2

# Read page ranges and custom names from the external file into a single array. Requaire bash 4.0
readarray -t page_data < "$data_file"

# Loop through the array and split the PDF
for data in "${page_data[@]}"; do
    IFS="=" read -r range custom_name <<< "$data"
    output_file="${custom_name// /_}.pdf"  # Replace spaces with underscores in the custom name
    pdftk "$input_file" cat $range output "$output_file"
    echo "$output_file — Done"
done

Приклад «маски», де спочатку номери сторінок, символ =, а далі назва файла (Проект-Знак-Точка-Розмір):

1-2=Tustan-WF-Sign-Т1-400x600
3=Tustan-WF-Sign-Т2.1-200x350
4=Tustan-WF-Sign-Т2.2-200x350
5=Tustan-WF-Sign-Т3.1-200x350
6=Tustan-WF-Sign-Т3.2-200x350
7-8=Tustan-WF-Sign-Т4.1-T4.2-200x600
9-10=Tustan-WF-Sign-Т4.3-T4.4-200x600
11=Tustan-WF-Sign-Т5.1-200x600
12=Tustan-WF-Sign-Т5.2-200x600
13=Tustan-WF-Sign-Т6.1-200x600
14=Tustan-WF-Sign-Т6.2-200x600
15=Tustan-WF-Sign-Т7.1-200x600
16=Tustan-WF-Sign-Т7.2-200x600
17=Tustan-WF-Sign-Т8.1-200x600
18=Tustan-WF-Sign-Т8.2-200x600
19=Tustan-WF-Sign-Т9.1-200x600
20=Tustan-WF-Sign-Т9.2-200x600
21=Tustan-WF-Sign-Т9.3-200x600
22-23=Tustan-WF-Sign-Т10-200x600
…

Весь процес виглядає ось так:

Розділення PDF-файлу по «масці»

Також можна цей підхід використовувати для нарізання макетів по одному і одразу з правильним перейменуванням файлів. Колись робив скрипт для перейменування пачки файлів, але тепер можна цей крок пропустити й робити все швидше.

Розділення на файли по одній сторінці

Нюанси

№1. Порядок артбордів/сторінок у файлі має завжди зберігатись і співпадає з «маскою». Тож при зміні порядку, треба міняти й маску.

№2. При збереженні PDF з Ілюстратора рекомендую прибирати прапорець Preserve Illustrator Editing Capabilities. Так при розділенні PDF у файлі не буде нічого, що було поза потрібного артборду. Якщо ж цей прапорець увімкнутий, то навіть якщо ви бачитиме у прев’ю лише один артборд, все одно при відкритті файлу в Ілюстраторі в ньому будуть всі артборди й об’єкти, що були в оригінальному AI-файлі.

Налаштування збереження PDF-файлу
Налаштування при збереженні PDF

№3. Як і з будь-якою автоматизацією її треба уважно перевірити, коли створюєте. Наприклад, можна помилково вказати не ті сторінки в «масці» і файл нарізатиметься неправильно.

Бонус №1: запуск скрипку одразу в теці

Щоб ще прискорити процес і навіть не запускати консоль, то можна зібрати виконавчий файл .command, який запускатиме все в наявній теці.

#!/bin/bash

# Change directory to be where the command is.
cd "$(cd "$(dirname "$0")" > /dev/null && pwd)"
# Run script with arguments
bash pdf-splitter.sh metromap_tram_v1.12.pdf Metromap-Tram-Range.txt

Єдина маніпуляція, яку треба зробити — дати системі права на виконання скрипту в нашій теці:

chmod u+x splitter.command

Таким чином у теку копіюються сам bash-скрипт, маска .txt, вхідний .pdf та у command файлі замінюються значення. Тепер просто зберігаєте PDF, запускайте файл, п’єте каву ☕️, готово.

Скрипт упакований у виконавчий файл

Бонус №2: артборди в AI → «маска»

Якщо ви називали артборди в Ілюстраторі так, як би ви хотіли мати готові файли, то можна теж це використати і скриптом вже в самому AI зберегти всі назви артбордів, як «маску» у текстовому файлі. Знову ChatGPT запропонував доволі простий скрипт, що робить на робочому столі готовий txt-файл з маскою.

Робота скрипта

Трохи допиляв, що він робив одразу потрібний вигляд:

// Function to export artboard names to a text file
function exportArtboardNames() {
    var doc = app.activeDocument;
    var artboards = doc.artboards;
    var file = new File("~/Desktop/artboard_names.txt");
    file.open("w");

    for (var i = 0; i < artboards.length; i++) {
        var artboard = artboards[i];
        var artboardName = artboard.name;
        file.writeln("" + (i + 1) + "=" + artboardName);
    }

    file.close();
    alert("Artboard names exported to ~/Desktop/artboard_names.txt");
}

// Run the exportArtboardNames function
exportArtboardNames();

Напевно було б можна написати скрипт саме для Ілюстратора, який би з «маскою» зберігав певні артборди, але всі подібні скрипти в Adobe Illustrator працюють доволі повільно. Тому найшвидше створювати конвеєр іншими інструментами.

Бонус №3: зробити зі скрипта окрему cli-програму (Mac OS)

Копіювати скрипт у кожну теку не зручно, тож можна піти далі і зробити з цього скрипта cli-програму, яку можна буде викликати просто у певній теці одразу з терміналу (описав як зробити це у Mac OS, але думаю у Windows це так само можливо; якщо хтось напише як це зробити, то додам у статтю).

Для цього модифікуємо спочатку сам скрипт. У першому рядку міняємо шлях до bash:

#!/usr/local/bin/bash

input_file=$1
data_file=$2

# Read page ranges and custom names from the external file into a single array. Requaire bash 4.0
readarray -t page_data < "$data_file"

# Loop through the array and split the PDF
for data in "${page_data[@]}"; do
    IFS="=" read -r range custom_name <<< "$data"
    output_file="${custom_name// /_}.pdf"  # Replace spaces with underscores in the custom name
    pdftk "$input_file" cat $range output "$output_file"
    echo "$output_file — Done"
done

Потім краще прибрати розширення і назвати файл так, як ви будете викликати команду. У моєму випадку — pdfsplitter.

Далі скопіювати файл у директорію ///usr/local/bin//, можна одразу в терміналі:

sudo cp pdfsplitter /usr/local/bin

Тепер можна у терміналі викликати нашу команду. Якщо ж при цьому буде відображатись помилка доступу, на кшталт, «zsh: permission denied: pdfsplitter», то треба дати системі дозвіл використати нашу програму. Наприклад, командою:

chmod 755 /usr/local/bin/pdfsplitter

Відтепер ви самі додали програму у термінал і її можна запускати у будь-якій теці, не копіюючи туди скрипт.

Скрипт, як cli-програма

Завантажити скрипти: * [pdf-splitter.sh](https://www.dropbox.com/scl/fi/zpdpqvcjau4ps7qaoqn9b/pdf-splitter.sh?rlkey=nsgiia85dj5noveqgoab3o9hz&dl=0) — розділювач PDF * [artboard-names-to-file.jsx](https://www.dropbox.com/scl/fi/sequwpl5crthcnsyb8pfn/artboard-names-to-file.jsx?rlkey=0eysee0w68fa99c8yg9vpu4p4&dl=0) — назви артбордів AI у TXT файл * [splitter.command](https://www.dropbox.com/scl/fi/303ikqdr93bt0ypzwgzet/splitter.command?rlkey=7uj309zmg2ijodxpqr42zx1qo&dl=0) — приклад виконавчого файлу запуску скрипта; має розміщуватись в одній теці з маскою та pdf-splitter.sh.

Якщо вам було цікаво та корисно, можете пригостити мене кавою ☕️: на монобанку чи по номеру картки банки 4874100025139125.