Привет,
Мне пока не удалось заставить это работать ни одним из доступных способов, и я хотел бы узнать, не ошибаюсь ли я в своих ожиданиях.
Я интегрируюсь с моей установкой 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 есть какой-то особенно идиоматический способ сделать всё это, но я надеялся, что для такой лёгкой интеграции не нужно быть экспертом в предметной области.
Буду рад получить здесь какие-либо рекомендации.