라우트 템플릿에 .gjs를 사용할 수 있나요?

현재 라우트에서 Glimmer 컴포넌트가 지원되나요?

Discourse의 경우 답이 "아니오"일 것 같지만, 다른 답변을 듣게 된다면 기쁠 것입니다.

네, 현재 Discourse에서 라우트 템플릿에 .gjs 파일을 사용할 수 있습니다. 실제로 오늘 코어에서 대량의 템플릿을 이 형식으로 전환했습니다. 예시를 확인하려면 https://github.com/discourse/discourse/tree/main/app/assets/javascripts/discourse/app/templates를 참고하세요.

해당 "누군가"는 바로 Discourse입니다. 우리는 ember-route-template의 개발을 후원했으며, 이 프로젝트는 우리의 GitHub 조직에 소속되어 있습니다. :slight_smile:

아직 최신 Ember 6.x를 사용하지는 않고 있지만, 해당 기능을 활성화하기 위해 이 애드온을 사용하고 있습니다.

아, 멋지네요! 빠른 답변 감사합니다!

하하, 그게 Discourse의 GitHub에 있는 건 전혀 몰랐네요. 좋은 지적이네요. :slight_smile:

앱에 새 라우트를 추가하는 것이 매우 직관적이지 않다는 것을 발견했습니다. 다른 사람들을 위해 여기 문서로 남깁니다.

저는 루트 레벨에 /print 라우트를 추가하고 싶었습니다.

제 환경에서 작동한 최종 코드는 다음과 같습니다. county-fence는 제 플러그인 이름이므로, 이것을 자신의 플러그인 이름으로 교체하세요.

Ember Route

assets/javascripts/discourse/routes/county-fence-route-map.js.es6

export default function() {
  this.route('print', { path: '/print' });
}

assets/javascripts/discourse/routes/print.js

import Route from "@ember/routing/route";

export default class PrintRoute extends Route {
  model() {
    return { message: "This is a custom print page!" };
  }
}

assets/javascripts/discourse/templates/print.gjs

import RouteTemplate from "ember-route-template";
import ...;

export default RouteTemplate(
  <template>
    ...
  </template>
)

API Route

plugin.rb

after_initialize do
  require_relative "app/controllers/print_controller"
end

app/controllers/print_controller.rb

# frozen_string_literal: true
# HTTP Status codes: https://github.com/discourse/discourse/blob/main/lib/discourse.rb

class ::CountyFence::PrintController < ::ApplicationController
  requires_plugin CountyFence::PLUGIN_NAME


  def save_print
  end

  def list_prints
    render json: { name: "donut", description: "delicious!" }
  end

  def get_print
  end

end

Discourse::Application.routes.append do
  post "/print" => "county_fence/print#save_print"
  get "/print" => "county_fence/print#list_prints"
  get "/print/:id" => "county_fence/print#get_print"
end

레이아웃, 내비게이션 바, 사이트의 CSS 없이 빈 페이지를 얻을 수 있는 방법이 있을까요? Glimmer 컴포넌트를 사용하려고 하는데, 웹사이트 스타일은 인쇄용 페이지를 생성하는 데 도움이 되지 않습니다.

실제로 인쇄되는 페이지에 대한 스타일링만 필요한 경우, 그리고 페이지를 볼 때 네비게이션 바나 추가 요소가 보이는 것을 개의치 않는다면, 인쇄 시 스타일링을 변경하기 위해 @media print CSS 선택자를 사용할 수 있습니다. Discourse는 이미 인쇄 시 많은 요소를 숨기고 있습니다 (discourse/app/assets/stylesheets/common/printer-friendly.scss at main · discourse/discourse · GitHub). Firefox의 검사 모드에서 print media simulation 모드를 사용하여 페이지를 미리 볼 수 있습니다. Chrome의 검사 모드에도 동일한 기능이 있어야 합니다.

인쇄 모드뿐만 아니라 일반 웹 브라우저에서도 완전히 빈 캔버스가 필요하다면, CSS 트릭을 사용할 수 있습니다.
가령 glimmer 컴포넌트의 루트 div에 id="print-component__root"가 있다고 가정하면, :has() 선택자(또는 glimmer 컴포넌트 라이프사이클에서 body에 클래스를 추가/제거하는 방식)를 사용하여 CSS가 그 존재를 확인하고 선택적으로 스타일링을 적용할 수 있습니다.

body:has(#print-component__root) {
  header,
  .avatar,
  .sidebar-wrapper,
  ... {
    all: unset !important;  // all: unset은 약간 과할 수 있음
    display: none !important;
  }
}

#print-component__root {
  // 일반 스타일링
}

DOM 요소를 실제로 제거하는 더 나은, 더 깔끔한 방법이 있을 수 있지만, 모든 것을 초기화하기 위한 좋은 대안은 CSS입니다.

제 SCSS가 로드되지 않습니다. 혹시 아이디어가 있으신가요? 코어의 채팅 플러그인 문서에 따라 파일을 설정했습니다.

plugins.rb에는 다음과 같이 작성했습니다:

register_asset "stylesheets/common/index.scss"

assets/stylesheets/common/index.scss에는:

@import "common";

assets/stylesheets/common/common.scss에는:

body:has(#print-root) {
  header,
  .avatar,
  .sidebar-wrapper {
    all: unset;  // all: unset은 좀 과할 수 있습니다
    display: none !important;
  }
}

SCSS 로딩 문제인지, 아니면 제가 제공한 스타일 규칙의 문제인지 확인해 보려면, :has() 셀렉터 없이 스타일을 추가해 보세요. 다음과 같이요:

.sidebar-wrapper {
  outline: 5px solid red;
}

