Microsoft 社는 2022년 6월 15일 Internet Explorer 11의 지원을 종료했습니다.

GrahaViewer

제목

GrahaViewer

1. about

1.1. 소개

GrahaViewer 는 웹브라우저에서 동작하는 다음 2가지 형식의 HTML Viewer 이다.

1.2. 다운로드

https://github.com/logicielkr/client_lib/tree/master/GrahaViewer/0.7.0.0

1.3. 호환성

다음의 환경에서 테스트했다.

  • Firefox 최신버전
  • Google Chrome 최신버전
  • IE 11

IE 11 에서는 Javascript 오류가 나지는 않지만, 인쇄 기능을 지원하지 않고, PDF 변환이 매우 느리고(html2canvas.min.js 때문이라고 생각한다), 여러 상황에 따라 결과물이 고르지 않을 수 있다.

1.4. 의존성

CDN 에서 다음과 같은 css 와 Javascript 라이브러리를 불러와서 사용한다.

1.4.1. 항상 사용하는 것

1.4.2. PDF 변환을 위해 사용하는 것

1.4.3. IE 11 을 위해서 사용하는 것

2. 사용법

2.1. 사용법

  1. .odt 문서는 odt.html 을 웹브라우저에서 불러온다.

  2. .hwpx 문서는 hwpx.html 을 웹브라우저에서 불러온다.

  3. 상단의 "찾아보기"를 클릭해서 odt 혹은 hwpx 파일을 선택하거나, odt 혹은 hwpx 파일 1개를 드래그 앤 드롭(Drag and Drop) 하면, HTML 로 변환한다.

  4. PDF 아이콘을 클릭하면, PDF 로 변환한다 (only IE 11).

    PDF 변환 기능은 소스코드에 함수가 남겨져 있지만, deprecated 되었다. 웹브라우저의 인쇄기능 or 웹브라우저 확장기능으로 쉽게 구현이 가능하다. jsPDF 를 이용해서 pdf 변환을 하기 위해서는 ttf 파일을 다운로드 받아야 하기 때문에 여러가지 문제가 발생한다. jsPDF는 underline 을 지원하지 않는 등 아주 소소한 이슈도 있도 있고, 웹브라우저의 인쇄기능을 이용해서 PDF 로 변환한 것과 결과물에서 약간의 차이가 있다.

  5. 인쇄(Print) 아이콘을 클릭하면, 웹페이지를 인쇄한다.

    odt 혹은 hwpx 파일과 웹브라우저의 용지 크기, 여백, 기타 인쇄와 관련된 설정이 맞지 않는다면, 페이지 넘김이 발생하는 위치가 다를 수 있으므로 주의를 요한다. IE 11 은 웹브라우저의 인쇄기능을 사용했을 경우 화면 layout 이 엉망이 되므로, 인쇄(Print) 아이콘은 숨겨진다.

  6. 다운로드 아이콘을 클릭하면, odt 혹은 hwpx 원본 파일을 다운로드 한다.

서버에 upload 하지 않고 client 에서 처리한다.

2.2. Notice

2.2.1. GrahaViewer 는 범용으로 사용 할 수 없다.

[한/글] 혹은 Apache OpenOffice Text, LibreOffice Text 의 극히 일부만 지원한다.

어떤 항목은 표시되지 않을 수도 있고, 페이지 레이아웃이 망가지는 경우도 있고, 페이지 넘김이 발생하는 위치가 다를 수도 있다.

[한/글]이나 Apache OpenOffice Text / LibreOffice Text 등과 비교하면 글자등이 표시되는 위치가 약간씩 다르다.

따라서 위치가 종이나 쪽 기준의 어떤 좌표값으로 정해진 것이라면, 다르게 표시될 수 있다.

GrahaViewer 는 필자가 만들어서 배포중인 GrahaReporter.js 혹은 GrahaReporter.js 의 Java 버전인 GrahaExtension 의 구성요소 중 하나인 GrahaReporterImpl 로 생성한 odt 혹은 hwpx 파일을 HTML 로 변환하여 미리보기 혹은 인쇄 기능을 제공 하기 위해 만들었다.

2.2.2. 한글 서체는 나눔폰트를 사용한다.

