Discourse의 Ember API를 사용해 iframe을 삽입할 때 문제가 발생합니다

이 플러그인은 Discourse에 i-frame을 삽입하며 여기에서 찾을 수 있습니다

최신 버전으로 비교적 업데이트를 유지하고 있어, 이 호환성 문제가 최근에 발생했습니다. 현재 3.3.0.beta1-dev 버전을 실행 중입니다.

콘솔에서 다음과 같은 3개의 오류 메시지를 확인합니다:

docuss.js:225 Uncaught (in promise) ReferenceError: Ember is not defined
at docuss.js:225:1

아마도 이 Ember 객체가 최근 Discourse 버전에서 Discourse API에서 제거되었을 가능성이 높으며, 이 오류는 해당 객체에 영향을 미치는 Discourse 업그레이드 후에 발생하는 것으로 보입니다.

제가 적용한 모든 수정 사항은 다음과 같습니다:

수정 1

assets\javascripts\discourse\initializers\docuss.js.es6
232행

기존:

const afterRender = res =>
  new Promise(resolve => {
    // @ts-ignore
    Ember.run.schedule('afterRender', null, () => resolve(res))

변경 후:

import { schedule } from '@ember/runloop'

const afterRender = res =>
  new Promise(resolve => {
     schedule('afterRender', null, () => resolve(res))
  })

수정 2

assets\javascripts\discourse\lib\DcsIFrame.js.es6
858행

기존:

  const afterRender = res =>
	new Promise(resolve => {
		Ember.run.schedule('afterRender', null, () => resolve(res))
	})

변경 후:

	import { schedule } from '@ember/runloop'

	const afterRender = res =>
	  new Promise(resolve => {
		schedule('afterRender', null, () => resolve(res))
	  })

수정 3

assets\javascripts\discourse\lib\onDidTransition.js.es6
239행

기존:

const afterRender = res =>
  new Promise(resolve => {
    Ember.run.schedule('afterRender', null, () => resolve(res))

변경 후:

import { schedule } from '@ember/runloop'

const afterRender = res =>
  new Promise(resolve => {
      schedule('afterRender', null, () => resolve(res))

이로 인해 콘솔의 모든 오류 메시지는 사라졌지만, 다음과 같은 새로운 오류들이 발생했습니다:

 Discourse v3.3.0.beta1-dev — https://github.com/discourse/discourse/commits/4c7d58a883 — Ember v5.5.0
app.js:197 Uncaught ReferenceError: Ember is not defined
    at s.callback (docuss.js:210:1)
    at s.exports (loader.js:106:1)
    at requireModule (loader.js:27:1)
    at y (app.js:171:18)
    at w (app.js:194:19)
    at app.js:157:29
    at e.start (app.js:51:5)
    at HTMLDocument.<anonymous> (start-app.js:5:7)
    at discourse-boot.js:20:12
    at discourse-boot.js:1:1

플러그인이 켜져 있는 라이브 플랫폼이 도움이 될 수 있으니 참고하세요

Ember API 객체 변경으로 인한 문제를 겪어 보신 분이 계신가요? 이 문제를 해결하는 방법에 대한 조언을 주시면 감사하겠습니다.

안녕하세요!

이것을 놓치고 계신 것 같습니다:

아래와 같은 방식으로 처리하실 수 있을 것 같습니다. 이 방법은 여전히 동작할 것입니다.

import { observes } from "discourse-common/utils/decorators";

@observes("model.tags")
tagsChanged() {

}

참고로, 컴포저 컨트롤러는 이제 서비스로 이동되었습니다.

GitHub 페이지에서 추천된 대안을 확인해 보셨나요?

저자는 여기에서 활동하고 있는 것으로 알고 있습니다.

@Heliosurge 제안해 주셔서 감사합니다. 다만 기존 라이브러리가 프로젝트에 깊숙이 통합되어 있어서, 저자의 허락을 받아 직접 유지보수를 이어가게 되었습니다.

현재 오픈소스 커뮤니티에서 관련 기술을 갖춘 개발자가 다소 부족한 상황입니다.

응, 완전히 말이 돼.

@Arkshine, 도움 주셔서 감사합니다. 내 노트북이 대체 충전기로 충전 회로가 타버려서 고장 났고, 어제 노트북을 수리할 때까지 테스트를 해볼 수 없었습니다.

import 문장을 페이지 맨 위에 넣고 그 아래에 당신의 코드를 넣었지만, 해당 코드나 유사한 변형 코드를 추가하려고 하면 구문 오류가 발생하고 있습니다:

Visual Basic Studio가 이러한 오류를 감지합니다:

// New tagsChanged function with @observes decorator
@observes("model.tags")
tagsChanged() {
  // See if it is a balloon tag

이 줄의 끝 괄호: tagsChanged() {

에 대해 다음과 같은 오류 메시지가 표시됩니다:
‘;’ expected.ts(1005)

  1. 코드의 마지막 괄호에도 다음과 같은 메시지와 함께 오류가 표시됩니다:

‘}’ expected.ts(1005)
docuss.js.es6(219, 54): The parser expected to find a ‘}’ to match the ‘{’ token here.

이것은 219번째 줄입니다:
tagsChanged: Ember.observer('model.tags', function() {

빌드를 시도할 때 내 서버는 이렇게 말합니다:

  251 |     }, 0);
  252 |   }
> 253 | }.observes("model.tags"),
      |                          ^
        in /tmp/broccoli-6523ExbXtskE5c0h/out-1067-funnel
        at Babel (Babel: discourse-plugins)
  - name: Error
  - nodeAnnotation: Babel: discourse-plugins
  - nodeName: Babel
  - originalErrorMessage: /var/www/discourse/app/assets/javascripts/discourse/discourse/plugins/docuss/discourse/initializers/docuss.js: Unexpected token (253:25)

왜 그런지 모르겠지만, 이 수정이 제대로 작동하지 않았고, 여러 가지 변형 시도도 마찬가지였습니다. 다른 파일에서는 아무 문제없이 작동했기 때문에 좀 이상합니다. 한동안 다른 일에 집중하다가도 계속 신경 쓰이더군요.

지금은 다시 살펴보고 있지만, 문제가 발생하는 원인을 찾지 못하고 있습니다. 원래 상태로 되돌려 두었습니다. 새로운 Ember API로 업데이트하려면 여기서 무엇을 수정해야 하는지 아시는 분 계신가요?

다음과 같은 몇 가지 포인트를 안내해 드립니다:

  • 사이트 설정이 서비스로 이동되었습니다:

    const siteSettings = container.lookup('service:site-settings');
    if (!siteSettings.docuss_enabled) {
      return;
    }
    
  • location:discourse-location → location:history

  • afterRender().then(() => onAfterRender(container));
    afterRender는 컴포넌트 클래스의 메서드 위에 붙이는 데코레이터입니다. 함수로 직접 사용하는 것은 의도된 사용법이 아닙니다.
    아마도 (필요해 보이지는 않지만) 아래처럼 사용하려는 것 같습니다:

    import { schedule } from '@ember/runloop';
    schedule("afterRender", () => onAfterRender(container))
    
  • composeStateChanged 함수에서 상당 부분의 코드가 빠져 있는 것 같습니다.
    또한, 여기서 라우터 서비스를 사용할 수 있습니다: container.lookup('router:main').transitionTo(path); → this.router.transitionTo(path);

  • 헤더가 현대화되었습니다. 현재 컨텍스트에서 home-logo 위젯의 커스터마이징은 비추천(deprecated)됩니다. 자세한 내용은 여기에서 확인하세요: Upcoming Header Changes - Preparing Themes and Plugins.
    당신의 경우, glimmer header mode 설정을 auto 또는 enabled로 해야 합니다. 그런 다음 플러그인 아웃렛을 사용하여 콘텐츠를 교체할 수 있습니다:

    api.renderInOutlet("home-logo-contents", <template>
      <HomeLogoContents
        @logoSmallUrl={{container.dcsHeaderLogo._smallLogoUrl}}
        @logoUrl={{container.dcsHeaderLogo._logoUrl}}
        @minimized={{@outletArgs.minimized}}
        @mobileLogoUrl={{container.dcsHeaderLogo._mobileLogoUrl}}
        @showMobileLogo={{@outletArgs.showMobileLogo}}
        @title={{@outletArgs.title}}
      />
    </template>);
    

    참고: glimmer <template> 문법을 사용하려면 파일 확장자를 .gjs로 변경해야 합니다.
    또한 아래 방법으로 사용할 수도 있습니다:

     api.registerValueTransformer("home-logo-image-url", (transformer) => {
        let url = transformer.value;
        if (transformer.context.name === 'logo') {
          url = container.dcsHeaderLogo._logoUrl;
        } else if (transformer.context.name === 'logo_small') {
          url = container.dcsHeaderLogo._smallLogoUrl;
        } else if (transformer.context.name === 'logo_mobile') {
          url = container.dcsHeaderLogo._mobileLogoUrl;
        }
        return url;
      });
    

    URL을 변경하려면:

    api.registerValueTransformer("home-logo-href", () => container.dcsHeaderLogo._href);
    

    참고: setLogo에서 다시 렌더링하는 코드는 glimmer 컴포넌트에서 작동하지 않을 것으로 생각됩니다.

    테스트 후 참고: 그러나 두 솔루션 모두 JSON에서 로고를 가져올 수 있기 전에 헤더가 렌더링되므로 작동하지 않습니다. 이에 대한 즉각적인 해결책은 없습니다. 더 나은 방법이 있는지 확실하지 않습니다: JSON 로딩을 서비스로 이동하고 결과를 추적하는 것이 좋겠습니다. 그런 다음 위 플러그인 아웃렛을 glimmer 컴포넌트와 함께 사용하세요. 이렇게 하면 추적 변수에 기반하여 컴포넌트에서 자동으로 업데이트를 트리거할 수 있습니다.

이렇게 하면 어딘가에서는 작동하는 것 같습니다. 여전히 컴포저(composer)처럼 작동하지 않는 부분이 있습니다. 이 부분에 대해 깊이 살펴보지는 않았습니다. 최소한 더 이상 차단 오류(blocking error)는 발생하지 않습니다. :slightly_smiling_face:

도움이 되기를 바랍니다.

정말 도움이 되네요, 감사합니다 :slight_smile: