— Created 2018-07-30 by Takaaki Naganoya — Modified 2018-08-05 by Takaaki Naganoya  — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" use framework "OSAKit" use framework "HTMLReader" –https://github.com/nolanw/HTMLReader
property |NSURL| : a reference to current application’s |NSURL| property NSArray : a reference to current application’s NSArray property NSString : a reference to current application’s NSString property NSBundle : a reference to current application’s NSBundle property NSThread : a reference to current application’s NSThread property OSAScript : a reference to current application’s OSAScript property NSPredicate : a reference to current application’s NSPredicate property NSTextView : a reference to current application’s NSTextView property NSDictionary : a reference to current application’s NSDictionary property NSUnarchiver : a reference to current application’s NSUnarchiver property OSALanguage : a reference to current application’s OSALanguage property OSAScriptView : a reference to current application’s OSAScriptView property NSMutableArray : a reference to current application’s NSMutableArray property OSAScriptController : a reference to current application’s OSAScriptController property NSMutableDictionary : a reference to current application’s NSMutableDictionary property OSALanguageInstance : a reference to current application’s OSALanguageInstance property NSUTF8StringEncoding : a reference to current application’s NSUTF8StringEncoding
set postID to 3864 set {myUser, myPass} to getAcountData() of me set aURL to "http://piyocast.com/as/xmlrpc.php" set cocoaClassList to getCocoaPropListFromPost(aURL, postID, myUser, myPass) of me –>  {"NSString", "NSBundle", "NSPredicate", "NSDictionary", "NSMutableArray", "NSMutableDictionary"}
–指定Blogの指定IDの記事にURLリンクされているAppleScriptから、Cocoa Classのpropertyのみ取得する on getCocoaPropListFromPost(aURL, postID, myUser, myPass)   –AppleScriptの構文色分け設定ファイルを読み込んで、重複色のチェックを実施     set cList to getAppleScriptSourceColors() of me   set cRes to chkASLexicalFormatColorConfliction(cList) of me –構文色分けの重複色チェック   if cRes = false then error "There is some duplicate(s) color among AppleScript’s lexical color settings"      –WordPressの指定Post IDの記事を取得してリンクされているURLからURL Schemeでフィルタして、リンクされているAppleScriptのソースを取得   set aScheme to "applescript://"   set sourceList to getASSouceLinkedInWordPressPost(postID, aURL, aScheme, myUser, myPass) of me      –AppleScriptのソースをRAM上でコンパイル(構文確認)して、構文色分けしたRTFを取得。RTFの書式情報をparseしてattribute runsと同様のrecordを生成   –構文色分けをもとにproperty項目を抽出し、Cocoa Classに該当するもののみを抽出   set outList to {}   repeat with i in sourceList     set j to contents of i     set anAttrStr to compileASandReturnAttributedString(j) of me     set attrRes to getAttributeRunsFromAttrString(anAttrStr) of me     set propNames to getPropertyNamesCocoaOnly(cList, attrRes) of me          if propNames is not equal to {} then       set outList to outList & propNames     end if   end repeat      –1D Listのユニーク化(重複要素の排除)   set aArray to NSArray’s arrayWithArray:outList   set bArray to aArray’s valueForKeyPath:"@distinctUnionOfObjects.self"   set bList to bArray as list of string or string –as anything      return bList end getCocoaPropListFromPost
–Property名称を取得する on getPropertyNamesCocoaOnly(cList, aRec)   script spdHnd     property aRec : {}   end script      set (aRec of spdHnd) to aRec      set targAttr to contents of item 7 of cList –ハンドラあるいは変数   set tmpCoStr to ((redValue of targAttr) as string) & " " & ((greenValue of targAttr) as string) & " " & ((blueValue of targAttr) as string)      set ontoColItem to contents of item 3 of cList –スクリプティング予約語(on/to)   set ontoCoStr to ((redValue of ontoColItem) as string) & " " & ((greenValue of ontoColItem) as string) & " " & ((blueValue of ontoColItem) as string)         –変数あるいはハンドラ名称をリストアップ(variables & handler)   set tmp1Array to NSArray’s arrayWithArray:(aRec of spdHnd)   set thePred0 to NSPredicate’s predicateWithFormat_("colorStr == %@", tmpCoStr)   set dArray to (tmp1Array’s filteredArrayUsingPredicate:thePred0) as list      –改行を含むデータをリストアップ(text data contains return)   set thePred1 to NSPredicate’s predicateWithFormat_("stringVal CONTAINS %@", return)   set eArray to ((tmp1Array’s filteredArrayUsingPredicate:thePred1)’s valueForKeyPath:"itemIndex") as list      set the beginning of eArray to 0 –ハンドラ宣言部がTopに来る場合に備える      –"property"(プロパティ宣言)の項目をリストアップ 文字と色で抽出   set thePred2 to NSPredicate’s predicateWithFormat_("stringVal == %@ && colorStr == %@ ", "property", ontoCoStr)   set fArray to ((tmp1Array’s filteredArrayUsingPredicate:thePred2)’s valueForKeyPath:"itemIndex") as list      set handlerList to {}      –property ではじまるハンドラの抽出   repeat with i in eArray –改行を含むテキストのアイテム番号リスト     set j to (contents of i) as integer     repeat with ii in fArray –"on"の項目リスト       set jj to (contents of ii) as integer              set handlerStr to missing value              if (j + 1) = jj then         set handlerStr to stringVal of (item (jj + 2) of ((aRec of spdHnd) as list))       else if (j + 2) = jj then         set handlerStr to stringVal of (item (jj + 2) of ((aRec of spdHnd) as list))       end if              set tmpStr to repChar(handlerStr, "|", "") of me              if tmpStr is not in {"error", missing value} and tmpStr is not in handlerList then         –抽出したProperty宣言がCocoa Classのものかどうか判定         if searchClassInFrameworks(tmpStr) of me is not equal to false then           set the end of handlerList to tmpStr         end if       end if            end repeat   end repeat      return handlerList end getPropertyNamesCocoaOnly
–RAM上にスクリプトエディタと同じ部品を組み立て(非表示)、AppleScriptのソーステキストからObjectを生成し、Attributed Stringデータを返す on compileASandReturnAttributedString(theSource as string)   set targX to 1024 –View Width   set targY to 2048 –View Height      set osaCon to current application’s OSAScriptController’s alloc()’s init()   set osaView to current application’s OSAScriptView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, targX, targY))      set resView to NSTextView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, targX, targY))   resView’s setRichText:true   resView’s useAllLigatures:true      osaCon’s setScriptView:osaView   osaCon’s setLanguage:(OSALanguage’s languageForName:"AppleScript")   osaCon’s setResultView:resView      osaView’s setString:theSource   osaCon’s compileScript:(missing value) –Compile(構文確認)      set aRes to (osaView’s attributedString())      return aRes end compileASandReturnAttributedString
–Attributed StringをDictionary化 on getAttributeRunsFromAttrString(theStyledText)   script aSpd     property styleList : {}   end script      set (styleList of aSpd) to {} —for output      set thePureString to theStyledText’s |string|() –pure string from theStyledText      set theLength to theStyledText’s |length|()   set startIndex to 0   set itemCount to 1      repeat until (startIndex = theLength)     set {theAtts, theRange} to theStyledText’s attributesAtIndex:startIndex longestEffectiveRange:(reference) inRange:{startIndex, theLength – startIndex}          –String       set aText to (thePureString’s substringWithRange:theRange) as string          –Color     set aColor to (theAtts’s valueForKeyPath:"NSColor")     if aColor is not equal to missing value then       set aSpace to aColor’s colorSpace()              set aRed to (aColor’s redComponent()) * 255       set aGreen to (aColor’s greenComponent()) * 255       set aBlue to (aColor’s blueComponent()) * 255              set colList to {aRed as integer, aGreen as integer, aBlue as integer} –for comparison       set colStrForFind to (aRed as integer as string) & " " & (aGreen as integer as string) & " " & (aBlue as integer as string) –for filtering     else       set colList to {0, 0, 0}       set colStrForFind to "0 0 0"     end if          –Font     set aFont to (theAtts’s valueForKeyPath:"NSFont")     if aFont is not equal to missing value then       set aDFontName to aFont’s displayName()       set aDFontSize to aFont’s pointSize()     end if          set the end of (styleList of aSpd) to {stringVal:aText, colorStr:colStrForFind, colorVal:colList, fontName:aDFontName as string, fontSize:aDFontSize, itemIndex:itemCount}     set startIndex to current application’s NSMaxRange(theRange)          set itemCount to itemCount + 1   end repeat      return (styleList of aSpd)    end getAttributeRunsFromAttrString
–指定クラスがいずれかのCocoa Frameworkに所属しているかを検索 on searchClassInFrameworks(aTarget)   set aClass to current application’s NSClassFromString(aTarget)   if aClass = missing value then return false   set theComponenents to (NSBundle’s bundleForClass:aClass)’s bundleURL’s pathComponents()   set thePred to NSPredicate’s predicateWithFormat:"pathExtension == ’framework’"   set aRes to (theComponenents’s filteredArrayUsingPredicate:thePred)’s firstObject() as list of string or string   return aRes end searchClassInFrameworks
–指定Post IDのWordPress記事から、指定SchemeのURLを抽出し、AS Sourceをdecodeしてproperty行のみ抽出 on getASSouceLinkedInWordPressPost(postID, aURL, aScheme, myUser, myPass)   –call xmlrpc命令に対するURLの間接指定を有効にするために、AppleScriptの構文解釈機能をダミーURLでだます   using terms from application "http://piyocast.com/as/xmlrpc.php" –URLと判定されればなんでもいい     tell application aURL       set wRes to (call xmlrpc {method name:"wp.getPost", parameters:{"1", myUser, myPass, postID as string}})     end tell   end using terms from      set aBody to post_content of wRes –Blog本文      –記事中でリンクしているURLを取得し、指定のURL Schemeでフィルタする   set urlList to filterURLLinksByScheme(aBody, aScheme) of me      set propList to {}      repeat with i in urlList     set j to contents of i     set urlRec to parseQueryDictFromURLString(j) of me     set tmpScript to (urlRec’s |script|) as string –Get AppleScript Source          set propList to propList & tmpScript   end repeat      return propList end getASSouceLinkedInWordPressPost
on parseQueryDictFromURLString(aURLStr as string)   if aURLStr = "" then error "No URL String"      set aURL to |NSURL|’s URLWithString:aURLStr   set aQuery to aURL’s query() –Get Query string part from URL   if aQuery’s |length|() = 0 then return false      set aDict to NSMutableDictionary’s alloc()’s init()   set aParamList to (aQuery’s componentsSeparatedByString:"&") as list      repeat with i in aParamList     set j to contents of i     if length of j > 0 then       set tmpStr to (NSString’s stringWithString:j)       set eList to (tmpStr’s componentsSeparatedByString:"=")       set anElement to (eList’s firstObject()’s stringByReplacingPercentEscapesUsingEncoding:(NSUTF8StringEncoding))       set aValStr to (eList’s lastObject()’s stringByReplacingPercentEscapesUsingEncoding:(NSUTF8StringEncoding))       (aDict’s setObject:aValStr forKey:anElement)     end if   end repeat      return aDict end parseQueryDictFromURLString
–指定のHTML文字列から、Link URLを抽出し、schemeで再抽出する on filterURLLinksByScheme(aBody, aScheme)   set conType to "text/html"      –HTML文字列をいったんNSDataにしているのは、HTMLReader.frameworkの仕様のため   set aData to (current application’s NSString’s stringWithString:aBody)’s dataUsingEncoding:(current application’s NSUTF8StringEncoding)   set aHTML to current application’s HTMLDocument’s documentWithData:aData contentTypeHeader:conType      set aTextArray to ((aHTML’s nodesMatchingSelector:"a")’s textContent) as list –リンク文字   set aLinkList to ((aHTML’s nodesMatchingSelector:"a")’s attributes’s valueForKeyPath:"href") as list –URL文字列      set outList to {}   repeat with i in aLinkList     set j to contents of i     if j begins with aScheme then       set the end of outList to j     end if   end repeat      return outList end filterURLLinksByScheme
–文字置換 on repChar(origText as string, targChar as string, repChar as string)   set curDelim to AppleScript’s text item delimiters   set AppleScript’s text item delimiters to targChar   set tmpList to text items of origText   set AppleScript’s text item delimiters to repChar   set retText to tmpList as string   set AppleScript’s text item delimiters to curDelim   return retText end repChar
–AppleScriptの構文色分けのカラー値をRGBで取得する on getAppleScriptSourceColors()   — get the plist info as a dictionary   set thePath to NSString’s stringWithString:"~/Library/Preferences/com.apple.applescript.plist"   set thePath to thePath’s stringByExpandingTildeInPath()   set theInfo to NSDictionary’s dictionaryWithContentsOfFile:thePath      — extract relevant part and loop through   set theArray to (theInfo’s valueForKey:"AppleScriptSourceAttributes") as list      set colList to {}      repeat with i from 1 to count of theArray     set anEntry to item i of theArray          set colorData to NSColor of anEntry     set theColor to (NSUnarchiver’s unarchiveObjectWithData:colorData)          set {rVal, gVal, bVal} to retColListFromNSColor(theColor, 255) of me          set fontData to NSFont of anEntry     set theFont to (NSUnarchiver’s unarchiveObjectWithData:fontData)          set aFontName to theFont’s displayName() as text     set aFontSize to theFont’s pointSize()          set aColRec to {redValue:rVal, greenValue:gVal, blueValue:bVal, fontName:aFontName, fontSize:aFontSize}          set the end of colList to aColRec   end repeat      return colList end getAppleScriptSourceColors
–NSColorからRGBの値を取り出す on retColListFromNSColor(aCol, aMAX as integer)   set aRed to round ((aCol’s redComponent()) * aMAX) rounding as taught in school   set aGreen to round ((aCol’s greenComponent()) * aMAX) rounding as taught in school   set aBlue to round ((aCol’s blueComponent()) * aMAX) rounding as taught in school      if aRed > aMAX then set aRed to aMAX   if aGreen > aMAX then set aGreen to aMAX   if aBlue > aMAX then set aBlue to aMAX      return {aRed, aGreen, aBlue} end retColListFromNSColor
–AS書式で配色に重複がないかどうかチェック on chkASLexicalFormatColorConfliction(aList)   set anArray to current application’s NSArray’s arrayWithArray:aList   set bList to (anArray’s valueForKeyPath:"redValue.stringValue") as list   set cList to (anArray’s valueForKeyPath:"greenValue.stringValue") as list   set dList to (anArray’s valueForKeyPath:"blueValue.stringValue") as list      set colStrList to {}   repeat with i from 1 to (length of bList)     set bItem to contents of item i of bList     set cItem to contents of item i of cList     set dItem to contents of item i of dList     set the end of colStrList to bItem & " " & cItem & " " & dItem   end repeat      set aRes to returnDuplicatesOnly(colStrList) of me   if aRes is equal to {} then     return true –重複が存在しなかった場合   else     return false –重複があった場合   end if end chkASLexicalFormatColorConfliction
on returnDuplicatesOnly(aList as list)   set aSet to current application’s NSCountedSet’s alloc()’s initWithArray:aList   set bList to (aSet’s allObjects()) as list      set dupList to {}   repeat with i in bList     set aRes to (aSet’s countForObject:i)     if aRes > 1 then       set the end of dupList to (contents of i)     end if   end repeat      return dupList end returnDuplicatesOnly
on getAcountData()   return {"xxxxxxxx_xx", "XXXXXXXXXXXXXXXXXXXXXXXX"} –user name, password  end getAcountData
  |