나눔폰트가 아닌 것들은 전부 다 나눔폰트로 변경해 버린다.

PDF 변환 기능을 사용하지 않는다면, 필수는 아니다. 아래의 폰트 변경 방법에 따라 변경할 수 있다.

폰트 이름에 "바탕" "명조" 따위가 들어간다면, 나눔명조로 변경하고,

"고딕" "굴림" 따위가 들어간다면, 나눔고딕으로 변경한다.

폰트에 따라 문자의 width 가 달라져서 발생하는 여러 문제들이 있을 수 있다.

3. 프로그래머를 위하여

3.1. hwpx.html 과 odt.html 에 대해서

hwpx.html 과 odt.html 는 예제이므로 누구든 저작권에 구애받지 않고, 자유롭게 변경해서 사용하거나 다시 배포할 수 있다.

3.2. 폰트 변경 방법

폰트와 관련된 것은 다음과 같다.

  • odt.html 혹은 hwpx.html 의 css
  • GrahaConverter.prototype.defaultFonts : PDF 변환기능에서만 사용
  • GrahaConverterUtility.defaultFontFamilyConverter

GrahaConverter.prototype.defaultFonts 및 GrahaConverterUtility.defaultFontFamilyConverter 는 odt.html 이나 hwpx.html 과 같이 단독 실행형 GrahaViewer 에서는 다음과 같이 GrahaViewer.ready 함수의 opts 파라미터로 넘길 수 있다. 처리한다.

var opts = {
fonts: GrahaViewerFontPlugin.fonts(),
fontFamilyConverter: GrahaViewerFontPlugin.fontFamilyConverter,
defaultFontFamily: "Nanum Myeongjo"
};
GrahaViewer.ready(opts);

fonts: GrahaViewerFontPlugin.fonts() 는 PDF 로 변환 할 때, jsPDF 에 공급되는 TrueType 폰트의 배열이며, GrahaConverter.prototype.defaultFonts 함수를 참조하여 작성한다.

파라미터로 넘어가는 것은 함수가 아니라, 함수의 실행결과(Array)이다.

각각의 폰트는 다음과 같이 family, truetype, weight 속성값을 가져야 한다.

fonts.push({
family: "Nanum Gothic",
truetype: "//cdn.jsdelivr.net/font-nanum/1.0/nanumgothic/v3/NanumGothic-Regular.ttf",
weight: "400"
});

fontFamilyConverter: GrahaViewerFontPlugin.fontFamilyConverter 는 hwpx 혹은 odt 파일의 font-family 를 GrahaViewer 에서 사용할 폰트로 변환하는 함수이며, GrahaConverterUtility.defaultFontFamilyConverter 함수를 참조하여 작성한다.

파라미터로 넘어가는 것은 함수다.

defaultFontFamily: "Nanum Myeongjo" 은 미리 정의해 놓은 폰트 외에 다른 font-family 가 들어온 경우에 사용한다.

3.3. 웹페이지내에서 GrahaViewer 를 올리는 방법

먼저 다음과 같이 의존성 있는 외부 파일과 GrahaViewer 파일들을 html 에 추가한다.

