여느 해보다 빨리 한여름 무더위🔥🔥🔥가 찾아온 6월입니다. 끝날듯 끝나지 않는 코로나와 장기전에 돌입하였지만, 이번달에도 TOAST UI는 멈추지 않고 릴리즈를 위해 열심히 달렸습니다. 🏃♂ 건강 유념하시면서 TOAST UI와 함께 즐거운 코딩하세요! (즐코하!🙋♂🙋♀)

사용성 개선
에디터에서는 XSS(Cross Site Scripting)를 발생시킬 수 있는 태그, 속성, 속성 값을 가지는 텍스트 값을 새니타이징하는 기능을 제공합니다. 아래 예제와 같이 onerror, src="javascript:" 등 일부 속성을 사용할 때 XSS가 발생하는 문제가 있었는데, 2.2.0 버전에서 에디터에서 내장하고 있는 기본 HTML 새니타이저 모듈을 고도화하여 XSS 취약점 문제를 해결하였습니다.
<input type="image" src="javascript:alert('XSS');" />
<table background="javascript:alert('XSS')"></table>
<img src="javas<!-- -->cript:alert('XSS')" />
<img src='vbscript:msgbox("XSS")' />
foo<a href=" javascript:alert(XSS)">click</a>
<img src="x:x" onerror="alert('XSS')" />
...contenteditable 속성을 지정할 수 있음 (#998)에디터의 customHTMLRenderer 옵션을 사용하면 마크다운 문법으로 생성되는 HTML을 사용자가 커스터마이징할 수 있습니다. 커스터마이징하여 생성된 HTML 중 위지윅 모드에서는 편집이 불가능하도록 처리하고 싶은 경우, contenteditable="false"로 속성값을 지정하여 처리할 수 있습니다. 2.2.0 버전부터는 파라그래프 요소에 contenteditable 속성을 설정할 수 있고, 속성이 설정된 요소가 위지윅에서도 정상 동작하도록 개선되었습니다.
const editor = new Editor({
  // ...
  customHTMLRenderer: {
    paragraph(node, { origin }) {
      const regexp = /(<%.*%>)|({:toc.*})/;
      const result = origin();
      const { firstChild } = node;
      if (regexp.test(firstChild.literal)) {
        const { attributes = {} } = result;
        attributes.contenteditable = false;
        result.attributes = attributes;
      }
      return result;
    }
  }
});차트, UML, 코드 구문 강조 플러그인을 사용할 때 대소문자를 구문하지 않고 코드 블럭 언어를 입력할 수 있도록 개선되었습니다.
Before

After

이전 버전에서는 마크다운 에디터에서 코드 블럭이 연속해서 입력되었을 때 구문 강조가 깨지는 것처럼 보이는 문제가 있었습니다. 코드 블럭 사이에 여백을 추가하여 각 코드 블럭 구문을 사용자가 정확하게 구분할 수 있도록 개선되었습니다.
Before

After

span 태그를 제거해줌 (#1036)버그 픽스
form이 제출되는 현상 (#969)setValue, getValue) 타입 제거 (#970)shift-tab 숏컷이 정상적으로 동작하지 않음 (#1014)change 이벤트가 발생하지 않음 (#757)min-height가 적용된 요소에 리사이저블 박스가 생성됨 (#984)
기능 추가
사용자가 원하는 comparator로 데이터를 정렬할 수 있는 comparator 옵션이 추가되었습니다. 정렬 시 셀 데이터의 가공이 필요하거나, 다른 컬럼 데이터를 참조하여 정렬할 필요가 있는 경우 유용하게 사용할 수 있습니다.
const comparator = (vluaeA, valueB, rowA, rowB) => {
  const lengthA = valueA.length;
  const lengthB = valueB.length;
  return lengthA - lengthB;
};
const grid = new Grid({
  data,
  columns: [
    { name: "alphabetA", sortable: true },
    { name: "alphabetB", sortable: true, comparator }
  ]
});visiblePages 옵션 추가 (#1097)그리드의 페이지네이션을 사용하는 경우, 페이지 번호의 범위를 설정할 수 있는 옵션이 추가되었습니다.
const grid = new Grid({
  data,
  columns,
  pageOptions: {
    useClient: true,
    visiblePages: 7
  }
});
unique 빌트인 validation 옵션 추가 (#1099)특정 컬럼내에 데이터가 중복되지 않는 유일한 값인지 검증할 수 있는 unique validation 옵션이 추가되었습니다.
Note: 내부적으로 최적화를 하였지만, 대용량 데이터에서 unique validation 옵션을 사용하는 경우에는 성능적인 이슈가 있을 수 있습니다.
const grid = new Grid({
  data,
  columns: [
    { name: "name", validation: { unique: true } }
    // ...
  ]
});사용성 개선
버그 수정
resetData API 호출 시 scrollEnd 이벤트가 호출되는 현상 수정 (#1086)
지정 영역 모자이크 기능과 화살표 라인을 그릴 수 있도록 기능을 추가할 예정입니다. 또한, 회전된 텍스트객체의 포지션이 틀어지는 버그를 수정할 계획입니다.
이번 달은 세 개의 번역 글이 올라왔습니다. 크로미움 84에서 웹 애니메이션 API가 어떻게 개선되었는지와 새롭게 등장한 React 상태 관리 라이브러리 Recoil에 대한 소개, 리액드 앱에서 중앙 집중식으로 어떻게 에러를 핸들링하는지에 대한 글들이 번역되었습니다. 아직 읽어보시지 않았다면 아래 링크를 클릭하세요! 👇👇
사용 문의, 기능 추가/수정 요청 및 버그 신고는 각 제품의 GitHub 저장소 이슈를 이용해주세요!