사용자 정의 마크다운 인용 BBCode 태그 추가

html 요소의 속성에 원본 텍스트를 저장해 두고, addTagDecorateCallback() 콜백 함수에서 해당 값을 반환하도록 하여 원본 텍스트를 가져오게 함으로써 문제를 해결할 수 있었습니다.

제가 어떤 방식으로 처리했는지 궁금한 분들을 위해 코드를 일부 공유합니다.

assets/javascripts/lib/discourse-markdown/snapblocks-discourse.js 파일에서 bbcode 태그를 초기화하는 부분에서, 나중에 이를 가져올 수 있도록 원본 텍스트를 snapblocks-source 속성에 저장하도록 수정했습니다.

assets\javascripts\discourse\initializers\snapblocks-discourse.js 파일에서는 인용(quoting)을 처리하는 코드를 추가했습니다.

// assets\javascripts\discourse\initializers\snapblocks-discourse.js

import {
  addBlockDecorateCallback, // 블록 bbcode 태그
  addTagDecorateCallback, // 인라인 bbcode 태그
} from "discourse/lib/to-markdown";

function initializeSnapblocks(api, siteSettings) {
  addTagDecorateCallback(function () {
    // this.element은 HTML 요소가 아닙니다.
    // 하지만 모든 html 속성을 포함하고 있습니다.
    const { attributes } = this.element;

    // 일반적으로 "class"가 자신의 클래스인지 확인해야 하지만,
    // 여기서는 "snapblocks-source"만 필요합니다.
    if (attributes["snapblocks-source"]) {
      let prefix = "[sb";

      // bbcode 태그에 속성을 추가합니다. (이 속성들은 요소의 속성으로도 저장됩니다.)
      const attrs = [
        "blockstyle",
        "wrap",
        "wrapsize",
        "zebra",
        "showspaces",
        "santa",
      ];
      for (const attr of attrs) {
        if (attributes[attr]) {
          prefix += ` ${attr}=${attributes[attr]}`;
        }
      }

      prefix += "]";

      this.prefix = prefix;
      this.suffix = "[/sb]";
      // 텍스트를 반환하면, 선택된 텍스트 대신 이 값이 사용됩니다.
      return attributes["snapblocks-source"];
    }
  });
}

블록 bbcode 태그의 경우에도 동일한 방식이며, addBlockDecorateCallback()을 사용하도록 변경하면 됩니다.

불행히도 이전 snapblocks 스니펫을 인용할 수 있도록 하려면 게시물을 다시 재처리(rebake)해야 합니다. 또한 svg 위의 텍스트를 선택하는 경우는 처리하지 않으며, svg 텍스트 앞뒤로 일부 텍스트를 함께 선택하고 svg 텍스트의 일부도 선택해야만 작동합니다.