<link rel="preconnect" href="//fonts.googleapis.com" />
<link rel="preconnect" href="//fonts.gstatic.com" crossorigin="anonymous" />
<style src="//fonts.googleapis.com/css2?family=Nanum+Gothic:wght@400;700;800&amp;amp;family=Nanum+Myeongjo:wght@400;700;800&amp;amp;display=swap" />
<script src="//cdn.jsdelivr.net/npm/bluebird@3.3.4/js/browser/bluebird.min.js" />
<script src="//cdn.jsdelivr.net/npm/has-font@1.0.2/hasfont.min.js" />
<script src="//cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js" />
<script src="//cdn.jsdelivr.net/npm/jspdf@2.5.2/dist/jspdf.umd.min.js" />
<script src="//cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js" />
<script src="//cdn.jsdelivr.net/npm/jspdf@2.5.2/dist/polyfills.umd.js" />
<script src="//cdn.jsdelivr.net/npm/jszip@3.10.1/dist/jszip.min.js" />
<script src="//cdn.jsdelivr.net/npm/jszip-utils@0.1.0/dist/jszip-utils.min.js" />
<style src="//graha.kr/static-contents/client_lib/GrahaViewer/lastest/GrahaViewer.css" />
<style src="//graha.kr/static-contents/client_lib/GrahaViewer/lastest/GrahaViewer.print.css" media="print" />
<script src="//graha.kr/static-contents/client_lib/GrahaViewer/lastest/GrahaHtmlConverterWrapper.js" />
<script src="//graha.kr/static-contents/client_lib/GrahaViewer/lastest/GrahaCSSProperties.js" />
<script src="//graha.kr/static-contents/client_lib/GrahaViewer/lastest/GrahaDummyElement.js" />
<script src="//graha.kr/static-contents/client_lib/GrahaViewer/lastest/GrahaOdtPageSplitterUtility.js" />
<script src="//graha.kr/static-contents/client_lib/GrahaViewer/lastest/GrahaHwpXPageSplitter.js" />
<script src="//graha.kr/static-contents/client_lib/GrahaViewer/lastest/GrahaConverterUtility.js" />
<script src="//graha.kr/static-contents/client_lib/GrahaViewer/lastest/GrahaOdtTableBorderCollapser.js" />
<script src="//graha.kr/static-contents/client_lib/GrahaViewer/lastest/GrahaHwpX2HtmlConverter.js" />
<script src="//graha.kr/static-contents/client_lib/GrahaViewer/lastest/GrahaOdt2HtmlConverter.js" />
<script src="//graha.kr/static-contents/client_lib/GrahaViewer/lastest/GrahaOdtPageSplitter.js" />
<script src="//graha.kr/static-contents/client_lib/GrahaViewer/lastest/GrahaConverter.js" />
<script src="//graha.kr/static-contents/client_lib/GrahaViewer/lastest/GrahaMenu.js" />
<script src="//graha.kr/static-contents/client_lib/GrahaViewer/lastest/GrahaViewer.js" />

다음과 같이 GrahaViewer.convert 를 호출한다.

GrahaViewer.convert(source);

source 는 string type 의 url 이거나, blob 이거나 file 이다.

폰트를 변경하기 위해서는 다음과 같이 처리한다.

var opts = {
fonts: GrahaViewerFontPlugin.fonts(),
fontFamilyConverter: GrahaViewerFontPlugin.fontFamilyConverter,
defaultFontFamily: "Nanum Myeongjo"
};
GrahaViewer.convert(source, opts);

3.4. 메뉴 변경 방법

3.4.1. 메뉴를 완전히 새롭게 작성하는 방법

GrahaMenu.js 의 GrahaMenus.default() 함수를 참조하여 작성한다.

3.4.2. title 변경 방법

GrahaViewer 의 default 메뉴에서 title 과 같이 일부 속성을 변경한 메뉴를 적용한다면 다음과 같은 형태이다.

var menus = GrahaMenus.default();
var list = menus.find("download");
if(list != null && Array.isArray(list) && list.length > 0) {
for(var i = 0; i < list.length; i++) {
list[i].setTitle("다운로드");
}
}
var opts = null;
GrahaViewer.convert(source, opts, menus);

