feat(cafe24): HTML 편집기 Ctrl+/ 주석 토글
- 선택이 있으면 선택이 걸친 줄 전체가 대상. 반쯤 걸친 줄이 잘려 태그가
깨지지 않게 하기 위함. 선택이 없으면 커서가 있는 줄 하나.
- 대상 안에 주석 기호가 하나라도 있으면 제거, 없으면 블록 전체를 <!-- -->
로 감싼다. HTML 주석은 중첩이 안 되므로 이미 주석인 부분을 또 감싸지
않는다.
- 선택이 개행에서 끝나면 다음 줄은 제외(줄 끝까지 드래그했을 때 아래 줄이
딸려오지 않게).
- execCommand("insertText") 로 넣어 Ctrl+Z 이력에 남긴다. 미지원 브라우저는
value 를 직접 바꾼다.
- 되돌린 뒤 커서/선택 위치를 복원한다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -78,7 +78,7 @@
|
||||
<input type="hidden" name="list_query" value="{{ list_query }}" />
|
||||
|
||||
<div class="cf24-editor-bar">
|
||||
<span class="cf24-muted">상세설명 HTML · {{ desc.description | length }}자 · PC/모바일 공통</span>
|
||||
<span class="cf24-muted">상세설명 HTML · {{ desc.description | length }}자 · PC/모바일 공통 · Ctrl+/ 주석</span>
|
||||
<span class="cf24-editor-bar-right">
|
||||
<input class="cf24-memo" type="text" name="memo" maxlength="200"
|
||||
placeholder="변경 메모 (버전 이력에 남습니다)" />
|
||||
@@ -99,7 +99,8 @@
|
||||
<div class="cf24-code-body">
|
||||
<pre class="cf24-code-hl" id="cf24-hl-pc" aria-hidden="true"></pre>
|
||||
<textarea id="cf24-html-pc" class="cf24-code-input" name="html" wrap="off"
|
||||
spellcheck="false" autocapitalize="off" autocorrect="off">{{ html_pc }}</textarea>
|
||||
spellcheck="false" autocapitalize="off" autocorrect="off"
|
||||
title="Tab 들여쓰기 · Ctrl+/ 주석 토글(선택한 줄 전체, 선택이 없으면 커서 줄)">{{ html_pc }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -186,10 +186,75 @@
|
||||
timer = setTimeout(repaint, 80);
|
||||
}
|
||||
|
||||
/* Ctrl+/ (Mac ⌘+/) 로 HTML 주석 토글.
|
||||
- 선택이 있으면 그 선택이 걸친 **줄 전체**가 대상이다(반쯤 걸친 줄이
|
||||
잘려 태그가 깨지지 않게).
|
||||
- 선택이 없으면 커서가 있는 줄 하나.
|
||||
- 대상 안에 주석 기호가 하나라도 있으면 **제거**, 없으면 블록 전체를
|
||||
<!-- --> 로 감싼다. HTML 주석은 중첩이 안 되므로 "이미 주석인 부분을
|
||||
또 감싸기"를 피하는 것이 이 규칙의 이유다. */
|
||||
var COMMENT_MARK = /<!--[ \t]?|[ \t]?-->/g;
|
||||
|
||||
function toggleComment() {
|
||||
var value = ta.value;
|
||||
var start = ta.selectionStart, end = ta.selectionEnd;
|
||||
// 선택이 개행에서 끝나면 그 다음 줄은 대상이 아니다(드래그로 줄 끝까지
|
||||
// 끌었을 때 아래 줄까지 주석되는 것을 막는다).
|
||||
if (end > start && value.charAt(end - 1) === "\n") end -= 1;
|
||||
|
||||
var lineStart = value.lastIndexOf("\n", start - 1) + 1;
|
||||
var lineEnd = value.indexOf("\n", end);
|
||||
if (lineEnd === -1) lineEnd = value.length;
|
||||
|
||||
var block = value.slice(lineStart, lineEnd);
|
||||
if (!block.trim()) return; // 빈 줄에서는 아무 것도 하지 않는다
|
||||
|
||||
var caretIn = start - lineStart; // 블록 안에서의 커서 위치
|
||||
var shift = 0, out;
|
||||
|
||||
COMMENT_MARK.lastIndex = 0;
|
||||
if (COMMENT_MARK.test(block)) {
|
||||
COMMENT_MARK.lastIndex = 0;
|
||||
out = block.replace(COMMENT_MARK, function (mark, offset) {
|
||||
if (offset < caretIn) shift -= mark.length; // 커서 앞이 줄어든 만큼
|
||||
return "";
|
||||
});
|
||||
} else {
|
||||
var indent = block.match(/^[ \t]*/)[0];
|
||||
out = indent + "<!-- " + block.slice(indent.length) + " -->";
|
||||
shift = caretIn >= indent.length ? 5 : 0; // "<!-- " 길이
|
||||
}
|
||||
|
||||
// execCommand 로 넣어야 브라우저의 실행취소(Ctrl+Z) 이력에 남는다.
|
||||
// 지원하지 않으면 value 를 직접 바꾼다(그때는 되돌리기가 안 될 뿐 동작은 같다).
|
||||
ta.selectionStart = lineStart;
|
||||
ta.selectionEnd = lineEnd;
|
||||
var inserted = false;
|
||||
try { inserted = document.execCommand("insertText", false, out); } catch (err) { inserted = false; }
|
||||
if (!inserted) ta.value = value.slice(0, lineStart) + out + value.slice(lineEnd);
|
||||
|
||||
if (start === end) {
|
||||
var pos = lineStart + Math.min(out.length, Math.max(0, caretIn + shift));
|
||||
ta.selectionStart = ta.selectionEnd = pos;
|
||||
} else {
|
||||
ta.selectionStart = lineStart; // 바꾼 범위를 계속 선택해 둔다
|
||||
ta.selectionEnd = lineStart + out.length;
|
||||
}
|
||||
dirty = true;
|
||||
refresh();
|
||||
}
|
||||
|
||||
ta.addEventListener("scroll", sync);
|
||||
ta.addEventListener("input", function () { dirty = true; refresh(); });
|
||||
// Tab 은 포커스 이동이 아니라 들여쓰기로 쓴다.
|
||||
ta.addEventListener("keydown", function (e) {
|
||||
// Ctrl+/ · ⌘+/ — 자판에 따라 key 가 "/" 가 아닐 수 있어 code 도 함께 본다.
|
||||
if ((e.ctrlKey || e.metaKey) && !e.altKey &&
|
||||
(e.key === "/" || e.code === "Slash" || e.code === "NumpadDivide")) {
|
||||
e.preventDefault();
|
||||
toggleComment();
|
||||
return;
|
||||
}
|
||||
// Tab 은 포커스 이동이 아니라 들여쓰기로 쓴다.
|
||||
if (e.key !== "Tab") return;
|
||||
e.preventDefault();
|
||||
var start = ta.selectionStart, end = ta.selectionEnd;
|
||||
|
||||
Reference in New Issue
Block a user