원문 캡처 · github.com
원문 캡처 · github.com

Markdown Viewer는 macOS에서 Markdown 문서를 Finder의 Quick Look 미리보기로 보거나 Preview에서 PDF로 열 수 있는 앱이다. .md, .markdown, .mdown, .mkd, .mkdn 파일을 지원하며, 두 방식 모두 GitHub 스타일 Markdown을 처리한다.

Finder에서 문서를 선택하고 스페이스 바를 누르면 서식이 적용된 미리보기가 표시된다. 문서를 두 번 클릭하면 A4 PDF로 변환되어 Preview에서 열린다. 표, 작업 목록, 취소선, 자동 링크, 각주, 코드 펜스가 지원된다. 원시 HTML은 변경 없이 전달된다. Quick Look 미리보기는 macOS의 라이트·다크 모드를 따르지만 PDF는 항상 흰색 페이지로 렌더링된다.

요구 사항

요구 사항은 macOS 13 이상, 명령줄 도구를 포함한 Xcode 15 이상, XcodeGen이다. XcodeGen은 다음 명령으로 설치할 수 있다.

sh
brew install xcodegen

설치

앱은 소스에서 빌드한다. 저장소를 복제한 뒤 설치 스크립트를 실행한다.

sh
git clone https://github.com/invertedworld/markdown-viewer.git
cd markdown-viewer
scripts/install.sh

스크립트는 Xcode 프로젝트를 생성하고 앱을 빌드해 /Applications에 복사한다. 이어 Quick Look 확장 프로그램을 등록하고 Markdown 문서의 기본 앱으로 설정한다. macOS에서 기본 앱 변경을 확인하라는 메시지가 표시될 수 있다.

기본 설정에서는 앱에 임시 서명이 적용된다. 이는 앱을 빌드한 Mac에서 사용하는 데 충분하다. Apple Development 인증서로 서명하려면 팀 식별자를 지정한다.

sh
TEAM=ABCDE12345 scripts/install.sh

팀 식별자는 Xcode의 Settings > Accounts 또는 Apple Developer 계정의 Membership details에서 확인할 수 있다.

설치 후에는 두 기능을 확인한다.

  1. Quick Look: Finder에서 Markdown 문서를 선택하고 스페이스 바를 누른다. 문서에 서식이 적용되어 표시된다. 일반 텍스트로만 보이면 System Settings > General > Login Items & Extensions > Quick Look에서 확장 프로그램이 활성화되어 있는지 확인한다. 필요하면 Option 키를 누른 채 Dock의 Finder 아이콘을 Control-클릭하고 Relaunch를 선택해 Finder를 다시 실행한다.
  2. Preview에서 열기: Markdown 문서를 두 번 클릭하면 Preview에서 PDF로 열린다. 다른 앱에서 열리면 Finder에서 문서를 선택하고 File > Get Info를 연다. Open with에서 Markdown Viewer를 선택한 뒤 Change All…을 클릭한다. 또는 Applications 폴더에서 Markdown Viewer를 실행하고 Set as Default for Markdown Files를 클릭한다.

Markdown용 Quick Look 확장 프로그램이 다른 앱에도 설치되어 있다면 macOS는 그중 하나만 사용한다. 나머지 확장 프로그램은 System Settings에서 비활성화해야 한다.

제거

/Applications/Markdown Viewer.app을 휴지통으로 옮기면 앱이 제거된다. 캐시 파일은 다음 명령으로 삭제할 수 있다.

sh
rm -rf ~/Library/Caches/com.invertedworld.MarkdownViewer

그 뒤 Get Info > Open with > Change All…에서 Markdown 문서에 사용할 다른 앱을 선택한다.

Preview에서 열기

Markdown 문서를 열면 Markdown Viewer는 WebKit으로 문서를 렌더링하고, 여백 15 mm의 A4 PDF로 출력한 뒤 Preview에 전달하고 종료한다. PDF는 원본 문서별 하위 폴더를 만들어 ~/Library/Caches/com.invertedworld.MarkdownViewer/에 저장하며, 원본 문서와 같은 이름을 사용한다. 상대 링크와 이미지는 원본 문서가 있는 폴더를 기준으로 해석하므로 로컬 이미지도 포함된다. 7일이 지난 렌더링 파일은 자동으로 삭제된다.

PDF는 문서를 열었을 당시의 내용을 담은 스냅샷이다. 이후 변경 사항을 보려면 문서를 다시 열어야 하며, 이때 Preview가 갱신된 PDF를 다시 불러온다.

Quick Look 미리보기

Quick Look 확장 프로그램은 macOS 샌드박스에서 실행되므로 미리보는 문서만 읽을 수 있다. 따라서 문서와 같은 폴더에 저장된 이미지는 미리보기에 표시되지 않는다. https:// 주소로 참조한 이미지는 표시된다.

Xcode에서 빌드

프로젝트 설정은 project.yml에 있으며 XcodeGen으로 생성한다. 생성된 MarkdownViewer.xcodeproj 파일은 저장소에 포함되지 않는다. Markdown 파싱에는 cmark-gfm을 사용하는 swift-cmark를 쓰며, Xcode가 Swift Package Manager를 통해 가져온다.

sh
xcodegen generate
open MarkdownViewer.xcodeproj

project.yml은 제작자의 Developer ID 인증서로 서명하도록 설정되어 있다. 다른 계정으로 Xcode에서 빌드하려면 두 타깃의 Signing & Capabilities에서 팀을 변경하거나, scripts/install.sh처럼 xcodebuild 명령줄에서 DEVELOPMENT_TEAM 및 CODE_SIGN_IDENTITY 설정을 재정의해야 한다. 명령줄에서 기본 앱을 설정할 수도 있다.

sh
open -a "Markdown Viewer" --args --set-default

Samples/sample.md에는 지원 기능별 예제가 들어 있다.

라이선스

Markdown Viewer는 MIT 라이선스로 배포된다. 자세한 내용은 LICENSE에서 확인할 수 있다. swift-cmark는 자체 라이선스에 따라 배포된다.

동작 원리

두 구성 요소는 Shared/MarkdownRenderer.swift를 공유한다. 이 파일은 cmark-gfm으로 문서를 파싱하고 GitHub 확장을 활성화한 뒤, 임베디드 스타일시트가 포함된 페이지에 결과 HTML을 넣는다.

Quick Look 확장 프로그램(QuickLook/PreviewProvider.swift)은 데이터 기반 미리보기 제공자로, 이 HTML을 Quick Look에 반환한다. 앱(App/)은 net.daringfireball.markdown 유형의 문서 뷰어로 등록된다. 문서 열기 요청을 받으면 문서를 렌더링하고 문서가 있는 폴더를 가리키는 <base> 요소를 삽입한다. 그다음 화면에 표시되지 않는 WebKit 뷰에 페이지를 불러와 PDF 파일로 출력하고, 해당 파일을 Preview에서 연다. 파일 전달이 취소되는 일을 막기 위해 Preview가 파일을 받은 것을 확인한 뒤 앱이 종료된다.