odt.html 이나 hwpx.html 과 같이 단독 실행형 GrahaViewer 에서는 다음과 같이 ``GrahaViewer.ready``` 함수의 menus 파라미터로 넘길 수 있다.

var opts = null;
GrahaViewer.ready(opts, menus);

3.4.3. 단축키 변경 방법

현재 버전의 GrahaViewer 는 Esc 키를 누르면 close 메뉴가 실행된다.

만약 print 에 Alt + p 단축키를 추가하고 싶다면, 다음과 같이 한다.

var menus = GrahaMenus.default();
var list = menus.find("print");
if(list != null && Array.isArray(list) && list.length > 0) {
for(var i = 0; i < list.length; i++) {
list[i].setShortcut("KeyP");
list[i].setModifier("alt");
}
}
var opts = null;
GrahaViewer.convert(source, opts, menus);

위의 경우에 action 이 print 인 menu 는 1개만 있어야 할 것이다.

modifier 는 소문자 alt, ctrl, shift, meta 중 하나이다.

4. 남겨진 일들

4.1. 6개월 이내에는 처리할 것들 (처리가 완료되면 0.8.0.0 으로 release)

  • 여러 개의 hwpx 파일 혹은 여러 개의 odt 파일을 일괄 변환할 수 있도록 개선

    • blob 으로부터 변환하는 경우에만 지원
    • blob 배열로 입력받고, 다운로드는 압축 한 후에...
  • <hp:autoNum numType="TOTAL_PAGE" num="1"> 처리

    • <hp:autoNum numType="PAGE" num="1"> 는 각 페이지가 끝날 때 처리하고 있으나,
    • TOTAL_PAGE 는 GrahaHwpX2HtmlConverter.prototype.sections 가 끝날 때 처리해야 하는 것으로 생각됨.
    • "여러 개의 hwpx 파일~~~" 이후에 처리 예정

4.2. 1년 이내에는 처리할 것으로 기대되는 것들 (처리가 완료되면 0.9.0.0 으로 release)

  • <hp:rect>

    • hwpx
    • odt 는 div 로 구현함
    • <hp:line> 등 다른 것들은 구현하지 않을 계획
  • <hp:pic>

    • hwpx
    • odt 는 구현함

4.3. 1년이 지나도 처리하지 않을 가능성이 높은 것들

  • hwpx 파일 내에서 페이지 크기나 가로/세로가 다르게 정의된 경우
    • [한/글]에서 메뉴 > 쪽 > 구역 나누기(Alt + Shift + Enter) 를 하면, 각 구역마다 편집용지의 크기나 방향, 머리말/꼬리말을 다르게 설정할 수 있다.

4.4. 처리 할 생각이 없는 것들

  • hwpx : 양쪽 어울림

    • [한/글] 에서 "표/그림"이 어울림이라면 기본값이 "양쪽"이다.
    • html/css 는 양쪽 어울림을 지원하지 않으므로 페이지 넘김까지 고려하여 이를 처리하는 것은 구조적인 문제까지 다시 검토해야 한다.
  • hwpx : "text - 표 - text" 가 있고, 표의 세로 위치가 글자의 높이보다 큰 값인 경우

  • hwp 지원

    • 서버 쪽에서 hwp2hwpx 를 이용해서, 간단하게 hwp 파일을 hwpx 파일로 변환할 수 있기 때문에 구현하지 않는다.

4.5. 완료된 것들

  • hwpx.html 과 odt.html 에서 font cdn 에 preconnect 하도록 변경

    • 0.6.0.1 에서 처리 완료
  • hwpx 에서 <font> 의 css 가 그 아래의 <table> 에 적용되지 않도록 수정

    • 0.6.0.1 에서 처리 완료
  • hwpx 에서 color 값이 html 의 그것과 다르다.

    • #0000FF : [한/글]에서는 red 로 표시
    • #FF0000 : [한/글]에서는 blue 로 표시
    • [한/글] 은 color 값을 BGR 로 저장하는 것으로 생각됨 (R : 233, G : 174, B : 42 가 #2BAEE9으로 저장됨)
    • #FFFFFFFF 혹은 #FF000000 와 같은 것들은, RGBA 와 유사한 BGRA 라고 가정하고 처리하였음(테스트 X).
    • 0.6.0.1 에서 처리 완료
  • font-stretch (장평) 가 지원되는지 여부를 확인하여 관련 코드를 정리할 필요가 있음

    • 기본 폰트 cdn (//cdn.jsdelivr.net/font-nanum/1.0/nanumgothic/nanumgothic.css) 의 font 는 font-stretch 를 지원하지 않음.
    • 폰트 cdn 을 //fonts.googleapis.com/css2 로 시작하는 것으로 변경하면, font-stretch (장평) 가 처리되는 것으로 보임.
    • 장평에 따라 font-size 를 줄이는 코드는 주석으로 막았음.
    • PDF 변환할 때 사용하는 TrueType 도 같이 변경해야 함.
    • 0.6.0.1 에서 처리 완료
  • hwpx.html 혹은 odt.html 없이 실행할 수 있도록 변경

    • GrahaConverter.prototype.ready 함수 같은 것을 추가해서...
제목

첨부파일