Источник: Nuances of Programming
В этой статье мы с вами приступим к процессу создания пользовательской платформы. Но прежде, пожалуйста, просмотрите ещё раз предыдущие статьи, чтобы убедиться, что вы понимаете, как работают платформы Angular.
Как было сказано в первой статье, Angular-приложения могут запускаться в разных средах благодаря абстракции. Довольно большая часть Angular описывается абстрактными классами. Мы используем разные платформы, каждая из которых предоставляет собственную реализацию этих абстрактных классов. Поэтому, чтобы создать платформу терминала, нам нужно просто обеспечить соответствующие реализации сервисам Angular.
Начнём с самой важной части терминала платформы — визуализатора. Angular использует абстракцию Renderer для выполнения динамической визуализации приложения. Визуализатор — это всего лишь абстрактный класс, поэтому мы будем создавать реализацию, которая покажет приложения внутри системного терминала с использованием графики ASCII.
Но как мы будем визуализировать приложения внутри системного терминала? Думаю, самое простое — это найти подходящую библиотеку, способную создавать виджеты в терминале с помощью графики ASCII. Я решил использовать blessed — библиотеку с высокоуровневым API терминала для node.js. Первым делом давайте установим библиотеку следующей командой:
npm install blessed @types/blessed
Поскольку для визуализации пользовательского интерфейса я решил использовать специфическую библиотеку, нам здесь ещё нужно создать что-то вроде адаптера. Надо найти способ подружить интерфейс Angular-визуализатора с интерфейсом нашей библиотеки.
Вот упрощённое описание визуализатора на Angular:
В его обязанности входит создание и удаление элементов, добавление классов и атрибутов, регистрация слушателей событий и т.д.
С другой стороны, у нас есть библиотека со следующим интерфейсом:
Заметьте, что blessed – это обыкновенная библиотека node.js, которая предоставляет screen и ряд компонентов. Screen – это что-то вроде document браузера и служит корневым элементом приложения, а также содержит несколько полезных интерфейсов API.
Экран
Приступим к интеграции нашего визуализатора со screen. Прежде всего, создаём отдельный сервис Screen для визуализатора.
Здесь у нас базовая реализация.
Сервис отвечает за создание экрана и настройку слушателя выхода. Часто приложения, запускаемые из терминала, при нажатии комбинации control+c закрываются. Поэтому нам надо слушать это событие на экране и реагировать на него выходом из процесса.
process.exit — это стандартный API node.js, с помощью которого скрипт может выйти сам, используя необходимый код. 0 означает, что процесс завершается без ошибок.
Кроме того, Screen даёт возможность выбрать корневой элемент для нашего приложения с помощью вызова selectRootElement.
Реестр элементов
У нас есть Screen. Мы можем выбрать корневой элемент. Самое время заняться созданием элементов.
Как уже было сказано, blessed даёт возможность создавать элементы на экране через набор функций, экспортированных непосредственно через пакет blessed. В то же время Angular-визуализатор использует единую функцию createElement. Поэтому нам нужно что-то вроде адаптера для логики создания этого элемента.
Например, я решил поместить логику создания элементов blessed в специальный сервис ElementsRegistry, который отвечает за создание элементов blessed посредством единой функции createElement:
Как видим, ElementsRegistry имеет единый метод createElement, который пытается найти требуемый элемент на карте элементов и вернуть экземпляр этого элемента. В случае если элемент не найден, ElementsRegistry возвращается к элементу box, который является аналогом элемента div в браузере.
Теперь у нас есть всё необходимое для создания визуализатора, который будет выводить приложения на экран из системного терминала с помощью графики ASCII.
Вот базовая реализация визуализатора:
Я решил реализовать здесь лишь малую часть всех требуемых методов, оставив остальные реализации вам. Итак, здесь у нас есть класс TerminalRenderer, который реализует интерфейс Renderer2. Он использует приведённые выше Screen и ElementsRegistry для создания элементов.
Обратите внимание, что здесь TerminalRenderer не является сервисом Injectable. Angular требует, чтобы Renderer создавался через RendererFactory. Давайте создадим его:
TerminalRendererFactory здесь реализует интерфейс RendererFactory2 и только один метод — createRenderer, который создаёт новый экземпляр с требующимися сервисами.
На этом этапе у нас есть полнофункциональный TerminalRenderer, способный выводить Angular-приложения на экран из системного терминала с помощью графики ASCII. Но нам ещё много чего надо добавить. Продолжим в заключительной части 🔥.
Читайте также:
Читайте нас в телеграмме и vk
Перевод статьи Nikita Poltoratsky: Angular Platforms in depth. Part 3. Rendering Angular applications in Terminal