FastComments.com

확장 프로그램 작성

확장 기능 개발

개요

FastComments는 우리가 확장(Extensions)이라고 부르는 스크립트를 통해 핵심 기능을 확장할 수 있는 기능을 제공합니다.

An Extension은 댓글 위젯에 추가 마크업을 더하고, 이벤트 리스너를 추가하며, 임의의 코드를 실행할 수 있습니다.

여기에는 우리가 프로덕션에서 사용 중인 확장 예제들과 확장을 작성하는 방법에 대한 문서가 있습니다.

확장 프로그램의 수명 주기 Internal Link

각 확장 기능의 스크립트는 댓글 위젯이 첫 번째 댓글 집합을 가져오고 UI를 렌더링하기 시작하기 전에 가져와서 실행됩니다.

초기 로드 시, 다음 데이터가 extension 객체에 추가됩니다:

  • config - config 객체에 대한 참조.
  • translations - translations 객체에 대한 참조.
  • commentsById - ID별 모든 댓글에 대한 참조.
  • root - 루트 DOM 노드에 대한 참조.

확장 기능은 댓글 위젯이 적절한 시점에 호출할 원하는 함수들을 재정의해야 합니다.

확장 프로그램 정의 Internal Link

가장 작은 확장 프로그램은 다음과 같습니다:

간단한 확장
Copy CopyRun External Link
1
2(function () {
3 const extension = FastCommentsUI.extensions.find((extension) => {
4 return extension.id === 'my-extension';
5 });
6})();
7

이 예시를 위해, 이것을 my-extension.js로 저장하고 https://example.com/my-extension.min.js에서 접근할 수 있게 하세요.

이 확장 프로그램은 아무 작업도 하지 않습니다. 다만 로드될 때 코어 댓글 라이브러리가 생성한 확장 객체를 가져옵니다.

이 Extension 객체는 싱글톤이며 다른 확장과 공유되지 않습니다.

다음으로, 확장을 로드하려면 댓글 위젯에 이를 알려야 합니다. 예를 들어:

Using a Custom Extension
Copy CopyRun External Link
1
2<script async src="https://cdn.fastcomments.com/js/embed-v2-async.min.js"></script>
3<div id="fastcomments-widget"></div>
4<script>
5window.fcConfigs = [{
6 "tenantId": "demo",
7 "extensions": [
8 {
9 "id": "my-extension",
10 "path": "https://example.com/my-extension.min.js"
11 }
12 ]
13}];
14</script>
15

실용적인 예제는 다음 섹션을 참조하세요.

확장 객체 Internal Link

확장(extension) 객체는 다음과 같은 정의로 구성됩니다:

