FigmaGen: Автоматизация стилей в iOS-приложении

q339vrmcwuw1jf24mujq60enevy.png

Сейчас многие команды систематизируют дизайн своих приложений. Мы решили пойти дальше и автоматизировать синхронизацию кода с нашей библиотекой компонентов. 

Дело в том, что в hh для проектирования UI используется небезызвестный сервис Figma, который, кроме прочих своих плюсов, имеет открытый API. А это в свою очередь открывает широкие возможности для разработчиков, чем мы и решили воспользоваться.

Так родилась идея проекта FigmaGen — инструмента, который синхронизирует код с библиотекой компонентов в Figma. Сначала он выглядел, как эксперимент, специфичный только для нашего продукта, но получилось более универсальное решение, и в этой статье мы поделимся первыми плодами своей разработки.


Как это работает

Figma позволяет построить библиотеку компонентов и стилей, которые могут быть глобально переиспользованы. Идеально, если эти компоненты сгруппированы и находятся в отдельном файле, тогда дизайнерам будет проще с ними работать, а разработчики получат единый источник знаний для реализации этих сущностей в коде.

Мы подготовили небольшой демо-файл в Figma для стилей, который доступен по ссылке и выглядит так:

ikbw3uhz1nxaebuj3gxc8stbw10.png

FigmaGen получает такие файлы Figma, используя его API, затем извлекает все необходимые данные и рендерит их с помощью Stencil-шаблонов в исходный код. Все эти шаги могут быть настроены в файле конфигурации, и тогда для запуска генерации необходимо лишь выполнить команду:

figmagen generate

На текущий момент подготовки статьи FigmaGen поддерживает генерацию цветовых и текстовых стилей, которые в результате могут быть использованы так:

titleLabel.attributedText = "Hello world".styled(
    .title2, 
    textColor: Colors.imperial
)

view.backgroundColor = Colors.whiteSmoke

Весь генерируемый код при этом может быть легко кастомизирован с использованием собственных Stencil-шаблонов. Следовательно, нет ограничений на платформы, необходимо реализовать только шаблон для соответствующего языка и указать путь к нему в конфигурации. Дополнительным бонусом является использование в FigmaGen фреймворка StencilSwiftKit, добавляющего полезные фильтры и теги в шаблонах.


Установка

Установка FigmaGen стандартна для подобных инструментов, и есть несколько основных способов:


  • CocoaPods: добавить строку pod 'FigmaGen' в Podfile и выполнить команду pod install --repo-update.
  • Homebrew: выполнить команду brew install hhru/tap/FigmaGen.
  • Вручную скачать и распаковать zip-архив свежего релиза из репозитория.

В случае установки с помощью CocoaPods команда генерации должна включать путь к папке Pods/FigmaGen:

Pods/FigmaGen/figmagen generate


Установка средствами CocoaPods является рекомендуемым способом, так как позволяет фиксировать версию FigmaGen на всех машинах команды.


Конфигурация

Для конфигурации FigmaGen необходимо создать файл .figmagen.yml в корневой папке проекта. При необходимости можно указать другой путь в параметре --config команды генерации, например:

figmagen generate --config 'MyFolder/figmagen.yml'

Сам файл конфигурации имеет формат YAML и разделен на несколько разделов:


  • base: базовые параметры, актуальные для всех остальных разделов. Любой параметр из этого раздела может быть переопределен для конфигурации самой подкоманды генерации.
  • colors: параметры подкоманды генерации цветов.
  • textStyles: параметры подкоманды генерации текстовых стилей.

Однако, если какой-либо раздел подкоманды генерации отсутствует в конфигурации, то эта подкоманда будет пропущена.


Базовые параметры

Чтобы не дублировать некоторые поля в конфигурации, мы выделили их в отдельный раздел base, который содержит параметры, актуальные для каждой подкоманды генерации:


  • accessToken: строка с токеном доступа Figma.
  • fileKey: строка с идентификатором файла Figma.

Эти параметры используются теми подкомандами генерации, для которых они не определены, например:

base:
  accessToken: '27482-71b3313c-0e88-481b-8c93-0e465ab8a868'

colors:
  fileKey: 'ZvsRf99Ik11qS4PjS6MAFc'
textStyles:
  fileKey: 'D1rfFI220qwaG8fD8iBqWa'

В этом случае будут сгенерированы цвета и текстовые стили из разных файлов Figma, но с использованием одного и того же токена доступа.


Токен доступа

Для получения файла Figma необходима авторизация, которая осуществляется путем передачи персонального токена доступа. Такой токен может быть создан в несколько простых шагов:


  • Открыть настройки аккаунта в Figma.
  • Нажать кнопку «Create a new personal access token» в разделе «Personal Access Tokens».
  • Ввести описание для создаваемого токена (например, «FigmaGen»).
  • Скопировать созданный токен в буфер обмена.

jwqmo0s75iotwuc67g64gac8h18.png

Далее необходимо вставить полученный токен в поле accessToken конфигурации. Если этот токен позволяет получить доступ ко всем файлам Figma, которые фигурируют в конфигурации, то достаточно определить его только в разделе base.


В целях безопасности рекомендуется использовать токен специально созданного пользователя, который имеет права только на чтение файла Figma.


Файлы Figma

FigmaGen запрашивает файл Figma по его стандартному идентификатору, который может быть получен из URL в адресной строке браузера.

nia8bnracxfynfnoypssf4brwmw.png

В общем виде этот URL имеет следующий формат:

