(function () { // 내장 툴바(toolbar: false)는 안 쓴다 — EasyMDE 기본 툴바 아이콘은 Font Awesome CDN을 전제로 // 하는데, 이 앱은 CDN을 안 쓰는 게 원칙이라 대신 journal.html/journal_day_detail.html에서 // 직접 만든 텍스트 버튼이 아래 EDITOR_ACTIONS로 EasyMDE 인스턴스 메서드를 호출한다. function initEditors(root) { if (typeof EasyMDE === "undefined") return; var scope = root instanceof Element ? root : document; var textareas = scope.querySelectorAll("textarea.markdown-editor:not([data-easymde-initialized])"); textareas.forEach(function (textarea) { textarea.setAttribute("data-easymde-initialized", "true"); var easymde = new EasyMDE({ element: textarea, toolbar: false, spellChecker: false, autoDownloadFontAwesome: false, status: false, placeholder: textarea.getAttribute("placeholder") || "", minHeight: (textarea.getAttribute("rows") || 6) * 24 + "px", // 글머리 목록 버튼/Enter 자동 이어쓰기가 기본 "*" 대신 "-"를 쓰게 한다. // 서버 렌더링(app/markdown_utils.py)은 -/*/+ 전부 동일하게 처리하니 렌더링과는 무관하고 // 순수하게 에디터가 새로 만들어주는 글머리 기호에 대한 취향 설정이다. unorderedListStyle: "-", }); // CodeMirror는 원본 textarea와 실시간으로 값이 동기화되지 않는다(.save()를 명시적으로 // 불러야 함) — 매 변경마다 저장하고, htmx 미리보기(hx-trigger="input ...")와 // Alpine x-model이 둘 다 반응하도록 input 이벤트를 합성해서 던진다. easymde.codemirror.on("change", function () { easymde.codemirror.save(); textarea.dispatchEvent(new Event("input", { bubbles: true })); }); textarea._easymde = easymde; }); } document.addEventListener("DOMContentLoaded", function () { initEditors(document); }); document.body.addEventListener("htmx:afterSwap", function (evt) { initEditors(evt.target); }); })();