Archive for the 'MacDown' Category

2016/06/23 オープン中のMarkdownドキュメントに、レンダリングに時間のかかるタグ要素がないかチェック v2

Mac用のオープンソースのMarkdownエディタ「MacDown」でオープン中の最前面のドキュメントをしらべ、Markdownテキスト中にレンダリングに時間のかかる画像および表の構成タグが入っていないかどうかを調べるAppleScriptの改良版です。

実運用してみたら、Tableのレンダリングは画像(Drobpboxからダウンロードして表示するという)処理にかかる時間よりは手短に終わるので、

 画像:20秒待ち
 Table:3秒待ち
 通常:1秒待ち

と、待機秒数を段階的に可変で返すルーチンに仕様を変更しました。また、Tableの検出がleft alighn cellのみの検出だったので、right align cellのタグについても調査するようにしました。

目下、週末土曜日の技術書典に向けて絶賛ラストスパート中ですが、

 AppleScript最新リファレンス:300ページ超え(増加中)
 最新事情がわかる AppleScript 10大最新技術:100ページ(作業終了間近)

と、合計400ページをすでに超えており、1冊分ビルドするためのオーバーヘッド縮小のためにこのようなチューニングが必要になってくるわけです。

AppleScript名:オープン中のMarkdownドキュメントに、レンダリングに時間のかかるタグ要素がないかチェック v2
– Created 2016-06-22 by Takaaki Naganoya
– 2016 Piyomaru Software

set mdRes to retImgOrTableTagsInMarkdownDoc() of me

–オープン中のMarkdownドキュメントに、レンダリングに時間のかかるタグ要素がないかチェック
on retImgOrTableTagsInMarkdownDoc()
  
  
tell application “MacDown”
    tell document 1
      set aProp to properties –個別に要素にアクセスできなかったので、まとめてプロパティを取得
    end tell
  end tell
  
  
set stList to text of aProp –なぜか、結果がファイル名、HTML、生Markdownのリストで返ってくる
  