확장 객체 JSDoc
Copy CopyRun External Link
1
2/**
3 * FastCommentsUI 확장 객체입니다. 특정 컴포넌트를 지연 로딩(lazy-loading)하는 데 사용됩니다. 예를 들어, 리뷰 시스템은
4 * 모든 고객이 사용하는 것이 아니므로 필요할 때만 해당 확장을 로드합니다.
5 *
6 * @typedef {Object} FastCommentsUIExtension
7 * @property {string} id
8 * @property {Element} scriptNode
9 * @property {Element} root - 위젯의 루트 DOM 노드입니다.
10 * @property {string} [css]
11 * @property {Object} config - FastComments 설정 객체입니다.
12 * @property {Object} commentsById - 모든 댓글을 id별로 담고 있는 객체에 대한 참조이며, 항상 최신 상태로 유지됩니다.
13 * @property {Object} translations - 모든 번역에 대한 참조입니다.
14 * @property {Function} reRenderComment - 호출하여 댓글을 다시 렌더링할 수 있는 함수에 대한 참조입니다.
15 * @property {Function} removeCommentAndReRender - 호출하여 메모리에서 댓글을 제거하고 DOM의 해당 부분을 다시 렌더링할 수 있는 함수에 대한 참조입니다.
16 * @property {Function} newBroadcastId - 호출하여 새 broadcast id를 생성하고 무시할 broadcast id의 로컬 목록에 추가할 수 있는 함수에 대한 참조입니다.
17 * @property {Function} [withSessionId] - 요청 URL과 콜백을 인자로 호출합니다. 서드파티 쿠키가 차단된 경우(댓글 및 투표 요청이 사용하는 것과 동일한 경로) 세션 id가 추가된 URL로 콜백을 실행하고, 그렇지 않으면 URL을 그대로 전달합니다. 이 방식으로 세션 id를 사용할 수 없는 경우, 마지막으로 rememberAnonSessionId에 전달된 익명 세션 id(있다면)를 추가합니다. SSO에는 사용되지 않습니다.
18 * @property {Function} [rememberAnonSessionId] - 응답이 반환한 anonSessionId를 인자로 호출합니다. 서버는 세션 쿠키가 없는 게스트의 요청에만 이 값을 반환하며, 로그인된 세션에는 절대 반환하지 않습니다. 이 값은 localStorage에 저장되고(저장소를 사용할 수 없는 경우 메모리에 저장) 이후 요청에서 withSessionId가 이를 전송하여 게스트가 하나의 동일성을 유지하도록 합니다.
19 * @property {FastCommentsUIExtensionSetupEventHandlers} [setupEventHandlers]
20 * @property {FastCommentsUIExtensionPrepareCommentForSavingCallback} [prepareCommentForSaving] - 게시하려는 댓글과 함께 호출됩니다. false를 반환하면 제출이 취소됩니다(예: 첨부된 투표가 완성되지 않은 경우).
21 * @property {FastCommentsUIExtensionNewCommentCallback} [newComment]
22 * @property {FastCommentsUIExtensionReplyAreaFilter} [replyAreaFilter] - 댓글 영역의 HTML을 필터링합니다.
23 * @property {FastCommentsUIExtensionWidgetFilter} [widgetFilter] - 렌더링 시 전체 위젯의 HTML을 필터링합니다.
24 * @property {FastCommentsUIExtensionCommentTopFilter} [commentFilter] - 렌더링 전에 각 댓글의 HTML을 필터링합니다.
25 * @property {FastCommentsUIExtensionReplyAreaFilter} [commentMenuFilter] - 렌더링 전에 각 댓글 메뉴의 HTML을 필터링합니다.
26 * @property {FastCommentsUIExtensionMenuFilter} [menuFilter] - 렌더링 시 전체 위젯의 HTML을 필터링합니다.
27 * @property {FastCommentsUIExtensionReplyAreaTop} [replyAreaTop] - (레거시) 답글 영역 상단에 추가할 HTML을 반환합니다.
28 * @property {FastCommentsUIExtensionWidgetTopCallback} [widgetTop] - (레거시) 위젯 상단에 추가할 HTML을 반환합니다.
29 * @property {FastCommentsUIExtensionCommentTopCallback} [commentTop] - (레거시) 댓글 요소 상단에 추가할 HTML을 반환합니다.
30 * @property {FastCommentsUIExtensionCommentBottomCallback} [commentBottom] - (레거시) 댓글 요소 하단에 추가할 HTML을 반환합니다.
31 * @property {FastCommentsUIExtensionCommentBottomCallback} [commentContentBottom] - 댓글 텍스트 뒤, 댓글 콘텐츠 요소 내부에 추가할 HTML을 반환합니다(투표에서 사용).
32 * @property {Function} [replyAreaInputBottom] - 댓글 입력 프레임 내부, 텍스트 입력 아래에 추가할 HTML을 반환합니다(투표의 인라인 투표 편집기에서 사용). 부모 댓글 id를 전달받으며, 루트 답글 상자의 경우 null을 전달받습니다.
33 * @property {Function} [onPollUpdate] - 페이지의 투표 투표 수가 변경될 때 라이브 이벤트와 함께 호출됩니다.
34 * @property {Function} isSiteAdmin - 조회자가 해당 테넌트의 관리자 또는 중재자인지 여부를 반환합니다. 첫 번째 fetch 이후에 알 수 있습니다.
35 * @property {FastCommentsUIExtensionMenuBottomCallback} [menuBottom] - (레거시) 각 댓글의 메뉴 요소 하단에 추가할 HTML을 반환합니다.
36 * @property {FastCommentsUIExtensionRenderCallback} [onRender]
37 * @property {FastCommentsUIExtensionConnectionStatusCallback} [onLiveConnectionStatusUpdate]
38 * @property {FastCommentsUIExtensionInitialRenderCallback} [onInitialRenderComplete]
39 * @property {FastCommentsUIExtensionPresenceUpdateCallback} [onPresenceUpdate]
40 */
41
42/**
43 * @callback FastCommentsUIExtensionSetupEventHandlers
44 * @param {Element} element - 루트 요소입니다.
45 * @param {Object.<string, Function>} clickListeners - 클래스 이름별 클릭 이벤트 핸들러로, 참조를 통해 수정할 수 있습니다.
46 * @returns void
47 */
48
49/**
50 * @callback FastCommentsUIExtensionWidgetTopCallback
51 * @param {Object} moduleData
52 * @returns {string}
53 */
54
55/**
56 * @callback FastCommentsUIExtensionWidgetFilter
57 * @param {Object} moduleData
58 * @param {Object} html
59 * @returns {string}
60 */
61
62/**
63 * @callback FastCommentsUIExtensionCommentTopCallback
64 * @param {Object} comment
65 * @returns {string}
66 */
67
68/**
69 * @callback FastCommentsUIExtensionCommentTopFilter
70 * @param {Object} comment
71 * @param {string} html
72 * @returns {string}
73 */
74
75/**
76 * @callback FastCommentsUIExtensionCommentBottomCallback
77 * @param {Object} comment
78 * @returns {string}
79 */
80
81/**
82 * @callback FastCommentsUIExtensionMenuBottomCallback
83 * @param {Object} comment
84 * @returns {string}
85 */
86
87/**
88 * @callback FastCommentsUIExtensionMenuFilter
89 * @param {Object} comment
90 * @param {string} html
91 * @returns {string}
92 */
93
94/**
95 * @callback FastCommentsUIExtensionRenderCallback
96 * @returns {string}
97 */
98
99/**
100 * @callback FastCommentsUIExtensionConnectionStatusCallback
101 * @param {boolean} isConnected
102 * @returns {void}
103 */
104
105/**
106 * @callback FastCommentsUIExtensionInitialRenderCallback
107 * @returns {void}
108 */
109
110/**
111 * @callback FastCommentsUIExtensionReplyAreaTop
112 * @param {Object|null} currentUser
113 * @param {boolean} isSaving
114 * @param {boolean} isReplyOpen
115 * @param {string|null} parentId
116 * @returns {string}
117 */
118
119/**
120 * @callback FastCommentsUIExtensionReplyAreaFilter
121 * @param {Object|null} currentUser
122 * @param {boolean} isSaving
123 * @param {boolean} isReplyOpen
124 * @param {string|null} parentId
125 * @param {string|null} html
126 * @returns {string}
127 */
128
129/**
130 * @callback FastCommentsUIExtensionPrepareCommentForSavingCallback
131 * @param {Object} comment
132 * @param {string} parentId
133 */
134
135/**
136 * @callback FastCommentsUIExtensionNewCommentCallback
137 * @param {Object} comment
138 */
139
140/**
141 * @callback FastCommentsUIExtensionPresenceUpdateCallback
142 * @param {Object} update
143 */
144