또는 Rails 서버를 재시작해 보는 것도 좋습니다. 과거에 register_asset 호출을 추가하거나 제거할 때 Docker 컨테이너를 완전히 재시작해야 했던 문제가 있었던 적이 있습니다.

  • :has() 선택자를 제거했습니다.
  • @import 문이 문제인지 확인하기 위해 코드를 index.scss에 넣었습니다.
  • d/rake assets:clobber tmp:cleard/rails s를 실행했습니다.

아직까지 로딩이 되지 않습니다.

대부분의 다른 파일은 브라우저에서 자동 재로드를 유발합니다. 하지만 이 파일은 그렇지 않습니다. 그래서 문제가 register_asset에 있는 것 같습니다. register_asset가 자동으로 assets 폴더를 조회하는 것 아닌가요? 제가 보고 있는 모든 예제에서는 그렇게 되어 있습니다.

d/rails cDiscoursePluginRegistry.stylesheets를 확인하면 다음과 같은 결과가 표시됩니다:

"county-fence"=>#<Set: {"/src/plugins/county-fence/assets/stylesheets/common/index.scss"}>

즉, 무언가 일어나고 있는 것입니다. ^^

d/rails s 로그에서 다음 오류를 발견했습니다: No such file or directory @ rb_sysopen - /src/app/assets/stylesheets/plugin-cf.scss.

즉, 플러그인이 /plugins 폴더에 county-fence라는 이름의 심볼릭 링크로 연결되어 있고, plugins.rb에서도 제 플러그인을 명시적으로 county-fence로 지정해 두었는데도, 어떤 코드는 실제 디렉터리 이름인 plugin-cf를 읽고 제 플러그인의 컴파일된 CSS 이름을 이에 맞춰 가정하고 있습니다.

이것은 버그인가요, 아니면 의도된 기능인가요? :smiley:

제 생각에는 이 이야기의 교훈은 어떤 경우에도 플러그인 디렉터리 이름을 플러그인 이름과 일치하지 않는 이름으로 지정하지 말 것이라는 것입니다. 올바르게 이름이 지정된 심볼릭 링크만으로는 충분하지 않습니다.

수정: 또한 register_asset "stylesheets/common/index.scss", plugin: "county-fence"를 사용하면 플러그인 이름이 올바르게 설정되도록 강제하는 우회 방법입니다.

body:has() 아래 규칙이 적용되지 않는 문제가 있습니다. 에셋 컴파일 파이프라인에서 업데이트가 되지 않는 것 같습니다. d/rake assets:clobber tmp:clear를 실행하고 d/rails s로 서버를 재시작해도 여전히 업데이트되지 않습니다.

예를 들어 body:has() 섹션에 body { background-color: red !important; }를 추가해도 body 요소의 스타일에 전혀 반영되지 않습니다. 단순히 다른 스타일에 의해 오버라이드되는 것이 아니라, devtools의 “styles” 패널에 해당 규칙이 아예 존재하지 않습니다.

같은 CSS 라인을 body:has() 외부에 배치하면 정상적으로 표시됩니다.

브라우저 콘솔에서 document.querySelector("body:has(#print-root)") !== null은 true를 반환합니다. 그리고 body:has()일부 규칙은 적용되고 있습니다.

에셋 생성 파이프라인에 이러한 변경 사항이 반영되지 않도록 방지하는 규칙이 있는지 궁금합니다.

이 문제를 해결하기 위해 내가 주로 쓰는 방법은 페이지의 glimmer 컴포넌트에 스타일을 직접 포함시키는 것입니다. 제가 시도해 본 방법 중 일관되게 효과가 있는 것은 이것뿐입니다. 이렇게 하면 조건부 CSS 규칙을 가지고 헤매지 않아도 됩니다.

CSS 컴파일 파이프라인이 끝없는 문제를 일으키고 있습니다. 새로고침이나 규칙 적용이 정말로 일관성이 없네요. 스타일이 사라지는데 그 이유를 알 수 없습니다. 이게 Docker 컨테이너에서 실행하는 것과 관련이 있는지 모르겠습니다. 이제 플러그인 폴더에 대한 심볼릭 링크를 완전히 제거했습니다. Docker 볼륨 마운트와 파일 감시/재컴파일 문제를 일으키는 원인이었던 것 같습니다. 이 문제를 재현할 수 있는 최소한의 저장소를 만들 수 있을 것 같습니다… 며칠 안에 해볼 수 있는지 확인해서 공개해 보겠습니다.

이전에 언급한 내용과 관련하여 추가 질문입니다…

Stripe에서 렌더링되는 iframe이 인쇄 레이아웃 하단에 빈 페이지가 표시되도록 만들고 있습니다. 해당 iframe은 요소에 display: block !important가 하드코딩되어 있습니다.

이 특정 버그는 해당 루트가 로드될 때 iframe을 삭제하는 방식으로 우회할 것 같습니다… (참고로 Stripe는 모든 클릭 이벤트를 감지하는 페이지 전체 너비의 div를 렌더링하고 있는데, 이는 상당한 프라이버시 침해로 보입니다. 구독 플러그인에서 비롯된 것으로 생각합니다.)

하지만 미래를 내다보았을 때, 인쇄 페이지에서 위장 게임을 하듯 끝없는 문제 해결이 이어질 것으로 예상됩니다. 레이아웃에 새로운 요소가 도입되는 경우, 눈에 띄지 않는 요소일지라도 인쇄 기능이 제대로 작동하지 않을 수 있습니다.

이 루트에 대해 사이트 레이아웃을 상속받는 것은 제게 이상적인 상황이 아닙니다. 이를 제외하거나 자체 레이아웃을 설정할 방법이 있을까요?