アンビリーバボ?アンビリバボー?
http://rashita.net/blog/?p=16722
こちらの2つ目、「拡張型ノートリンク」と書かれた機能をAppleScriptで実装しました。
使い方(基礎編)
Evernoteのノート上で引用したい箇所を選択状態に。
スクリプトメニューからcitation
を実行すると
「Copied」と通知。
好きなところでペーストすれば、それっぽい見た目のノートリンク。
使い方(応用編)
スクリプトオブジェクトを使って他のアプリケーションにも拡張できます。
例えばSafariの場合。ページ上で引用部分を選択してcitation
を実行。
Evernoteにペーストで引用文を含んだリンクに。画像は反映されません。
今のところEvernoteとSafariの2種類のみです。ソースコードをいじって他のアプリケーションを追加してみてください。
リンクの色を変えるなり、アイコンを付けるなりしないと見分けがつきませんが、それはまた別の機会に。
(2015-12-18 追記) 使い方(発展編)
HTMLを理解できる方にオススメ。
ソースコード冒頭にあるproperty citationTemplate : ...
の部分で、貼り付けるリンクの見た目を決めています。
このテンプレート、見ればわかるようにHTMLで記述されているのです。
- 元のままでは無駄な情報が多い
- 文字やリンクの大きさや色、順番が気にくわない
- 引用は
blockquote
じゃないと気持ち悪い
なんて方はHTMLをいじって自分好みの見た目に変更しましょう。
その際に注意すべきこととして 特殊文字の取り扱い があります。
property citationTemplate : ...
の部分ではHTML全体を文字列としてcitationTemplate
という変数に入れるため、ダブルクオーテーション(")で囲っています。
HTML内でダブルクオーテーション(")を使うと、そこが文字列の終わりと判断されて「残りの文字列はなんだ?」ってエラーが出てしまいます。
そこで、エスケープのためにバックスラッシュ(\)を前に置いて、\"
と記述してください。こうすればエラーは出ないはず。
他にもつまずくことがあるかもしれませんが、Googleに頼りながら試してみてください。
動作環境
- Mac OS X: 10.11
- Evernote: ver 6.3 (452832 Direct)
ソースコード
(*
* [[Clipping]]: 引用内容 - getClipping()
* [[Link]]: リンクURL - getLink()
* [[Title]]: リンクタイトル - getTitle()
* [[Author]]: 作者 - getAuthor()
* [[Publisher]]: 出版社、発行元 - getPublisher()
* [[Date]]: 日付 - getDate()
*)
property citationTemplate : "<br>
<div class='citation' style='padding: 0px 30px;'>
<div class='clipping' style='line-height:18px; padding: 8px 15px; border-left:2px solid #dedede; color: #919191; font-family: Helvetica, sans-serif; font-style: italic; font-size: 14px;'>[[Clipping]]</div>
<div style='padding-left: 17px;'>
<div class='title' style='color: #000000; font-family: Helvetica, sans-serif; font-size: 14px; margin-top: 19px;'>
<a style='text-decoration: none; color: rgba(45,190,96,1.0);' href='[[Link]]'>
"[[Title]]"
</a>
</div>
<div style='color: #919191; font-size: 12px; margin-top: 4px; font-family: 'CaeciliaLTStd', serif; font-style: italic;'>
<span class='author'>[[Author]]</span>
<span class='publisher'>[[Publisher]].</span>
<span class='date'>[[Date]]</span>
</div>
</div>
</div>
<br>"
on run
--アプリケーション判別
if application "Evernote" is running and application "Evernote" is frontmost then
set curApp to make Evernote
else if application "Safari" is running and application "Safari" is frontmost then
set curApp to make Safari
else
--set curApp to make some_application
error
end if
--citationのHTML作成
copy citationTemplate to citation
repeat with replacement in {¬
{"[[Clipping]]", getClipping() of curApp}, ¬
{"[[Link]]", getLink() of curApp}, ¬
{"[[Title]]", getTitle() of curApp}, ¬
{"[[Author]]", getAuthor() of curApp}, ¬
{"[[Publisher]]", getPublisher() of curApp}, ¬
{"[[Date]]", getDate() of curApp} ¬
}
set {f, r} to replacement
set r to my escapeHTMLSpecialChars(r)
set r to my replace(r, {return, linefeed}, "<br>")
set citation to my replace(citation, f, r)
end repeat
--HTMLをコピー
my copyHTML(citation)
display notification getTitle() of curApp with title "Copied"
end run
script some_application
on getClipping()
repeat until application id (my appID) is frontmost
activate application id (my appID)
end repeat
set the clipboard to ""
set tmpClipboard to the clipboard as record
tell application "System Events"
keystroke "c" using {command down}
set timestamp to current date
repeat while (the clipboard as record) = tmpClipboard
if (current date) > timestamp + 10 then
error
end if
delay 1
end repeat
end tell
return the clipboard as text
end getClipping
on getLink()
return ""
end getLink
on getTitle()
return ""
end getTitle
on getAuthor()
return ""
end getAuthor
on getPublisher()
return ""
end getPublisher
on getDate()
return ""
end getDate
on make
set a_class to me
script Instance
property parent : a_class
property appID : run script "tell application \"System Events\" to return bundle identifier of process 1 whose frontmost = true and visible = true"
end script
end make
end script
script Evernote
property parent : some_application
--on getClipping()
-- continue getClipping()
--end getClipping
on getLink()
tell application "Evernote"
return note link of (note id (my noteID)) of notebook 1
end tell
end getLink
on getTitle()
tell application "Evernote"
return title of (note id (my noteID)) of notebook 1
end tell
end getTitle
on getAuthor()
tell application "Evernote"
set noteAuthor to author of (note id (my noteID)) of notebook 1
end tell
if noteAuthor = missing value then
set noteAuthor to ""
end if
return noteAuthor
end getAuthor
on getPublisher()
tell application "Evernote"
return name of notebook of (note id (my noteID)) of notebook 1
end tell
end getPublisher
on getDate()
tell application "Evernote"
tell creation date of (note id (my noteID)) of notebook 1 as date
return "" & year & "年" & (month of it as number) & "月" & day & "日"
end tell
end tell
end getDate
on make
set self to continue make
script EvernoteInstance
property parent : self
property noteID : run script "tell application \"Evernote\" to return local id of item 1 of (selection as list)"
end script
end make
end script
script Safari
property parent : some_application
on getClipping()
tell application "Safari"
set clipping to do JavaScript "document.getSelection().toString();" in current tab of window id (my windowID)
end tell
if clipping = "" then
try
set clipping to my extractText(my metas, linefeed & "og:description,", linefeed)
on error number -2700
end try
end if
return clipping
end getClipping
on getLink()
try
return my extractText(my metas, linefeed & "og:url,", linefeed)
on error number -2700
end try
tell application "Safari"
return URL of current tab of window id (my windowID)
end tell
end getLink
on getTitle()
try
return my extractText(my metas, linefeed & "og:title,", linefeed)
on error number -2700
end try
tell application "Safari"
return name of current tab of window id (my windowID)
end tell
end getTitle
on getAuthor()
try
return my extractText(my metas, linefeed & "twitter:creator,", linefeed)
on error number -2700
end try
return ""
end getAuthor
on getPublisher()
try
return my extractText(my metas, linefeed & "og:site_name,", linefeed)
on error number -2700
end try
return ""
end getPublisher
on getDate()
try
set ISODate to my extractText(my metas, linefeed & "article:published_time,", linefeed)
tell my ISODateToDate(ISODate)
return "" & year & "年" & (month of it as number) & "月" & day & "日"
end tell
on error number -2700
end try
return ""
end getDate
on make
set self to continue make
script SafariInstance
property parent : self
property windowID : run script "tell application \"Safari\" to return id of window 1 whose current tab ≠ missing value"
property metas : run script "tell application \"Safari\" to return do JavaScript \"var ary=[]; var elements=document.getElementsByTagName('meta'); for(i=0; i<elements.length; i++) {content=elements[i].getAttribute('content'); if(elements[i].getAttribute('property')) {ary.push(elements[i].getAttribute('property') + ',' + elements[i].getAttribute('content'));} else if(elements[i].getAttribute('name')) {ary.push(elements[i].getAttribute('name') + ',' + elements[i].getAttribute('content'));}} '\\\\n' + ary.join('\\\\n') + '\\\\n';\" in current tab of window id " & windowID
end script
end make
end script
on escapeHTMLSpecialChars(args)
if class of args = list then
repeat with i from 1 to count args
set item i of args to my escapeHTMLSpecialChars(item i of args)
end repeat
else
set args to my replace(args, "&", "&")
set args to my replace(args, "<", "<")
set args to my replace(args, ">", ">")
set args to my replace(args, quote, """)
set args to my replace(args, "'", "'")
end if
return args
end escapeHTMLSpecialChars
on replace(str as text, find, replace as text)
set oldDel to AppleScript's text item delimiters
set AppleScript's text item delimiters to find
set replaceList to text items of str
set AppleScript's text item delimiters to replace
set str to replaceList as string
set AppleScript's text item delimiters to oldDel
return str
end replace
on copyHTML(HTML as text)
set the clipboard to {«class utf8»:HTML, string:HTML, Unicode text:HTML, «class HTML»:my htmlToRawData(HTML)}
end copyHTML
on extractText(theText, beginText, endText)
--beginText, endText例: {text:"a", forwardSearch:false, containText:true}
set beginText to (beginText as record) & {forwardSearch:true, containText:false}
set endText to (endText as record) & {forwardSearch:true, containText:false}
if theText does not contain text of beginText or theText does not contain text of endText then error "引数の文字列が含まれません"
set scraps to my split(theText, text of beginText)
if forwardSearch of beginText then
set theText to my join(rest of scraps, text of beginText)
else
set {theText} to reverse of scraps
end if
set scraps to my split(theText, text of endText)
if forwardSearch of endText then
set {theText} to scraps
else
set theText to my join(reverse of rest of reverse of scraps, text of endText)
end if
if containText of beginText then
set theText to "" & text of beginText & theText
end if
if containText of endText then
set theText to "" & theText & text of endText
end if
return theText
end extractText
on ISODateToDate(ISODate)
if class of ISODate = «class isot» then
set aDate to ISODate as date
else
set aDate to (do shell script "echo " & quoted form of ISODate as «class isot») as date
if ISODate ends with "Z" then
set aDate to my shiftDateFromGMT(aDate)
end if
end if
return aDate
end ISODateToDate
on htmlToRawData(HTML as text)
return run script "«data HTML" & (do shell script "echo " & quoted form of HTML & " | hexdump -v -e '/1 \"%02X\"'") & "»"
end htmlToRawData
on split(str as text, delim)
set oldDel to AppleScript's text item delimiters
set AppleScript's text item delimiters to delim
set aList to text items of str
set AppleScript's text item delimiters to oldDel
return aList
end split
on join(textList, term as text)
set oldDel to AppleScript's text item delimiters
set AppleScript's text item delimiters to term
set aText to textList as string
set AppleScript's text item delimiters to oldDel
return aText
end join
on shiftDateFromGMT(aDate)
global timeToGMT
try
timeToGMT
on error number -2753
set timeToGMT to time to GMT
end try
return aDate + timeToGMT
end shiftDateFromGMT
普段AppleScriptを使わない方へ
メニューバーにスクリプトメニューを表示する方法
このスクリプトはスクリプトメニューから実行することを想定しています。スクリプトエディタから実行してもエラーになってしまうので、次に示す設定をお願いします。
- スクリプトエディタ.app (/Applications/Utilities/Script Editor.app) 起動
- メニューバー
- 「スクリプトエディタ」
- 「環境設定…」
- 「一般」
- 「スクリプトメニュー」
- 「メニューバーにスクリプトメニューを表示」 にチェック
メニューバーにスクリプトメニューのアイコンが表示されればOK。
GUIスクリプティングを有効に
スクリプト中に「GUIスクリプティング」と呼ばれる機能を使っています。スクリプトメニューから実行する前に以下の設定が必要です。
- システム環境設定.app (/Applications/System Preferences.app) 起動
- 「セキュリティとプライバシー」
- 「プライバシー」
- 鍵マーク 「変更するにはカギをクリックします。」をクリック
- パスワード入力
- 「ロックを解除」
- 「アクセシビリティ」
- 「+」
- /System/Library/CoreServices/SystemUIServer.app を選択
- 「開く」
(2015-12-18 追記) スクリプトファイルの保存方法
スクリプトファイルの保存場所を書いていませんでした。スクリプトメニューからAppleScriptを実行するには特定の場所にファイルがなければいけません。
下の方法でスクリプトファイルを保存してください。
- スクリプトエディタ.app (/Applications/Utilities/Script Editor.app) 起動
- ファイル選択ダイアログが表示された場合は「新規書類」
- このページ中部の「ソースコード」にある「citation.scpt」全体をスクリプトエディタ.appにコピペ
- ⌘+Kでコンパイル
- ⌘+Sで保存
- 名前を「citation.scpt」に
- 保存場所を「/Users/(ユーザ名)/Library/Scripts」に
- ファイルフォーマットは「スクリプト」のままで
- 「保存」
保存が完了しました。スクリプトエディタ.appを終了してください。
スクリプトの実行方法は冒頭の「使い方(基礎編)・(応用編)」に書いたとおり。きちんと動くか確認してみてください。
更新履歴
- 2015-12-16: Evernoteのノート上で引用型ノートリンクをコピーする機能実装
- 2015-12-17: Safariで引用型リンクをコピーする機能追加