set aBody to last item of stList –生Markdownテキストを取り出し
  
  
set aIMGFlag to aBody contains “![” –Image
  
set aTableFlag1 to aBody contains “:—” –Table (left align or center align cell)
  
set aTableFlag2 to aBody contains “—:” –Table (right align or center align cell)
  
set aTableFlag to (aTableFlag1 or aTableFlag2)
  
  
if aIMGFlag = true then
    return 20 –画像入りは20秒
  else if aTableFlag = true then
    return 3 –テーブル入りは3秒
  else
    return 1 –通常は1秒
  end if
  
end retImgOrTableTagsInMarkdownDoc

★Click Here to Open This Script 

2016/06/22 オープン中のMarkdownドキュメントに、レンダリングに時間のかかるタグ要素がないかチェック

Mac用のオープンソースのMarkdownエディタ「MacDown」でオープン中の最前面のドキュメントをしらべ、Markdownテキスト中にレンダリングに時間のかかる画像および表の構成タグが入っていないかどうかを調べるAppleScriptです。

MacDownの書類やPagesの書類をまとめてデスクトップフォルダにPDFで出力するAppleScriptを運用していたら、画像を含むページで画像抜けが発生する現象が確認されました。画像をすべてDropboxに置いて、それをリンクしているので余計に時間がかかるんですね。

また、表を含むページのレンダリングには時間がかかるので(表を入れすぎという噂も)、そちらへの対策も念のために行うべきと思われました。

そこで、MacDownでオープン中のドキュメントのソースにアクセスして、画像や表のタグが入っているかどうかを調査。入っていればtrue、入っていなければfalseを返すように書いてみました。

このルーチンの結果を参照して、trueが返ってきた場合にはドキュメントのオープン後、長めに時間待ちして(15秒とか)そのあとでPDF出力を行えば安全です。

最初は、一律に1書類あたり15秒時間待ちをしていたのですが、280ページ本1冊、100ページ本1冊をすべて出力するのに時間がかかりすぎるため、必要な書類についてのみ時間待ちを行うように処理を最適化。

280ページの本については300ページ越えが確実なので、合計400ページも書いていることに。6月25日土曜日の技術書系同人誌即売会「技術書典」まであと少しです。

AppleScript名:オープン中のMarkdownドキュメントに、レンダリングに時間のかかるタグ要素がないかチェック
– Created 2016-06-22 by Takaaki Naganoya
– 2016 Piyomaru Software

set mdRes to retImgOrTableTagsInMarkdownDoc() of me

–オープン中のMarkdownドキュメントに、レンダリングに時間のかかるタグ要素がないかチェック
on retImgOrTableTagsInMarkdownDoc()
  
  
tell application “MacDown”
    tell document 1
      set aProp to properties –個別に要素にアクセスできなかったので、まとめてプロパティを取得
    end tell
  end tell
  
  
set stList to text of aProp –なぜか、結果がファイル名、HTML、生Markdownのリストで返ってくる
  
set aBody to last item of stList –生Markdownテキストを取り出し
  
  
set aIMGFlag to aBody contains “![” –Image
  
set aTableFlag to aBody contains “:—” –Table
  
  
–どちらか含んでいればレンダリングに時間がかかるのでフラグをtrueで返す
  
return (aIMGFlag or aTableFlag)
  
end retImgOrTableTagsInMarkdownDoc

★Click Here to Open This Script 

2016/06/18 指定フォルダ以下にあるMacDownとPages書類をソートしてPDFに書き出す

指定フォルダ以下にあるMacDownで記述したMarkdown書類と、Pages書類をすべての階層からピックアップしてファイル名でソートして、すべてデスクトップにPDFで書き出すAppleScriptです。

コンパイル(構文確認)および実行に際しては、Shane StanleyのScript Library「Bridge Plus」をインストールしておく必要があります。また、GUI Scriptingを利用しているため「システム環境設定」>「セキュリティとプライバシー」>「プライバシー」>「アクセシビリティ」でスクリプトエディタ(アプレットとして実行する場合にはアプレットそのもの)を登録して許可しておく必要があります。

「技術書典」に出す電子ブックのフォーマットがギリギリまで決まらず、しかも縦長のスクロールさせるタイプのものにできないかとあがいていたのですが、結局iPadあたりで読むことを考慮するとiPadのリーダーの仕様にしたがう必要があります。

……あれ?(^ー^; 結局、ページめくりは発生するし、一般的な本と同じような体裁になってしまいますよ → フォーマットがPDFになりました。

Markdown書類とPages書類が混在しているフォルダ構造のトップ階層のフォルダを指定すると、Markdown書類とPages書類をピックアップし、ファイル名でそれらをソートし、順次PDFに書き出すAppleScriptを書いてみました(必要は発明のマザー!)。

book1.png

ただ、MacDownには「書類をPDFに書き出す」という機能がAppleScript側に公開されていません(T_T)。

macdown_dict.png

ないものを「ないない」と嘆いても仕方がないので、さっさとGUI Scriptingで強制的にメニュー操作することにしました。

macdown_gui.png

で、どこに? どこに保存させるのでしょう??

大丈夫! そんなときには、保存ダイアログで幾つかのフォルダに強制的に移動させるキーボードショートカットが存在しており、Command-Dは「カレントディレクトリをデスクトップに移動させる」=「保存先をデスクトップにする」働きをします。

このため、保存先を操作しづらい(不可能とはいいませんけれども)GUI Scriptingにおいて保存先を指定することが、デスクトップフォルダについては可能になっています。

Pagesの方はひじょうに素直に(GUI Scriptingなんて使わずに)PDF書き出しが可能です。

そんなわけで、時間に追い詰められながらもなんとか大量のデータ処理を行っているのでありました。書き出した大量のPDFもAppleScriptでさくっと連結できるので、非常にいい感じです。あとは、本が完成すれば、、、、

AppleScript名:指定フォルダ以下にあるMDとPagesをソートしてPDFに書き出す
– Created 2016-06-17 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use BridgePlus : script “BridgePlus”
–use spotLight : script “spotlightLib”

property searchRes : {}

load framework

set origPath to POSIX path of (choose folder with prompt “Markdown/Pages ファイルの入っているフォルダを選択”)

set aResList to (spotlightSearch(origPath, “kMDItemKind == ’Markdown’ || kMDItemKind == ’Pages 一般書類’”) of me) as list –Caution! this parameter is *localized*

–フルパスとファイル名のペアの2D Listを作成
set newList to {}
repeat with i in aResList
  set j to contents of i
  
set aStr to (current application’s NSString’s stringWithString:j)
  
set aFileName to aStr’s lastPathComponent()
  
set the end of newList to {aStr, aFileName}
end repeat

–番号順にソート
set sortIndexes to {1} –Key Item id: begin from 0, Sort by filename
set sortOrders to {true}
set sortTypes to {“compare:”}
set resList to (current application’s SMSForder’s subarraysIn:(newList) sortedByIndexes:sortIndexes ascending:sortOrders sortTypes:sortTypes |error|:(missing value)) as list
if resList = {} then return –No Result

–ソートした順番にMarkdownファイル/Pages書類ファイルをオープンしてデスクトップにPDF生成してクローズ
repeat with i in newList
  copy i to {fullPath, aFileName}
  
  
set apFile to (POSIX file (fullPath as string))
  
set anAlias to apFile as alias
  
set aFileName to aFileName as string
  
  
if aFileName ends with “.md” then
    exportFromMacDown(anAlias) of me –Markdown
  else if aFileName ends with “.pages” then
    exportFromPages(anAlias) of me –Pages
  end if
end repeat

–指定のPagesファイル(alias)をデスクトップ上にPDFで書き出し
on exportFromPages(anAlias)
  tell application “Finder”
    set aName to name of anAlias
  end tell
  
  
set dtPath to (path to desktop) as string
  
set outPath to dtPath & aName & “.pdf”
  
  
tell application “Pages”
    close every document without saving
    
open anAlias
    
export document 1 to file outPath as PDF with properties {image quality:Best}
    
close every document without saving
  end tell
end exportFromPages

–指定のMacDownファイル(alias)をデスクトップ上にPDFで書き出し
on exportFromMacDown(anAlias)
  tell application “MacDown”
    open {anAlias}
  end tell
  
  
tell current application
    delay 1 –ここの時間待ちが少ないと画像抜けが発生?
  end tell
  
macDownForceSave() of me
  
  
tell application “MacDown”
    close every document without saving
  end tell
end exportFromMacDown

–注意!! ここで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

–Spotlight Libの内容を引っ張り出してきた
on spotlightSearch(origPOSIXpath, aCondition)
  
  
set searchRes to {} –initialize
  
  
initiateSearchForFullPath(aCondition, origPOSIXpath) –Predicate & Scope Directory
  
  
–Waiting for the result
  
repeat while searchRes = {}
    current application’s NSThread’s sleepForTimeInterval:(“0.001″ as real) –delay 0.001
  end repeat
  
  
set anObj to searchRes’s firstObject() –Pick up the first one for test
  
if anObj = missing value then return {} –No Result
  
  
–set anAttrList to anObj’s attributes() –”mdls” attributes
  
–>  (NSArray) {”kMDItemContentTypeTree”, “kMDItemContentType”, “kMDItemPhysicalSize”, …}
  
  
set resArray to {}
  
repeat with anItem in my searchRes
    set j to contents of anItem
    
set aPath to (j’s valueForAttribute:“kMDItemPath”) as string
    
set the end of resArray to aPath
  end repeat
  
  
return resArray
end spotlightSearch

on initiateSearchForFullPath(aQueryStrings, origPath)
  
  
set aSearch to current application’s NSMetadataQuery’s alloc()’s init()
  
  
current application’s NSNotificationCenter’s defaultCenter()’s addObserver:(me) selector:“queryDidUpdate:” |name|:(current application’s NSMetadataQueryDidUpdateNotification) object:aSearch
  
current application’s NSNotificationCenter’s defaultCenter()’s addObserver:(me) selector:“initalGatherComplete:” |name|:(current application’s NSMetadataQueryDidFinishGatheringNotification) object:aSearch
  
  
set aPredicate to current application’s NSPredicate’s predicateWithFormat:aQueryStrings
  
aSearch’s setPredicate:aPredicate
  
  
set aScope to current application’s NSArray’s arrayWithObjects:{origPath}
  
aSearch’s setSearchScopes:aScope
  
  
set sortKeys to current application’s NSSortDescriptor’s sortDescriptorWithKey:“kMDItemFSName” ascending:true
  
aSearch’s setSortDescriptors:(current application’s NSArray’s arrayWithObject:sortKeys)
  
  
aSearch’s startQuery()
  
end initiateSearchForFullPath

on queryDidUpdate:sender
  –  
end queryDidUpdate:

on initalGatherComplete:sender
  set anObject to sender’s object
  
anObject’s stopQuery()
  
current application’s NSNotificationCenter’s defaultCenter()’s removeObserver:me |name|:(current application’s NSMetadataQueryDidUpdateNotification) object:anObject
  
current application’s NSNotificationCenter’s defaultCenter()’s removeObserver:me |name|:(current application’s NSMetadataQueryDidFinishGatheringNotification) object:anObject
  
set my searchRes to anObject’s results()
end initalGatherComplete:

★Click Here to Open This Script