Skip to content

Instantly share code, notes, and snippets.

@fractaledmind
Last active August 31, 2018 05:57
Show Gist options
  • Save fractaledmind/7065110 to your computer and use it in GitHub Desktop.
Save fractaledmind/7065110 to your computer and use it in GitHub Desktop.
REQUIRED PROGRAMS: - Skim (pdf viewer and annotator) - Evernote (cloud based note app) - works with PDFPen for iPad and iPhone This script will (as the title suggests) export all of you Skim notes directly to Evernote with hyperlinks.
(* EXPORT ALL SKIM NOTES TO EVERNOTE WITH IOS HYPERLINKS
-- Stephen Margheim
-- 10/16/13
-- open source
REQUIRED PROGRAMS:
- Skim (pdf viewer and annotator)
- Evernote (cloud based note app)
- works with PDFPen for iPad and iPhone
This script will (as the title suggests) export all of you Skim notes directly to Evernote with hyperlinks.
When launched, the script will ask you a series of questions:
* where you want the current PDF to be moved to finally reside,
* what the relation of the Printed page number is relative to Skim's indexed page number,
* if the PDF is a Primary Source or a Secondary Source.
Your choices will determine (1) the file path used in the URL Handler, (2) the key to generating the hyperlinked printed page numbers, (3) the text values for the 6 different highlight colors.
NOTE: YOU MUST SAVE YOUR PDFS TO THE SAME FOLDER AS THE FOLDER THAT THE URL HANDLER SEARCHES
*)
(* PROPERTIES *)
property LF : (ASCII character 10)
property LF1 : (ASCII character 32) & (ASCII character 32) & (ASCII character 10)
property tid : AppleScript's text item delimiters
property theHome : path to home folder as string
(* THE SCRIPT *)
tell application "Skim"
(* ///
PRE-PROCESSING:
Check if annotated on iOS. If yes, convert annotations
/// *)
if every note of document 1 = {} then convert notes document 1
(* ///
PART 1:
Dialog Boxes
/// *)
--move PDF file to its proper place
set theFile to name of document 1 as string
set theFolder to choose folder default location (theHome & "Dropbox:" as alias) with prompt "Whither save the PDF?"
set theFolder to theFolder as string
--get relation of printed page number to Skim's indexed page number
set pageRelation to text returned of (display dialog ¬
"Subtract printed page number from Skim's indexed page number" with title "Relation of Printed page # to indexed page #" default answer "") as number
--determine type of PDF
set theTextStatus to display dialog "Is the PDF a Primary or Secondary text?" buttons {"Primary", "Secondary"} default button {"Secondary"}
(* ///
PART 2:
Generate Top 3 Notes with relevant Meta-Data
/// *)
--URL encode pdf's title
set pdfTitle to name of document 1
set PdfName to my encode_text(pdfTitle, true, false)
--create Custom URL with partial file path
set customurl to "pdfpen:///" & pdfTitle & "?pg="
--create the three opening notes
tell page 1 of document 1
make note with properties {type:anchored note, bounds:{579, 842, 595, 826}, text:customurl, extended text:pdfTitle}
delay 0.1
make note with properties {type:anchored note, bounds:{579, 826, 595, 810}, text:"[" & pdfTitle & "](" & customurl}
delay 0.1
make note with properties {type:anchored note, bounds:{579, 810, 595, 794}, text:pageRelation, extended text:"pr# - sk#"}
end tell
(* ///
PART 3:
Get all Annotation Information
/// *)
--get info for all notes
set allNotes to every note of document 1
set allNotes_types to every type of notes of document 1
set allNotes_text to text of every note of document 1
set allNotes_pages to index of every page of every note of document 1
--get info for all notes except top 3
set selNotes to items 1 through -4 of allNotes
set selNotes_types to items 1 through -4 of allNotes_types
set selNotes_text to items 1 through -4 of allNotes_text
set selNotes_pages to items 1 through -4 of allNotes_pages
--get info from top 3 notes
set PDFLink to customurl
set Markdownlink to (get text of note -2 of page 1 of document 1) as string
set number_of_Note3 to (get text of note -1 of page 1 of document 1) as string
--prepare Headers for all of the various note types
set notesText_text to "<hr />" & LF & LF & "<h2>The ToC</h2>" & LF1 & LF & LF
set notesText_anchor to "<hr />" & LF & LF & "<h2>All of my Text Notes</h2>" & LF1 & LF & LF
set notesText_highlight to "<hr />" & LF & LF & "<h2>All of the Highlighted Text </h2>" & LF1 & LF & LF
set notesText_underline to "<hr />" & LF & LF & "<h2>All of the Underlined Text</h2>" & LF1 & LF & LF
set notesText_strikethru to "<hr />" & LF & LF & "<h2>All of the Strike-Through Text</h2>" & LF1 & LF & LF
(* ///
PART 4:
The Meat-n-Potatoes of the Script
/// *)
repeat with i from 1 to count of selNotes_types
--prepare Skim page # and actual page #
set notePage to item i of selNotes_pages
set theRealPage to notePage + number_of_Note3 as string
--collect Text Notes
if item i of selNotes_types is text note then
set noteText to item i of selNotes_text
set notesText_text to notesText_text & "<p>" & noteText & " (<a href=\"" & PDFLink & notePage & "\">" & "p." & theRealPage & "</a>)" & LF & LF
--collect Anchor Notes
else if item i of selNotes_types is anchored note then
set titleText to item i of selNotes_text
set noteText to extended text of item i of selNotes
--precaution for running script multiple times
repeat 1 times
if titleText contains "customurl://" or noteText contains "pr# - sk#" then exit repeat
set notesText_anchor to notesText_anchor & "<p><strong>" & titleText & ":</strong> " & noteText & " (<a href=\"" & PDFLink & notePage & "\">p." & theRealPage & "</a>)" & LF & LF
end repeat
--collect Underline Notes
else if item i of selNotes_types is underline note then
set noteText to item i of selNotes_text
set notesText_underline to notesText_underline & "<p>\"" & noteText & "\"" & " (<a href=\"" & PDFLink & notePage & "\">" & "p." & theRealPage & "</a>)" & LF & LF
--collect Strike-Thru Notes
else if item i of selNotes_types is strike out note then
set noteText to item i of selNotes_text
set notesText_strikethru to notesText_strikethru & "<p>\"" & noteText & "\"" & " (<a href=\"" & PDFLink & notePage & "\">" & "p." & theRealPage & "</a>)" & LF & LF
--collect Highlight Notes
else if item i of selNotes_types is highlight note then
set theColor to color of item i of selNotes
set titleText to my color2text(theColor, theTextStatus)
set noteText to item i of selNotes_text
set notesText_highlight to notesText_highlight & "<p><strong>" & titleText & ":</strong> " & LF1 & "\"" & noteText & "\"" & " (<a href=\"" & PDFLink & notePage & "\">p." & theRealPage & "</a>)" & LF & LF
end if
end repeat
(* ///
PART 5:
Extract Summary Annotations
/// *)
--extract "Summary" notes from the collection of all highlight notes
set theSummary to {}
set theParas to paragraphs of notesText_highlight
repeat with i from 1 to count of theParas
if item i of theParas contains "<p><strong>Summary:" then
set theTitle to item i of theParas
set theText to item (i + 1) of theParas
set theSumm to theTitle & LF & theText & LF & LF
copy theSumm to the end of theSummary
end if
end repeat
--remove "Summary" highlight notes from collection of highlight notes
if (not (theSummary is {})) then
set SumText to theSummary as string
set SumList to paragraphs of SumText
set empty to {""}
set FinalSum to my cleanmyList(SumList, empty)
set HighList to paragraphs of notesText_highlight
set finalHighlights to my cleanmyList(HighList, FinalSum)
set AppleScript's text item delimiters to LF
set notesText_highlight to (finalHighlights as string)
set theSummary to "<hr />" & LF & LF & "<h2>Text Summary</h2>" & LF1 & LF & LF & SumText
end if
--ALWAYS RETURN TEXT ITEM DELIMITERS TO NORMAL
set AppleScript's text item delimiters to tid
(* ///
PART 6:
Remove any Empty Annotation Sections
/// *)
--remove any note sections that are empty
set FinalList to my textCheck(notesText_text, notesText_anchor, notesText_highlight, notesText_underline, notesText_strikethru, theSummary)
--prepare the final collection of notes, with MetaData
set FinalText to FinalList
(* ///
PART 7:
Create the Evernote Note
/// *)
tell application "Evernote"
--create new "PDF Notes" notebook if necessary
if (not (notebook named "PDF Notes" exists)) then
make notebook with properties {name:"PDF Notes"}
end if
--create the HTML note
set theTitle to "Notes: " & pdfTitle
set newNote to create note title theTitle with html FinalText notebook "PDF Notes"
set noteTags_list to {"notes", "pdfpen"}
repeat with i from 1 to count of noteTags_list
set x to item i of noteTags_list
if (not (tag named x exists)) then
set tag1 to make tag with properties {name:x}
else
set tag1 to tag x
end if
assign tag1 to newNote
end repeat
--synchronize Evernote
repeat until isSynchronizing is false
synchronize
end repeat
repeat until isSynchronizing is false
end repeat
end tell
(* ///
PART 8:
Display Growl Notifications
/// *)
--save as flattened pdf to be viewed by iOS app
save front document as "PDF With Embedded Notes" in (theFolder & theFile)
--is Growl installed?
set Growl_ to my Growl_Check()
--notify on Success or Failure
if Growl_ is true then
tell application "Growl"
set allNotificationsFiles to {"Success Notification", "Failure Notification"}
set enabledNotificationsFiles to {"Success Notification", "Failure Notification"}
register as application ¬
"Skim Annotations to Evernote" all notifications allNotificationsFiles ¬
default notifications enabledNotificationsFiles ¬
icon of application "URL Handler"
end tell
--on Success
tell application "Growl"
if newNote exists then
notify with name ¬
"Success Notification" title ¬
"Import Success!" description "Successfully Exported All Skim Annotations to Evernote" application name "Skim Annotations to Evernote" icon of application "Custom URL Handler"
else
notify with name ¬
"Failure Notification" title ¬
"Import Failed" description "The script failed to export all Skim notes to Evernote" application name "Skim Annotations to Evernote" icon of application "Custom URL Handler"
end if
end tell
end if
end tell
(* HANDLERS *)
--URL encode text
on encode_text(this_text, encode_URL_A, encode_URL_B)
set the standard_characters to "abcdefghijklmnopqrstuvwxyz0123456789"
set the URL_A_chars to "$+!'/?;&@=#%><{}[]\"~`^\\|*"
set the URL_B_chars to ".-_:"
set the acceptable_characters to the standard_characters
if encode_URL_A is false then set the acceptable_characters to the acceptable_characters & the URL_A_chars
if encode_URL_B is false then set the acceptable_characters to the acceptable_characters & the URL_B_chars
set the encoded_text to ""
repeat with this_char in this_text
if this_char is in the acceptable_characters then
set the encoded_text to (the encoded_text & this_char)
else
set the encoded_text to (the encoded_text & encode_char(this_char)) as string
end if
end repeat
return the encoded_text
end encode_text
on encode_char(this_char)
set the ASCII_num to (the ASCII number this_char)
set the hex_list to {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"}
set x to item ((ASCII_num div 16) + 1) of the hex_list
set y to item ((ASCII_num mod 16) + 1) of the hex_list
return ("%" & x & y) as string
end encode_char
on replaceString(theText, oldString, newString)
-- ljr (http://applescript.bratis-lover.net/library/string/)
local ASTID, theText, oldString, newString, lst
set ASTID to AppleScript's text item delimiters
try
considering case
set AppleScript's text item delimiters to oldString
set lst to every text item of theText
set AppleScript's text item delimiters to newString
set theText to lst as string
end considering
set AppleScript's text item delimiters to ASTID
return theText
on error eMsg number eNum
set AppleScript's text item delimiters to ASTID
error "Can't replaceString: " & eMsg number eNum
end try
end replaceString
--convert highlights into text values
on color2text(noteColor, theTextStatus)
set colorText to {}
if theTextStatus is {button returned:"Secondary"} then
if noteColor is {64634, 900, 1905, 65535} then
set end of colorText to "Disagree"
else if noteColor is {64907, 32785, 2154, 65535} then
set end of colorText to "Agree"
else if noteColor is {65535, 65531, 2689, 65535} then
set end of colorText to "Summary"
else if noteColor is {8608, 65514, 1753, 65535} then
set end of colorText to "Reference"
else if noteColor is {8372, 65519, 65472, 65535} then
set end of colorText to "Quotable"
else if noteColor is {64587, 1044, 65481, 65535} then
set end of colorText to "Technique"
end if
else if theTextStatus is {button returned:"Primary"} then
if noteColor is {64634, 900, 1905, 65535} then
set end of colorText to "Key Quote"
else if noteColor is {64907, 32785, 2154, 65535} then
set end of colorText to "Key Theme"
else if noteColor is {65535, 65531, 2689, 65535} then
set end of colorText to "Summary Passage"
else if noteColor is {8608, 65514, 1753, 65535} then
set end of colorText to "Key Motif"
else if noteColor is {8372, 65519, 65472, 65535} then
set end of colorText to "Confusing Passage"
else if noteColor is {64587, 1044, 65481, 65535} then
set end of colorText to "\"Purple\" Passage"
end if
end if
return colorText
end color2text
--remove any empty note sections
on textCheck(notesText_text, notesText_anchor, notesText_highlight, notesText_underline, notesText_strikethru, theSummary)
if notesText_text is "<hr />
<h2>The ToC</h2>
" then
set notesText_text to ""
else
set notesText_text to notesText_text & LF & LF
end if
if notesText_anchor is "<hr />
<h2>All of my Text Notes</h2>
" then
set notesText_anchor to ""
else
set notesText_anchor to notesText_anchor & LF & LF
end if
if notesText_highlight is "<hr />
<h2>All of the Highlighted Text </h2>
" then
set notesText_highlight to ""
else
set notesText_highlight to notesText_highlight & LF & LF
end if
if notesText_underline is "<hr />
<h2>All of the Underlined Text</h2>
" then
set notesText_underline to ""
else
set notesText_underline to notesText_underline & LF & LF
end if
if notesText_strikethru is "<hr />
<h2>All of the Strike-Through Text</h2>
" then
set notesText_strikethru to ""
else
set notesText_strikethru to notesText_strikethru & LF & LF
end if
if theSummary is {} then
set theSummary to ""
else
set theSummary to theSummary & LF & LF
end if
return notesText_text & theSummary & notesText_anchor & notesText_highlight & notesText_underline & notesText_strikethru
end textCheck
--remove items from a list
on cleanmyList(theList, itemsToDelete)
set cleanList to {}
repeat with i from 1 to count theList
if {theList's item i} is not in itemsToDelete then set cleanList's end to theList's item i
end repeat
return cleanList
end cleanmyList
--Check For Growl
on Growl_Check()
if appIsRunning("Growl") then
set growl_Running to true
tell application "Growl"
set allNotificationsFiles to {"Import To Evernote", "Success Notification", "Failure Notification"}
set enabledNotificationsFiles to {"Import To Evernote", "Success Notification", "Failure Notification"}
register as application ¬
"Skim Annotations to Evernote" all notifications allNotificationsFiles ¬
default notifications enabledNotificationsFiles ¬
icon of application "Custom URL Handler"
end tell
return growl_Running
else
error
end if
end Growl_Check
--App Detect
on appIsRunning(appName)
tell application "System Events" to (name of processes) contains appName
end appIsRunning
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment