글꼴 크기 노드 타입

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

스키마 정의

글꼴 크기 마크 타입의 스키마 정의:

{
  fontSize: {
    attrs: {
      size: { default: 16 }
    },
      style: 'font-size: ' + node.attrs.size + 'px' 
    }, 0]
  }
}

모델 표현

모델 표현 예제:

{
  type: 'text',
  text: '큰 텍스트',
  marks: [{
    type: 'fontSize',
    attrs: { size: 24 }
  }]
}

HTML 직렬화

모델을 HTML로 변환:

function serializeFontSizeMark(text, mark) {
  const size = mark.attrs?.size || 16;
  return '<span style="font-size: ' + size + 'px">' + text + '</span>';
}

HTML 역직렬화

HTML을 모델로 파싱:

function extractFontSizeMark(element) {
  if (element.tagName === 'SPAN' && element.style.fontSize) {
    const size = parseInt(element.style.fontSize) || 16;
    return {
      type: 'fontSize',
      attrs: { size }
    };
  }
  return null;
}

뷰 연동

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

뷰 연동 코드:

// 글꼴 크기 설정
function setFontSize(size) {
  addMark({
    type: 'fontSize',
    attrs: { size }
  });
}

// 글꼴 크기 선택기
function showFontSizePicker() {
  const sizes = [12, 14, 16, 18, 20, 24, 28, 32];
  // 크기 선택기 표시
}

일반적인 문제

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

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

// 문제: 글꼴 크기 단위 (px, em, rem)
// 해결: px로 정규화
function normalizeFontSize(size) {
  if (typeof size === 'string') {
    if (size.endsWith('px')) {
      return parseInt(size);
    }
    if (size.endsWith('em')) {
      return parseFloat(size) * 16; // 16px 기준 가정
    }
  }
  return size;
}

// 문제: 글꼴 크기 검증
// 해결: 유효한 범위로 제한
function validateFontSize(size) {
  return Math.max(8, Math.min(72, size));
}

구현

완전한 구현 예제:

class FontSizeMark {
  constructor(attrs) {
    this.type = 'fontSize';
    this.attrs = { size: attrs?.size || 16 };
  }
  
  toDOM() {
    return ['span', { 
      style: 'font-size: ' + this.attrs.size + 'px' 
    }, 0];
  }
  
  static fromDOM(element) {
    if (element.tagName === 'SPAN' && element.style.fontSize) {
      return new FontSizeMark({ 
        size: parseInt(element.style.fontSize) || 16 
      });
    }
    return null;
  }
}