edama2さんからの投稿です。実際に動かして「こんな素朴な記述でMarkdownのプレビューができるのか?!」とぶっ飛びましたが、箱庭グラフ表示シリーズ(JavaScriptのライブラリに描画丸投げ)と同様、外部のJavaScriptライブラリを呼んで表示しています。
→ Download archive
タイトルは「アラートダイアログでMarkdownをプレビュー」
アラートダイアログ上でMarkdownのプレビュー表示をします
中身はhtml内のjavascriptで変換してWkWebViewで表示しているだけなので今更目新しいこともありません
一応うまく動いていると思いますが、いろんなパターンを試したわけじゃないのでちょっと不安です
技術的に見所が多すぎて困るぐらいの内容です。ちょろっと流せるぐらいの規模ではありません。
JavaScriptのライブラリでMarkdownのプレビューが行えるというのは、割と盲点でした。グラフやらアニメーションやらはさんざんJavaScriptを呼び出して表示させていましたが、Markdownのプレビューまで行えるとは。
主に、Markdownのレンダリング系のフレームワークとか、AppleがXcodeに添付したMarkdownのプレビュー機能あたりが活用できないか調べていたことはありましたが、CDN上のJavaScriptを呼び出してプレビューというのはなかなか強力です。
さらに、本Scriptはblocks構文が必要なAPIに対してパラメータにmissing valueを指定することで呼び出せています。
blocks構文のパラメータにヌル文字やmissing valueを指定することで誤魔化せるケースがあることはedama2さんと話して知っていましたが、実例として提示されたのはこれがはじめてでしょう(macscripter.netでも見かけない)。
また、箱庭WebViewダイアログ系のプログラムが「スクリプトエディタ上から実行すると、実行後にウィンドウのオブジェクトがメモリ上に残ったままになる」という問題を抱えていた点を解決……はできていないですね。Appletで動かせば解決できるのと、親プロセス(スクリプトエディタやScript Debugger)が終了するとまとめて消えるので、その方向でなんとか対処を。
▲添付のサンプルMarkdown書類をプレビューしたところ。表のレンダリングができている点に驚き
▲実際に書籍用にメンテナンスしているMarkdown書類をプレビュー。applescript://のURLリンクも有効。インラインHTMLの類いも使える
▲箱庭Webダイアログの負の遺産、実行するたびにたまるゴミプロセス。これで解消なるか?!→それは無理でした
ちなみに、CotEditorのスクリプトメニューに組み込んで実行してみましたが、ネットワークへのアクセスが必要なためCotEditor側のセキュリティポリシーと合わずに実行できませんでした。 → できました。WebKitをuseし忘れていただけのようです(CDN上のライブラリで円グラフ表示できているので、逆にできないのがおかしいと気づきました)。
macOS標準装備のスクリプトメニュー内から、Applet形式に書き出したAppleScriptを呼び出すスタイルにしたら実行できました。
AppleScript名:アラートダイアログでMarkdownをプレビュー |
use AppleScript
use framework “Foundation”
use scripting additions
on run
my main()
end run
on main()
set mes to “Markdownファイルを選択してください。”
set chooseItems to choose file of type {“net.daringfireball.markdown”} with prompt mes
#
set aScreen to current application’s NSScreen’s mainScreen()
set screenFrame to aScreen’s frame()
set aHeight to current application’s NSHeight(screenFrame)
set aWidth to current application’s NSWidth(screenFrame)
set aHeight to aHeight * 0.845
set aWidth to aWidth * 0.94 / 2
set paramObj to {}
set paramObj to paramObj & {myMessage:“Markdown preview”}
set paramObj to paramObj & {mySubMessage:“file : “ & chooseItems’s POSIX path}
set paramObj to paramObj & {mdFile:chooseItems}
set paramObj to paramObj & {viewWidth:aWidth}
set paramObj to paramObj & {viewHeight:aHeight}
my performSelectorOnMainThread:“displayMarkdownPreview:” withObject:(paramObj) waitUntilDone:true
end main
# Markdownをダイアログで表示
on displayMarkdownPreview:paramObj
set mesText to myMessage of paramObj as text
set infoText to mySubMessage of paramObj as text
set mdFile to (mdFile of paramObj) as alias
set viewWidth to (viewWidth of paramObj) as integer
set viewHeight to (viewHeight of paramObj) as integer
## HTMLを読み込む
set mePath to path to me
set resPath to (mePath & “Contents:Resources:index.html”) as text
set htmlStr to (read (resPath as alias) as «class utf8») as text
## MDを読み込む
set mdStr to (read mdFile as «class utf8») as text
## MD内に改行があるとうまく読み込まれないので改行を置き換え
set mdStr to current application’s NSString’s stringWithString:mdStr
set mdStr to mdStr’s stringByReplacingOccurrencesOfString:(linefeed) withString:“\\n”
set mdStr to mdStr’s stringByReplacingOccurrencesOfString:“’” withString:“\\’”
## html内の文字を置き換え
set aString to current application’s NSString’s stringWithFormat_(htmlStr, mdStr) as text
log result
## baseURL
set aPath to mdFile’s POSIX path
set baseURL to current application’s NSURL’s fileURLWithPath:aPath
set baseURL to baseURL’s URLByDeletingLastPathComponent()
##
set aConf to current application’s WKWebViewConfiguration’s new()
tell current application’s WKUserContentController’s new()
aConf’s setUserContentController:it
end tell
## WebViewを作成&読み込み
set frameSize to current application’s NSMakeRect(0, 0, viewWidth, viewHeight)
tell current application’s WKWebView’s alloc()
tell initWithFrame_configuration_(frameSize, aConf)
setNavigationDelegate_(me)
setUIDelegate_(me)
loadHTMLString_baseURL_(aString, baseURL)
set theView to it
end tell
end tell
## アイコンの指定
set aImage to current application’s NSWorkspace’s sharedWorkspace()’s iconForFileType:“net.daringfireball.markdown”
## set up alert
tell current application’s NSAlert’s new()
addButtonWithTitle_(“Close”)
setAccessoryView_(theView)
setIcon_(aImage)
setInformativeText_(infoText)
setMessageText_(mesText)
tell |window|()
setInitialFirstResponder_(theView)
end tell
### show alert in modal loop
if runModal() is (current application’s NSAlertSecondButtonReturn) then return
end tell
##後始末
theView’s stopLoading()
set js to “window.open(’about:blank’,’_self’).close();”
theView’s evaluateJavaScript:js completionHandler:(missing value)
set theView to missing value
end displayMarkdownPreview:
|
★Click Here to Open This Script |