테마 구성 요소를 pretix에 통합할 때 발생하는 문제

안녕하세요 -

제가 찾아본 모든 방법을 시도해 보았지만 아직까지 작동하지 않고 있습니다. 제 기대치가 잘못된 것인지 알고 싶습니다.

저는 (이벤트 티켓 판매를 위한) 제 pretix 설치 환경과 연동하고 있습니다. 이 작업은 단순히 게시글에 HTML을 추가하고 pretix의 HTML과 CSS가 포함되도록 하는 것으로 이루어져야 합니다.

<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>

<!-- elsewhere, in a post -->
<pretix-widget event="https://pretix.eu/demo/democon/"></pretix-widget>
<noscript>
   <div class="pretix-widget">
        <div class="pretix-widget-info-message">
            JavaScript is disabled in your browser. To access our ticket shop without JavaScript,
            please <a target="_blank" href="https://pretix.eu/demo/democon/">click here</a>.
        </div>
    </div>
</noscript>

물론, pretix 스크립트는 태그를 기준으로 문서에서 해당 요소를 스캔한 후, 이를 스킨을 적용할 수 있는 항목으로 대체합니다(제가 원하는 방식이죠).

저는 이 연동을 가볍게 수행할 수 있다고(그리고 그렇게 하기를 원한다고) 생각하며, 커스텀 테마 컴포넌트를 사용하여 외부 pretix 스크립트/스타일을 포함하고 게시글에 위젯 HTML을 추가하는 것(즉, 단순히 '설정’만 하는 것)으로 이를 달성할 수 있을 것이라 생각했습니다.

처음으로 CSP 보호 기능(좋은 점)과 allowList(이것도 좋은 점)에 부딪혔습니다. 마찬가지로, CSP 설정을 추가했지만 이제 실제 코드 변경 없이 allowList를 변경할 수 없는 것 같습니다. 그래서 저는 게시글에 ‘flavoured’ HTML을 삽입한 후, 렌더링된 후 이를 변경하려고 시도해야 하는 상황에 놓여 있습니다.

저는 테마 컴포넌트 스펙에서 가벼운 JS(인라인 스크립트 형태)를 사용해 보았습니다. allowList의 [data-*] 예외 조항을 사용하는 것과 같은 아래 코드처럼요:

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에서 이를 수행하는 매우 관용적인(idiomatic) 방식이 있을 것이라고 확신합니다. 하지만 저는 이 가벼운 연동을 수행하기 위해 해당 분야 전문가가 되어야 한다고 생각하지는 않았습니다.

여기서 몇 가지 조언을 얻으면 좋겠습니다.

api.onPageChange()를 검색해 보세요. 이 부분을 처리하기에 좋은 위치를 찾을 수 있습니다.

이 문제를 해결하기 위해 몇 가지 개별적인 요소가 필요했는데, 나중에 참고할 분들을 위해 여기에 정리해 둡니다.

  • <script type="text/discourse-plugin" /> (예상 밖이었습니다)
  • loadScripts (깔끔했습니다)
  • api.decorateCookedElement (처음에 검색해 본 항목은 아니었습니다)
  • api.pageLoaded (유용했습니다)

그리고 '설정’만으로도 pretix와 제 Discourse 사이트를 성공적으로 통합할 수 있었습니다.