확장 API Internal Link

Extension과 상호작용하는 것은 간단합니다. 호출되길 원하는 함수들에 대한 참조를 정의하기만 하면 됩니다.

앞의 예제에서 이어서, 각 댓글의 상단에 HTML을 추가한다고 가정해봅시다:

간단한 확장 - 계속
Copy CopyRun External Link
1
2(function () {
3 const extension = FastCommentsUI.extensions.find((extension) => {
4 return extension.id === 'my-extension';
5 });
6
7 extension.commentFilter = function(comment, html) {
8 return `<h3>The user's name is ${comment.commenterName}!</h3>` + html;
9 }
10})();
11

이와 같이 HTML을 반환하면, dom-diffing 알고리즘을 통해 UI에 병합됩니다.

댓글을 수동으로 다시 렌더링하기

초기 페이지 로드를 기다린 다음 reRenderComment를 호출하여 댓글을 수동으로 다시 렌더링할 수 있습니다:

댓글 재렌더링
Copy CopyRun External Link
1
2(function () {
3 const extension = FastCommentsUI.extensions.find((extension) => {
4 return extension.id === 'my-extension';
5 });
6
7 let renderCount = 0;
8
9 extension.commentFilter = function(comment, html) {
10 renderCount++;
11 return `<h3>The render count is ${renderCount}!</h3>` + html;
12 }
13
14 extension.onInitialRenderComplete = function() {
15 setInterval(function() {
16 extension.reRenderComment(extension.commentsById[Object.keys(extension.commentsById)[0]], function renderDone() {
17 console.log('Comment re-render done.');
18 });
19 }, 2000); // timeout not required, just an example.
20 }
21})();
22