Markdown書類からリンクしているローカルの画像(相対パス表記)へのリンクを書き換えるAppleScriptです。
MacDownが画像リンクの管理などは一切してくれないので、自前で(AppleScriptで)書き換えを行なっています。
ルートフォルダはフォルダ名が「–」ではじまるようにルールを(勝手に)決めており、各Markdown書類フォルダをさらに細分化した場合には、Markdown書類から画像フォルダへの相対パス指定が合わなくなってしまいます。
そこで、画像フォルダを求めてMarkdown書類の画像リンクを再計算して書き換えてみました。画像自体をルートフォルダからSpotlightで検索するようにしてもよいのですが、今回はとりあえずルールを自分で決めて自分で守っているので、このように処理してみました。
ただ、いまだにリンク画像のパスを手で書かされる(記述自体はAppleScriptでその場で計算しているので完全手書きではないですが)のには、いささかMarkdownの仕様の素朴さに呆れてしまうところです、、、、
AppleScript名:Markdownのimglinkタグ行のリンク書き換え |
— Created 2017-01-26 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use mdLib : script "Metadata Lib" version "2.0.0" –https://www.macosxautomation.com/applescript/apps/ property NSArray : a reference to current application’s NSArray property NSString : a reference to current application’s NSString property NSScanner : a reference to current application’s NSScanner property NSPredicate : a reference to current application’s NSPredicate property NSDictionary : a reference to current application’s NSDictionary property NSMutableArray : a reference to current application’s NSMutableArray property NSDataDetector : a reference to current application’s NSDataDetector property NSAttributedString : a reference to current application’s NSAttributedString property NSUTF8StringEncoding : a reference to current application’s NSUTF8StringEncoding property NSTextCheckingTypeLink : a reference to current application’s NSTextCheckingTypeLink set origPath to POSIX path of (choose folder with prompt "Markdown書類が入っているフォルダを選択") set savePath to POSIX path of (choose folder with prompt "画像フォルダを選択") set tmp2 to NSString’s stringWithString:savePath set tmp3 to (tmp2’s lastPathComponent()) as string –Spotlightで指定フォルダ以下のMarkdown書類を検索 set aRes to mdLib’s searchFolders:{origPath} searchString:("kMDItemKind == %@ ") searchArgs:{"Markdown Document"} repeat with i in aRes –テキストエンコーディングをUTF-8でMarkDown書類テキスト読み込み set aText to (NSString’s stringWithContentsOfFile:(i) encoding:(NSUTF8StringEncoding) |error|:(missing value)) as string –Markdown記法の画像タグが入っている場合のみ処理 set repLinkURLs to {} –パス置換対象リスト(oldPath, newPathでペア) set aFreq to retFrequency(aText, "![") of me if aFreq is not equal to 0 then set bList to parseStringParagraphs(NSString’s stringWithString:aText) of me set aPredicates to NSPredicate’s predicateWithFormat_("SELF BEGINSWITH[cd] %@", "![") set cList to (bList’s filteredArrayUsingPredicate:aPredicates) as list –画像ダウンロードおよび、ダウンロードずみ画像への相対パスの計算ループ repeat with ii in cList set jj to contents of ii –画像リンクのMarkdownタグ行 set tmpLinkPath to parseStrFromTo(jj, "(", ")") of me set aStr to (NSString’s stringWithString:((contents of i) as string)) set aList to (aStr’s stringByDeletingLastPathComponent’s pathComponents()) as list of string or string set aLen to length of aList –リンク画像の相対パスを絶対パスに変換する set rStr to (NSString’s stringWithString:tmpLinkPath) set r2Str to rStr’s stringByDeletingLastPathComponent’s lastPathComponent() –フォルダ名(="9999_images") set r3Str to (rStr’s lastPathComponent()) as string –ファイル名(="fake_scriptable.png") –書籍のルートフォルダを求め、その直下にある画像フォルダを名指しで指定 repeat with i2 from aLen to 0 by -1 set j to contents of (item i2 of aList) if j begins with "–" then exit repeat end if end repeat set f1Path to (items 1 thru i2 of aList) & r2Str & r3Str set f2Path to (NSString’s pathWithComponents:f1Path) as string –MarkDown書類と移動先の画像フォルダ中の画像の相対パスを求める set newRelPath to calcRelativePathFromTwoAbsolutePaths(i, f2Path) of me set the end of repLinkURLs to {tmpLinkPath, newRelPath} end repeat –リンク書き換え copy aText to bText repeat with ii in repLinkURLs copy ii to {oldPath, newPath} set bText to repChar(bText, oldPath, newPath) of me end repeat –もともとのパスにMarkdown書類を上書き保存 set writeString to (NSString’s stringWithString:bText) set ssRes to (writeString’s writeToFile:i atomically:true encoding:(NSUTF8StringEncoding) |error|:(missing value)) end if end repeat –指定文字列内の指定キーワードの出現回数を取得する on retFrequency(origText, aKeyText) set aRes to parseByDelim(origText, aKeyText) of me return ((count every item of aRes) – 1) end retFrequency on parseByDelim(aData, aDelim) set curDelim to AppleScript’s text item delimiters set AppleScript’s text item delimiters to aDelim set dList to text items of aData set AppleScript’s text item delimiters to curDelim return dList end parseByDelim –テキストを行ごとにparseしてNSArrayに on parseStringParagraphs(anNSString) set anArray to NSMutableArray’s alloc()’s init() set aRange to current application’s NSMakeRange(0, anNSString’s |length|()) repeat while aRange’s |length|() > 0 set subRange to anNSString’s lineRangeForRange:(current application’s NSMakeRange(aRange’s location(), 0)) –行が改行コードまで取得されるので、改行コードを除外するように微調整 copy subRange to tmpRange set tmpRange’s |length| to ((subRange’s |length|()) – 1) –微調整 set aLine to anNSString’s substringWithRange:tmpRange anArray’s addObject:aLine set aRange’s location to (current application’s NSMaxRange(subRange)) set aRange’s |length| to ((aRange’s |length|()) – (subRange’s |length|())) end repeat return anArray end parseStringParagraphs on repChar(origText, targStr, repStr) set {txdl, AppleScript’s text item delimiters} to {AppleScript’s text item delimiters, targStr} set temp to text items of origText set AppleScript’s text item delimiters to repStr set res to temp as text set AppleScript’s text item delimiters to txdl return res end repChar on parseStrFromTo(aParamStr, fromStr, toStr) set theScanner to NSScanner’s scannerWithString:aParamStr set anArray to NSMutableArray’s array() repeat until (theScanner’s isAtEnd as boolean) — terminate check, return the result (aDict) to caller set {theResult, theKey} to theScanner’s scanUpToString:fromStr intoString:(reference) — skip over separator theScanner’s scanString:fromStr intoString:(missing value) set {theResult, theValue} to theScanner’s scanUpToString:toStr intoString:(reference) if theValue is missing value then set theValue to "" –>追加 — skip over separator theScanner’s scanString:toStr intoString:(missing value) anArray’s addObject:theValue end repeat if (anArray’s |count|()) as integer = 1 then return theValue as list of string or string else return anArray as list end if end parseStrFromTo –2つの絶対パス間の相対パスを求める on calcRelativePathFromTwoAbsolutePaths(aPOSIXfile as string, bPOSIXfile as string) set aStr to NSString’s stringWithString:aPOSIXfile set bStr to NSString’s stringWithString:bPOSIXfile set aList to aStr’s pathComponents() as list set bList to bStr’s pathComponents() as list set aLen to length of aList set bLen to length of bList if aLen ≥ bLen then copy aLen to aMax else copy bLen to aMax end if repeat with i from 1 to aMax set aTmp to contents of item i of aList set bTmp to contents of item i of bList if aTmp is not equal to bTmp then exit repeat end if end repeat set bbList to items i thru -1 of bList set aaItem to (length of aList) – i set tmpStr to {} repeat with ii from 1 to aaItem set the end of tmpStr to ".." end repeat set allRes to NSString’s pathWithComponents:(tmpStr & bbList) return allRes as text end calcRelativePathFromTwoAbsolutePaths |
More from my site
(Visited 129 times, 1 visits today)