Некоторые проблемы при настройке компонента темы для интеграции с pretix

Привет,

Мне пока не удалось заставить это работать ни одним из доступных способов, и я хотел бы узнать, не ошибаюсь ли я в своих ожиданиях.

Я интегрируюсь с моей установкой pretix (для продажи билетов на мероприятия). Это должно сводиться к простому добавлению HTML в пост и обеспечению включения HTML и CSS pretix.

<link rel="stylesheet" type="text/css" href="https://pretix.eu/demo/democon/widget/v1.css">
<script type="text/javascript" src="https://pretix.eu/widget/v1.en.js" async></script>

<!-- в другом месте, в посте -->
<pretix-widget event="https://pretix.eu/demo/democon/"></pretix-widget>
<noscript>
   <div class="pretix-widget">
        <div class="pretix-widget-info-message">
            В вашем браузере отключен JavaScript. Чтобы получить доступ к нашему магазину билетов без JavaScript,
            пожалуйста, <a target="_blank" href="https://pretix.eu/demo/democon/">нажмите здесь</a>.
        </div>
    </div>
</noscript>

Очевидно, что скрипты pretix сканируют документ на наличие соответствующих элементов по тегу, а затем заменяют их на настраиваемые записи (что мне и нужно).

Я считаю, что могу (и хочу) реализовать эту интеграцию минимальными усилиями, и думал, что смогу просто использовать компоненты пользовательской темы, включив внешние скрипты и стили pretix, а также добавив HTML виджета в посты (то есть только через «конфигурацию»).

Сначала я столкнулся с защитой CSP (хорошо) и allowList (тоже хорошо). Аналогично, я добавил конфигурацию CSP, но теперь, похоже, не могу изменить allowList без фактических изменений в коде — так что мне приходится вставлять «модифицированный» HTML в посты, а затем пытаться изменять их после рендеринга.

Я попытался использовать небольшой JS в спецификации компонента темы (просто как встроенный скрипт) — что-то вроде этого, используя исключение [data-*] из allowList:

function upgradeWidgets() {
    const divsWithDataEvent = document.querySelectorAll('div[data-event]');

    divsWithDataEvent.forEach((div) => {
      const attributes = div.attributes;
    
      for (let i = 0; i < attributes.length; i++) {
        const attr = attributes[i];
        if (attr.nodeName.startsWith('data-')) {
          const newAttrName = attr.nodeName.replace('data-', '');
          const attrValue = attr.nodeValue;
    
          div.setAttribute(newAttrName, attrValue);
          div.removeAttribute(attr.nodeName);
        }
      }
    });
}

Конечно, это теперь подвержено проблемам с таймингом — я не могу использовать событие onload (скрипт удаляется из компонента темы?!), и ни одно другое событие DOM, которое я могу перехватить из скриптов, не происходит в момент, когда HTML этого поста надёжно доступен в документе.

Я уверен, что в Discourse есть какой-то особенно идиоматический способ сделать всё это, но я надеялся, что для такой лёгкой интеграции не нужно быть экспертом в предметной области.

Буду рад получить здесь какие-либо рекомендации.

Поиск api.onPageChange(), который станет отличным местом для обработки этого.

Так что для решения этой задачи потребовалось несколько отдельных компонентов, которые я отмечу здесь для будущих исследователей.

  • <script type="text/discourse-plugin" /> (удивительно)
  • loadScripts (неплохо)
  • api.decorateCookedElement (не первое, что пришло в голову искать)
  • api.pageLoaded (полезно)

И только с помощью «configuration» мне удалось интегрировать pretix и мой сайт на Discourse.