하이라이트 노드 타입

카테고리: 포맷팅 • 뷰 연동 노트를 포함한 상세 구현 가이드

스키마 정의

하이라이트 마크 타입의 스키마 정의:

{
  highlight: {
    attrs: {
      color: { default: '#ffff00' }
    },
      style: 'background-color: ' + node.attrs.color 
    }, 0]
  }
}

모델 표현

모델 표현 예제:

{
  type: 'text',
  text: '하이라이트된 텍스트',
  marks: [{
    type: 'highlight',
    attrs: { color: '#ffff00' }
  }]
}

HTML 직렬화

모델을 HTML로 변환:

function serializeHighlightMark(text, mark) {
  const color = mark.attrs?.color || '#ffff00';
  return '<mark style="background-color: ' + escapeHtml(color) + '">' + 
         text + '</mark>';
}

HTML 역직렬화

HTML을 모델로 파싱:

function extractHighlightMark(element) {
  if (element.tagName === 'MARK') {
    const color = element.style.backgroundColor || '#ffff00';
    return {
      type: 'highlight',
      attrs: { color }
    };
  }
  return null;
}

뷰 연동

뷰 연동 노트: 이 노드 타입을 뷰 레이어에서 구현할 때 contenteditable 동작, 선택 처리, 이벤트 관리에 특히 주의하세요.

뷰 연동 코드:

// 하이라이트 적용
function applyHighlight(color = '#ffff00') {
  addMark({
    type: 'highlight',
    attrs: { color }
  });
}

// 하이라이트 제거
function removeHighlight() {
  removeMark('highlight');
}

일반적인 문제

일반적인 함정: 이 노드 타입을 구현할 때 자주 발생하는 문제들입니다. 구현 전에 주의 깊게 검토하세요.

일반적인 문제 및 해결 방법:

// 문제: 하이라이트 색상 형식
// 해결: hex로 정규화
function normalizeHighlightColor(color) {
  return normalizeColor(color);
}

// 문제: 중첩된 하이라이트
// 해결: 중첩된 하이라이트 병합 또는 평탄화
function mergeHighlights(element) {
  const marks = element.querySelectorAll('mark');
  // 중첩된 마크 처리
}

구현

완전한 구현 예제:

class HighlightMark {
  constructor(attrs) {
    this.type = 'highlight';
    this.attrs = { color: attrs?.color || '#ffff00' };
  }
  
  toDOM() {
    return ['mark', { 
      style: 'background-color: ' + this.attrs.color 
    }, 0];
  }
  
  static fromDOM(element) {
    if (element.tagName === 'MARK') {
      return new HighlightMark({ 
        color: element.style.backgroundColor || '#ffff00' 
      });
    }
    return null;
  }
}