This is a short script to help me with web-clipping sort of activities while composing email and notes. I use it mainly with Mail, Notes and sometimes TextEdit to insert page title, link and selection from web pages. Grabbing the selection and pasting is not as perfect as copying it directly from Safari, but still useful.
This is one of my first scripts - please let me know of any glaring errors and also of any improvements.
Thanks.
-- Crude 'web-clipping' script to grab URL, page title and selected text from Safari
-- and insert the info in HTML
-- Written mainly to be used with Mail, Notes and TextEdit (via FastScripts)
-- What it will try to do:
-- Grab info from all the windows and tabs in Safari
-- Present a list selection with multiple selection showing the page titles
-- Paste the information from the selected tabs into the current application (clipboard will be modified)
-- If a single item is selected it is pasted as HTML paragraph
-- Multiple selections are pasted as items of unordered list enclosed in a DIV element
-- Only inline css-styles seem to work with the above mentioned application (other methods didn't work)
-- Code contains snippets gleaned from other postings
-- version 0.1: 2013-Sep-27 Friday: 04:51:33 pm
-- version 0.2: 2013-Nov-14 Thursday: 07:37:42 am
-- Corrected occasional error "Safari got an error: Can't get every tab of window id ..." when extension dialog had been open
set {leftArrow, rightArrow, downArrow, upArrow} to {123, 124, 125, 126}
set jsCode1 to "
function getSelectionHtml() {
var html = \"\";
if (typeof window.getSelection != \"undefined\") {
var sel = window.getSelection();
if (sel.rangeCount) {
var container = document.createElement(\"div\");
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
container.appendChild(sel.getRangeAt(i).cloneContents());
}
html = container.innerHTML;
}
} else if (typeof document.selection != \"undefined\") {
if (document.selection.type == \"Text\") {
html = document.selection.createRange().htmlText;
}
}
return html;
}
function htmlEncode( html ) {
var myString = document.createElement( 'a' ).appendChild(
document.createTextNode( html ) ).parentNode.innerHTML;
return myString.replace(/\"/g, '\\"').replace(/\\n/g, '\\
').replace(/( )/g,\" \");
};
[document.title, htmlEncode(document.title), window.location.href, getSelectionHtml()];
"
set tabsInfo to {}
set listInfo to {}
set listIndex to 0
set theSelection to {}
set AppleScript's text item delimiters to return
tell application "System Events"
set foreMostApplication to item 1 of (get name of processes whose frontmost is true)
end tell
tell application "Safari"
set windowsList to (windows whose visible is true) as list
repeat with currWindow in windowsList
set tabsList to tabs of currWindow as list
repeat with currTab in tabsList
set {unencodedPageTitle, pageTitle, currURL, selectedText} to (do JavaScript jsCode1 in currTab)
set infoText to {unencodedPageTitle, pageTitle, currURL, selectedText} as text
copy infoText to end of tabsInfo
set listIndex to listIndex + 1
copy {unencodedPageTitle, listIndex} as text to the end of listInfo
end repeat -- tabsList
end repeat -- windowsList
end tell -- Safari
if length of tabsInfo is equal to 1 then
set theSelection to tabsInfo
else
try
set listOfSelected to (choose from list listInfo ¬
with title ¬
"Grab page information (as HTML)" with prompt ¬
"Select page(s) to grab:" with multiple selections allowed)
on error number -128 # Cancelled
return
end try
set theSelection to {}
repeat with eachItem in listOfSelected
set {unencodedPageTitle, listIndex} to paragraphs of eachItem
copy item listIndex of tabsInfo to the end of theSelection
end repeat
end if
outputHTML(theSelection)
-- Assumes invocation from an application capable of accept pasting
delay 0.25
tell application foreMostApplication
activate
delay 0.25
tell application "System Events"
keystroke return
delay 0.25
key code upArrow
delay 0.25
keystroke "v" using command down
delay 0.25
key code downArrow
end tell
end tell
to outputHTML(selectedItems)
set HTMLout to ""
set pageInfo to ""
repeat with theSelection in selectedItems
set {unencodedPageTitle, pageTitle, pageURL, selectedText} to text items of theSelection
set pageInfo to "<em style=\"display:block;\"><a href=\"" & pageURL & "\">" & pageTitle & "</a></em>" & return
if selectedText is not equal to "" then
set pageInfo to pageInfo & "<div style=\"padding:8px; border-left: 1px solid #999; margin-bottom: 1em; \">" & selectedText & "</div>" & return
end if
if (count of selectedItems) > 1 then
set HTMLout to HTMLout & "<li><p>" & pageInfo & "</p></li>" & return
else
set HTMLout to HTMLout & "<p>" & pageInfo & "</p>" & return
end if
end repeat
-- Wrap around in a box with unordered list items
set divStyle to "padding: .5em; margin-bottom: .5em; font-size: 1.2em; font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif;"
if (count of selectedItems) > 1 then
set HTMLout to "<ul>" & return & HTMLout & return & "</ul>" & return
set divStyle to divStyle & " border-style: dotted; border-width: thin; border-color: black;"
end if
set HTMLout to "<div style=\"" & divStyle & "\">" & return & HTMLout & return & "</div>"
set HTMLout to HTMLout -- & return & "<p></p>" -- this helps to place the cursor outside the inserted element
set HTMLout to ¬
"<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Clipped items</title>
</head>
<body>
" & HTMLout & "
</body>
</html>"
-- set the clipboard to HTMLout
set htmlData to do shell script "echo " & (quoted form of HTMLout) & " | hexdump -ve '1/1 \"%.2x\"'"
run script "set the clipboard to «data HTML" & htmlData & "»"
end outputHTML