CotEditorで編集中のMarkdown書類を、MacDownでPDF書き出しして、Skimでオープンして表示するAppleScriptです。
CotEditorにMarkdownのプレビュー機能がついたらいいと思っている人は多いようですが、MarkdownはMarkdownで、方言は多いし標準がないし、1枚もののMarkdown書類だけ編集できればいいのか、本などのプロジェクト単位で編集とか、目次が作成できないとダメとか、リンクした画像の扱いをどうするのかとか、対応しようとすると「ほぼ別のソフトを作るのと同じ」ぐらい手間がかかりそうです(メンテナー様ご本人談)。
そこで、AppleScript経由で他のソフトを連携させてPDFプレビューさせてみました。これなら、誰にも迷惑をかけずに、今日この時点からすぐにMarkdownのプレビューが行えます(当然、HTML書き出ししてSafariでプレビューするバージョンははるかかなた昔に作ってあります)。
ただし、OS側の機能制限の問題で、CotEditor上のスクリプトメニューから実行はできません(GUI Scriptingの実行が許可されない)。OS側のスクリプトメニューに登録して実行する必要があります。
GUI Scriptingを利用してメニュー操作を行なっているため、システム環境設定で許可しておく必要があります。
本来であれば、PDFの書き出し先フォルダ(この場合は書き出しダイアログで、GUI Scirptingを用いてCommand-Dで指定して一律に場所指定が行えるデスクトップフォルダ)に同名のPDFが存在しないかどうかチェックし、存在すれば削除するといった処理が必要ですが、面倒だったのであらかじめMarkdown書類をUUIDにリネームしておくことで、書き出されたPDFも同じくUUIDのファイル名になるため、論理上はファイル名の衝突を回避できるため、削除処理を省略しています。
AppleScript名:🌏レンダリングしてPDFプレビュー |
— Created 2019-06-15 by Takaaki Naganoya — 2019 Piyomaru Software use AppleScript version "2.5" use scripting additions use framework "Foundation" use framework "AppKit" property NSUUID : a reference to current application’s NSUUID property NSWorkspace : a reference to current application’s NSWorkspace –オープン中のMarkdown書類を取得する tell application "CotEditor" tell front document set cStyle to coloring style if cStyle is not equal to "Markdown" then display dialog "編集中のファイルはMarkdown書類ではないようです。" buttons {"OK"} default button 1 return end if set aPath to path end tell end tell –一時フォルダにMarkdown書類をコピー set sPath to (path to temporary items) tell application "Finder" set sRes to (duplicate ((POSIX file aPath) as alias) to folder sPath with replacing) end tell –コピーしたMarkdown書類をリネーム set s1Res to sRes as alias set aUUID to NSUUID’s UUID()’s UUIDString() as text –UUIDを作成する tell application "Finder" set name of s1Res to (aUUID & ".md") end tell –Markdown書類をデスクトップにPDF書き出し set pdfRes to exportFromMacDown(POSIX path of s1Res) of me –PDF Viewerでオープン tell application "Skim" –Preview.appでもOK activate open pdfRes end tell –一時フォルダに書き出したMarkdown書類を削除 tell application "Finder" delete s1Res end tell –指定のMacDownファイル(alias)をデスクトップ上にPDFで書き出し on exportFromMacDown(anAlias) set s1Text to paragraphs of (do shell script "ls ~/Desktop/*.pdf") –pdf書き出し前のファイル一覧 tell application "MacDown" open {anAlias} end tell macDownForceSave() of me tell application "MacDown" close every document without saving end tell do shell script "sync" –ねんのため set s2Text to paragraphs of (do shell script "ls ~/Desktop/*.pdf") –pdf書き出し後のファイル一覧 set dRes to getDiffBetweenLists(s1Text, s2Text) of me –デスクトップ上のPDFファイル名一覧の差分を取得 set d2Res to (addItems of dRes) if length of d2Res ≥ 1 then return contents of first item of d2Res else error "Error in exporting PDF to desktop folder…." end if end exportFromMacDown on getDiffBetweenLists(aArray as list, bArray as list) set allSet to current application’s NSMutableSet’s setWithArray:aArray allSet’s addObjectsFromArray:bArray –重複する要素のみ抜き出す set duplicateSet to current application’s NSMutableSet’s setWithArray:aArray duplicateSet’s intersectSet:(current application’s NSSet’s setWithArray:bArray) –重複部分を削除する allSet’s minusSet:duplicateSet set resArray to (allSet’s allObjects()) as list set aSet to current application’s NSMutableSet’s setWithArray:aArray set bSet to current application’s NSMutableSet’s setWithArray:resArray aSet’s intersectSet:bSet –積集合 set addRes to aSet’s allObjects() as list set cSet to current application’s NSMutableSet’s setWithArray:bArray cSet’s intersectSet:bSet –積集合 set minusRes to cSet’s allObjects() as list return {addItems:minusRes, minusItems:addRes} end getDiffBetweenLists –注意!! ここでGUI Scriptingを使用。バージョンが変わったときにメニュー階層などの変更があったら書き換え on macDownForceSave() activate application "MacDown" tell application "System Events" tell process "MacDown" — File > Export > PDF click menu item 2 of menu 1 of menu item 14 of menu 1 of menu bar item 3 of menu bar 1 –Go to Desktop Folder keystroke "d" using {command down} –Save Button on Sheet click button 1 of sheet 1 of window 1 end tell end tell end macDownForceSave –Bundle IDからアプリケーションのPathを返す on retAppAbusolutePathFromBundleID(aBundleID) set appPath to NSWorkspace’s sharedWorkspace()’s absolutePathForAppBundleWithIdentifier:aBundleID if appPath = missing value then return false return appPath as string end retAppAbusolutePathFromBundleID |