Подготовка к захвату мира, закрываю гештальты
Спрашивается, о чём мой проект? А я сам не знаю. Планы меняются. Идей много. Но есть общий базовый функционал. Вот я пока про это. Уже 5 месяцев. После весеннего обострения, в приступе одиночества, хочу поделиться некоторыми наработками.
Первым делом развернул Create React App. Его нужно дорабатывать напильником. Давно уже можно обойти страшную команду eject с помощью react-app-rewired. Грешен, config-overrides.js полностью мой; получилось коряво, хочется переписать на функциональных линзах. Но всё работает: yarn workspaces, babel-плагины, less-loader (для кастомизации Ant-Design), абсолютные пути импорта.
Prettier настроил таким образом, что в проекте один конфиг и для vscode и для коммитов (в корне лежит .prettierrc). В какой-то момент перестал удовлетворять lint-staged, уже не помню — почему. Ему на замену пришел pretty-quick (как подключить, смотри в package.json). Но очень раздражало, что prettier переформатировал служебные json-файлы. Добавил исключения в .prettierignore для package.json и для tsconfig.json — немного меньше мусора в коммитах.
Пару слов про утилиту nvm. В корне лежит .nvmrc с указанной версией связки node + npm, в моём случае «stable». Достаточно выполнить команду nvm use. Очень удобно.
Lerna когда-то казалась страшным чудищем. А в результате я использую всего лишь одну очень удобную команду — lerna publish. Пакеты в моём монорепозитории публикуются на npmjs.com с обновлением собственной версии, которую выбираешь в диалоговом режиме. В сочетании с yarn workspaces, есть возможность разложить проект на пакеты и разрабатывать их одновременно (hot-reload работает для всего кода). Практическое воплощение связности и связанности. Нагуглите, если не знаете, что это такое. Очень помогает управлять сложностью кода. А ещё прикрутил rollup для сборки пакетов, он использует общие настройки typescript хост-приложения монорепозитория.
Про Ant-Design. Удивительно, как много менеджеров и разработчиков не понимают преимуществ собирать дом из готовых кирпичей, и бросаются производить свои собственные кирпичи. Разве обязательно переизобретать реализацию модального окна? Научиться кастомизировать и композировать — это повторно применимая практика, это следующий уровень абстракции в наращивании технологической сложности. Только нужно немного поменять подход к дизайну, учитывая накладываемые ограничения. Плясать придётся от печки, вместо «я так вижу». Но выгода мне представляется очевидной.
Внутри Ant-Design используется less — препроцессор css. Доступно около 700 переменных. Кастомизируй — не хочу. Однако, мой выбор — css-in-js. Тогда надо вытащить все эти переменные в js — внутри less-loader есть опция modifyVars. Чтобы переиспользовать один и тот же theme.js в NodeJS и ES, использовал esm: const requireForES = require('esm')(module /*, options*/)
. Но многие переменные — производные от других, например @primary-color: @blue-6;
; помог Proxy для полей объекта theme: primaryColor: (theme) => theme.blue6
; если поле в theme — это функция, тогда вызвать функцию, и так рекурсивно к следующему полю, пока не дойдём до поля с конечным значением. А ещё есть less-миксины — это js-код упакованный в less; например, скопипастил обратно в js функцию colorPalette: primaryColor5: (theme) => colorPalette(theme.primaryColor, 5)
. Исходики theme.js.
Съел собаку на styled-components. Но не стоит тратить время на рассказы, потому как близится релиз reshadow (очень хочется верить). Может напишу заметку. Шикарная презентация на React Russia 2019. В предвкушении праздника. Пока лишь об одном моменте, включил в настройках vscode "editor.foldingStrategy": "indentation"
, чтобы нормально сворачивать css-код внутри шаблонной строки. Раздражает, что редактор не запоминает свернутое. Надо бы поискать плагин.
Проекты в моих планах разные, но неизменно, что проекты для пользователей. Тогда нужен функционал авторизации. Желательно без паролей. Ответ: Facebook Account Kit. Короткий цифровой код для логина приходит письмом, или SMS (бесплатно), или сообщением в WhatsApp. Написал свой враппер поверх API, пока живёт внутри проекта, как react-компонент. Прекрасно работает. Теперь хочется вынести в npm-пакет, на тот момент я не умел пользоваться lerna + yarn workspaces.
Многие проекты про текстовый контент. Нужен редактор текста. Просто markdown — маловато будет. Да, внутри формата markdown можно добавлять вставки из HTML, но это уже редактор не для массового потребителя, а для хакеров. Выход — блочный редактор. Для блоков необходимо хранить мета-данные. Например, виджет галереи картинок — пару кликов мышкой и всё готово. А ещё хочется переставлять блоки, тоже мышкой. Нравится koenig-editor внутри Ghost и ещё отечественный EditorJS. Понятно, что medium.com — прародитель. Но меня не устраивает функционал, чтобы на 100%. И это не ReactJS. Может быть DraftJS by Facebook? К сожалению, подзаброшен. Вдохновлённый им SlateJS сравнительно выигрывает в моменте. Но SlateJS — это конструктор из плагинов. Может быть есть готовые сборки на его основе? Под спойлером длинный список плюсов-минусов некоторых.
canner-slate-editor
[+] не показывает Hovering Menu при выделении мышкой заголовка, или текста внутри блока с кодом
[-] при завершении операции drag’n'drop для картинки, наблюдается непрорисованный курсор
[+] плюсик с контекстным меню, когда курсор находится в пустой строке вне блока кода (как в Ghost, но там еще плюсик, когда подвести мышку к концу текста)
[+] плюсик с контекстным меню появляется в конце строки (но если строка декорирована, как «H2», то плюсик уже не появляется — это не бага, а фича)
[+] анимация плюсика с контекстным меню (в Ghost такого нет); и плюсик превращается в крестик, когда меню открыто
[-] в контекстном меню присутствуют кнопки форматирования текста (в Ghost там только виджеты)
[+] применение antd-компонентов для инструментов внутри редактора
[+] богатый функционал для загрузки картинки: drag’n'drop, url, open file
[-] картинки можно загружать только по одной (нет виджета галереи)
[+] есть выравнивания картинок и других блоков
[+] редактирование размера картинки (но проще бы, как в Ghost режимы regular-white-full)
[+] применение форматирования markdown
[-] отсутствует drag’n'drop для cards (в терминологии Ghost)
[+] виджет таблицы, как в старом-добром MS Word
[-] по урл можно вставить только видео (в Ghost это виджет «Other…», который поддерживает много другого — «embedded content»)
[-] виджет ссылки не позволяет ее редактировать (в Ghost это можно)
[-] одновременно всплывает Hovering Menu и url-popup ссылки (в Ghost выделение текста скрывает url-popup ссылки)
[-] Hovering Menu залезает за край редактируемой области (в Ghost выравнивается по краю)
react-page (ory-editor)
[+] режим изменения композиции блоков через drag’n'drop
[+] режим изменения размеров картинок и других блоков, если их несколько в одном ряду (но только через drag’n'drop)
[+] режим добавления виджетов (но только через drag’n'drop)
[+] режим «preview result» изменяет поведение виджетов (например: картинка становится кликабельной)
[+] в режиме изменения композиции блоков, блок с картинкой можно вставить в блок с текстом через drag’n'drop — чтобы текст обрамлял картинку; плюс есть «защита от дурака»: так можно вставить только одну картинку
[-] без мышки функционал сильно ограничен
[-] нет растягивания размеров картинок (как в Ghost режимы regular-white-full)
[-] вообще нет форматирования markdown (в Ghost два режима: в тексте, в отдельном виджете)
[-] не очевидно, как удалить блок картинки (нужно перетащить в корзину через drag’n'drop) — нужно сместить иконку корзины за пределы текста
[-] нет рамки фокуса для виджета картинки в режиме редактирования свойств (хотя для виджета HTML5-видео — есть, вероятно индикацию фокуса задает сам браузер)
[+] панель инструментов редактирования текущего элемента (toolbar для текста, или диалог для картинки etc.) всплывает в подвале и закреплена там
[-] режим добавления виджетов возвращает в исходное состояние выбора виджетов после вставки какого-либо виджета, а хотелось бы перейти к редактированию добавленного виджета; вероятно так и задумано: сначала накидать блоки, а уж потом их редактировать по очереди
[-] url ссылки тупо удаляется при клике по кнопке, а хотелось бы popup с отображением url ссылки и диалог редактирования ссылки (в Ghost тоже нет редактирования, только пустое поле ввода для новой ссылки); понятно, что компромиссы из-за возможной коллизии добавления ссылки в ссылку — надо прорабатывать; в sanity один диалог служит для редактирования ссылки (и ее отображения) и для перехода по этой ссылке
[-] в инструменте редактирования картинки отсутствует drag’n'drop на добавление исходной картинки
[-] нет виджета для кода
[-] не реализован drag’n'drop для загрузки картинки
[-] системный диалог выбора файлов для загрузки картинок не фильтрует допустимые файлы (надо отображать только картинки)
[-] в Ghost, в режиме drag’n'drop, анимировано смещаются другие элементы для полоски-указателя, куда будет выполнен drop
[-] в режиме изменения композиции блоков через drag’n'drop, дублировано отображается паразитная полоска-указатель (видимо из-за лишних div-элементов)
netlify-cms-widget-markdown
[+] можно подсмотреть, как поженить slate и remark (remarkSlate.js, slateRemark.js)
[+] встроены плагины slate-edit-list и slate-edit-table
[+] две реализации редактора: RawEditor & VisualEditor
sanity
[+] выбор кропа для картинок (см. вложение) — не относится к slate-js
[+] paste markdown (?)
Ладно, придётся мастерить свою, самую-самую лучшую сборку SlateJS. Может быть даже habr её себе поставит. Одумайтесь, зачем вам VueJS (шутка). Итак, сначала нужна композиция контролов для управления редактором: для добавления новых блоков, для управления выбранным блоком, для изменения настроек блока, для форматирования выделенного текста. Переписывал несколько раз, вроде устоялось, пока нравится. Контролы на базе Ant-Design. Опубликовал npm-пакет slate-controls. Не судите строго — это любимое дитя.
Исходники будущего проекта.