https://www.figma.com/file/<идентификатор>/<название>?node-id=<идентификатор выделенного узла>

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


Настройки генерации

Помимо базовых параметров, для каждой подкоманды генерации необходимо определить следующие настройки:


  • destinationPath: путь для сохранения сгенерированного файла.
  • templatePath: путь к файлу Stencil-шаблона. Если параметр пропущен, то будет использован стандартный шаблон.
  • includingNodes: идентификаторы фреймов, которые должны быть использованы при генерации кода. Если этот параметр пропущен, то будут использованы все узлы файла.
  • excludingNodes: идентификаторы фреймов, которые должны быть проигнорированы при генерации кода. Если этот параметр пропущен, то будут использованы все фреймы файла, указанные в поле includingNodes.

Для примера, настройки генерации текстовых стилей могут иметь следующий вид:

textStyles:
  destinationPath: Sources/Generated/TextStyle.swift
  templatePath: Templates/TextStyles.stencil
  includingNodes:
    - 7:24
    - 3:19
...

С такой конфигурацией будут сгенерированы только те текстовые стили, которые находятся во фреймах с идентификаторами »7:24» и »3:19».


Фильтрация узлов

Библиотека нашего проекта содержит компоненты, специфичные для определенных платформ. Например, в текстовых стилях отличается шрифт: в iOS — это San Francisco, а в Android — Roboto. Чтобы не генерировать лишний код, необходима фильтрация таких стилей, но, увы, стандартных средств Figma тут недостаточно, и нами рассматривалась пара вариантов ее реализации:


  • Систематизация названий стилей и компонентов: в этом случае, название каждого элемента содержало бы некоторую мета-информацию, которая соответствующим образом обрабатывалась в FigmaGen.
  • Фильтрация по идентификаторам фреймов: все стили сгруппированы в отдельные фреймы по типу и платформе, и идентификаторы этих фреймов зафиксированы в конфигурации FigmaGen.

На данном этапе мы выбрали второй способ, так как не хотели ради автоматизации на стороне разработки менять процессы команды дизайнеров. Так в параметрах includingNodes и excludingNodes можно перечислить идентификаторы фреймов, которые должны быть, соответственно, включены или исключены для подкоманд генерации.

Для получения самих идентификаторов также можно использовать адресную строку браузера. Для этого необходимо выделить нужный фрейм в Figma, и в URL окажется его идентификатор в значении параметра node-id. В конфигурацию можно вставлять как экранированный, так и неэкранированный идентификатор.

ykm9lm4khbqzud_67jvibahfcn8.png

Возможно, для реализации нового функционала нам все-таки будет недостаточно фильтрации фреймов по их идентификаторам. В этом случае мы обязательно расширим возможности FigmaGen, если к этому моменту не появится стандартное решение от Figma, например, в виде тегов для компонентов.


Генерация

В отдельном репозитории есть готовый к бою демо-проект, можно загрузить его и смело ставить эксперименты. В нем FigmaGen устанавливается средствами CocoaPods, поэтому сначала следует выполнить команду pod install. Для удобства вызов команды генерации добавлен в фазу сборки, и каждый ее запуск обновляет все генерируемые файлы.

Наигравшись с кодом для стилей из демо-библиотеки, можно скопировать ее файл в собственный аккаунт Figma, нажав кнопку «Duplicate to your Drafts».

7gykfl2s6zolz6cattdfw3d89fi.png

Это позволит модифицировать стили и лучше понимать, как генерируется их код. Следует только изменить конфигурацию FigmaGen, указав данные нового файла.

Также демо-проект отлично подойдет в качестве плейграунда для кастомизации Stencil-шаблонов, которые находятся в папке Templates. Можно редактировать их прямо в Xcode и одним запуском сборки проекта проверять корректность как самих шаблонов, так и генерируемого ими кода.


Интеграция в проект

Различные инструменты генерации кода (SwiftGen, R.Swift) рекомендуется запускать в фазе сборки проекта, потому что они используют локальные ресурсы, которые могут меняться в ходе разработки. В этом случае такая интеграция гарантирует, что в сборку всегда попадает самый актуальный код.

FigmaGen же не использует локальные ресурсы, все данные для генерации находятся в Figma, следовательно, не имеет смысла вызывать его для каждой сборки. Гораздо лучше единожды сгенерировать код и периодически обновлять при появлении новых версий библиотеки компонентов, либо при обновлении версии самого FigmaGen.

Сейчас в нашем проекте обновлением генерируемого кода занимается дежурный разработчик. В следующих же версиях FigmaGen планируется добавить поддержку версионирования файлов Figma, тогда, возможно, и эту процедуру удастся автоматизировать, но это уже совсем другая история.

rziiuprdumkdaaoqbagw_gjfmg8.png


Подводя итоги

Это лишь первые наши шаги на пути создания мощного инструмента, который позволит разработчикам максимально автоматизировать всю рутину, связанную с дизайн-системой. 

Завершена самая сложная часть проекта: определена архитектура, сформированы основные переиспользуемые узлы и настроена инфраструктура. Это позволяет нам быстро наращивать новый функционал FigmaGen, а в планах у нас еще много интересного:


  • версионирование файлов Figma
  • автоматизация изображений
  • поддержка светлой и темной тем
  • генерация кода для градиентов, теней, обводки и т.д.

И наверняка, очень скоро появятся новые версии с этими фичами, следите за релизами в репозитории FigmaGen.

На этом все. Будем рады обратной связи в комментариях. Пока!

© Habrahabr.ru