스키마 정의
취소선 마크 타입의 스키마 정의:
{
strikethrough: {
}
}모델 표현
모델 표현 예제:
{
type: 'text',
text: '삭제된 텍스트',
marks: [{ type: 'strikethrough' }]
}HTML 직렬화
모델을 HTML로 변환:
function serializeStrikethroughMark(text, mark) {
return '<s>' + text + '</s>';
}HTML 역직렬화
HTML을 모델로 파싱:
function extractStrikethroughMark(element) {
if (element.tagName === 'S' ||
element.tagName === 'STRIKE' ||
element.tagName === 'DEL') {
return { type: 'strikethrough' };
}
return null;
}뷰 연동
뷰 연동 노트: 이 노드 타입을 뷰 레이어에서 구현할 때 contenteditable 동작, 선택 처리, 이벤트 관리에 특히 주의하세요.
뷰 연동 코드:
// 취소선 토글
function toggleStrikethrough() {
const selection = window.getSelection();
if (!selection.rangeCount) return;
const range = selection.getRangeAt(0);
const hasStrikethrough = hasMarkInSelection(range, 'strikethrough');
if (hasStrikethrough) {
removeMark('strikethrough');
} else {
addMark({ type: 'strikethrough' });
}
}일반적인 문제
일반적인 함정: 이 노드 타입을 구현할 때 자주 발생하는 문제들입니다. 구현 전에 주의 깊게 검토하세요.
일반적인 문제 및 해결 방법:
// 문제: <s> vs <del> vs <strike>
// 해결: <s>로 정규화
function normalizeStrikethrough(element) {
element.querySelectorAll('strike, del').forEach(el => {
const s = document.createElement('s');
s.innerHTML = el.innerHTML;
el.parentNode.replaceChild(s, el);
});
}
// 문제: 취소선 시맨틱 의미
// 해결: <del>은 시맨틱 의미가 있음 (삭제된 콘텐츠)
// 버전 관리 시나리오에서는 <del> 사용 고려구현
완전한 구현 예제:
class StrikethroughMark {
constructor() {
this.type = 'strikethrough';
}
toDOM() {
return ['s', 0];
}
static fromDOM(element) {
if (['S', 'STRIKE', 'DEL'].includes(element.tagName)) {
return new StrikethroughMark();
}
return null;
}
}