solovyov.net

У Nounry власне редактор побудований з ProseMirror’а (та tiptap, але це не важливо для розповіді). І підхід проузміррора нагадує React трошки: в тебе є в пам’яті модель твого тексту (параграфів та такого іншого), а в HTML він її рендерить. Презентація в HTML ніякого впливу на власне текст документу не має взагалі, і коли ти до DOM-нод додаєш якийсь клас, чи шось редагуєш, він миттєво те все прибиває і HTML виходить чистенький.

Тобто хочеш ти якісь штуки навколо текста показати, декорації якісь? Треба використовувати спеціальний апі для декорацій, авжеж. Робиш плагін (бо в проузміррорі все шо є — плагіни, навіть параграф), в якому шось вирішуєш і повертаєш декорації.

Коли я задумуюсь, скільки всього відбувається кожну транзакцію, прозріваю — кожен плагін треба опитати. Тим не менш, працює відносно непогано. :) Цікаво, чи можна б його було запхати кудись у сервіс-воркер? Здається, що з наявною архітектурою затримка вводу не дозволить…

Ладно, це я відволікся. Значить сів я на тижні зробити так, щоб в посилання була якась декорація, яка дозволить його відкривати — бо по кліку відкривати посилання я зовсім не хочу, це ж не презентатор, а редактор. Ось шось таке, як на картинці.

Ну що там всередині? <a href>url <svg></a>, вірно? Але цікавий нюанс в тому, що віджету (це термінологія проузміррора) треба передати не рядок, а готову DOM-ноду. І для створення ноди я юзаю crelt:

  return crel('span', {class: 'sticky-widget'},
              crel('a', {class:  'sticky-widget-inner badge bg-secondary',
                         target: '_blank',
                         rel:    'noopener noreferer',
                         href:   attrs.href},
                   title + ' ',
                   core.svgiconel('box-arrow-up-right')));

Ну й svgiconel всередині теж використовує такий самий crel. Краса, здавалося б. Один нюанс: іконки нема. В будь-якому іншому місці додаєш її, і вона рендериться, а всередині ProseMirror’a — нема!

Я обшукався, чому PM не рендерить svg, питав у жпт (і клавдії), не знаю, ну реально вбив годину-другу життя (за кілька днів), і випадково попав на обговорення document.createElement десь на Stack Overflow, де чувак жалівся, що свг з серверу показуються, а зроблені на клієнті — ні!

Дивне відчуття, бо я прям пам’ятаю, як я на це попадав колись давно, коли хотів Реактом свг рендерити. Для свг треба не document.createElement(‘svg’), а document.createElementNS('http://www.w3.org/2000/svg', ‘svg’)! 🤦‍♂️

Дуже кльово, що браузер, коли парсить ХТМЛ, може розібратися, а коли ти викликаєш його апі — не може. Консистентно і зручно. Радий, що тепер у мене в голові з’явилася нова крупиночка знання. 😒

(@ tg)