Created
December 5, 2013 08:37
-
-
Save sorrycc/7802016 to your computer and use it in GitHub Desktop.
Pinboard Add.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Pinboard Add Script. | |
// @namespace http://use.i.E.your.homepage/ | |
// @version 0.1 | |
// @description enter something useful | |
// @match http://*/* | |
// @match https://*/* | |
// @copyright 2012+, You | |
// ==/UserScript== | |
// Pinboard. | |
document.addEventListener("keydown", function(e) { | |
if (e.keyCode === 65 && e.metaKey && e.shiftKey && e.ctrlKey && e.altKey) { | |
(function() { | |
/******************* begin configuration options ***************************/ | |
// Change `read` to true to invoke the promptless, self-closing | |
// version of the bookmarklet. | |
var readlater = false; | |
var appUrl = null; | |
// when set to true selected text is quoted using markdown quote syntax | |
var quoteSelectionAsMarkdown = true; | |
// when this text appears in title or description they are added as tags | |
var tagKeywords = { | |
javascript:'javascript', | |
js:'javascript', | |
python:'python', | |
ios:'ios', | |
youtube:'video', | |
vimeo:'video', | |
video:'video', | |
books:'book', | |
book:'book' | |
}; | |
// this matches domain names to special selectors for the title | |
var titleTweaks = { | |
"github.com":".entry-title .js-current-repository" | |
}; | |
// this matches domain names to special selectors for the title | |
var descriptionTweaks = { | |
"www.kickstarter.com":".short-blurb" | |
}; | |
/********************* begin code ********************************************/ | |
// reduce a string to some canonical representation | |
// right now this just picks a case but could get really complicated if need be | |
// see: http://stackoverflow.com/questions/227950/programatic-accent-reduction-in-javascript-aka-text-normalization-or-unaccentin | |
// some people like stack overflow straighten their curly quotes | |
var normalize = function(string) { | |
return string.toLowerCase(); | |
} | |
var elementText = function(el) { | |
return el ? el.textContent.trim().replace(/\s+/g,' ') : null; | |
} | |
var normalizedDocumentTitle = normalize(document.title); | |
// used as tes | |
var isSubtitle = function(string) { | |
if(string) { | |
return normalizedDocumentTitle.indexOf(normalize(string)) != -1; | |
} | |
else { | |
return false; | |
} | |
}; | |
// loops over a node list and applies a function | |
// returning the first value that is non-null | |
var selectFromNodeList = function(nodeList,func,thisObj) { | |
thisObj = thisObj || window; | |
var l = nodeList.length; | |
var result; | |
for(var i=0;i<l;++i) { | |
result = func.call(thisObj,nodeList.item(i)); | |
if(result !== null) { | |
return result; | |
} | |
} | |
return null; | |
}; | |
var getTitle = function() { | |
var url = location.href; | |
var host = location.hostname; | |
var e; | |
if(host in titleTweaks) { | |
e = document.querySelector(titleTweaks[host]); | |
if(e) { | |
return elementText(e); | |
} | |
} | |
var documentTitle = document.title; | |
var e = document.querySelector("meta[property='og:title']"); | |
if(e) { | |
documentTitle = e.content.trim().replace(/\s+/g,' '); | |
} | |
var i,a; | |
// hEntry microformat | |
if(selectFromNodeList(document.getElementsByClassName('hentry'), function(x) {return true;})) { | |
var htitle = document.querySelector( | |
'.hentry .entry-title' | |
); | |
if(htitle) { | |
return elementText(htitle) | |
} | |
} | |
// method 1 - look for link to self with text that is contained in title | |
var a_text = selectFromNodeList(document.getElementsByTagName('A'), function(a) { | |
if(a.href == url) { | |
a_text = elementText(a); | |
if(isSubtitle(a_text)) { | |
return a_text; | |
} | |
} | |
return null; | |
}); | |
if(a_text) { | |
return a_text; | |
} | |
// method 2 - look at header tags and see if it matches part of title | |
var headerTags = ['h1','h2','h3','h4','h5','h6']; | |
var h; | |
var headerTitle; | |
for(var j=0;j<headerTags.length;++j) { | |
selectFromNodeList(document.getElementsByTagName(headerTags[j]), function(h) { | |
h_text = elementText(h) | |
if(isSubtitle(h_text) && (!headerTitle || h_text.length > headerTitle.length)) { | |
headerTitle = h_text; | |
} | |
return null; | |
}); | |
} | |
if(headerTitle) { | |
return headerTitle; | |
} | |
// method 3 - just return the title | |
return documentTitle; | |
}; | |
var getTags = function(text) { | |
text = normalize(text); | |
var tags = []; | |
var re; | |
for(keyword in tagKeywords) { | |
re = keyword instanceof RegExp ? keyword : new RegExp("\\b"+keyword+"\\b","i"); | |
if(re.test(text)) { | |
tags.push(tagKeywords[keyword]); | |
} | |
} | |
return tags; | |
}; | |
var getMetaDescription = function() { | |
var e; | |
e = document.querySelector("meta[name='description']"); | |
if(e) { | |
return e.content.trim().replace(/\s+/g,' '); | |
} | |
e = document.querySelector("meta[property='og:description']"); | |
if(e) { | |
return e.content.trim().replace(/\s+/g,' '); | |
} | |
return ""; | |
}; | |
var getDescription = function() { | |
var text; | |
// Grab the text selection (if any) and quote it | |
if('' !== (text = String(document.getSelection()))) { | |
if(quoteSelectionAsMarkdown) { | |
text = text.trim().split("\n").map(function(s) {return "> "+s;}).join("\n"); | |
} | |
} | |
var host = location.hostname; | |
var e; | |
if(host in descriptionTweaks) { | |
e = document.querySelector(descriptionTweaks[host]); | |
if(e) { | |
return elementText(e); | |
} | |
} | |
if(!text) { | |
text = getMetaDescription(); | |
} | |
return text; | |
}; | |
// Assembles default form pre-fill arguments. | |
var url = location.href; | |
var title = getTitle(); | |
var description = getDescription(); | |
// remove if title is trailing or leading | |
var ix = description.indexOf(title); | |
if(ix == 0) { | |
description = description.substring(title.length).trim(); | |
} | |
else if(ix == description.length-title.length) { | |
description = description.substring(0,ix).trim(); | |
} | |
var args = [ | |
'url=', encodeURIComponent(location.href), | |
'&title=', encodeURIComponent(title), | |
'&description=', encodeURIComponent(description), | |
// this could based on a general function "getText()" | |
'&tags=', encodeURIComponent(getTags(document.title+" "+description+" "+getMetaDescription()).join(" ")) | |
]; | |
// If readlater mode, add the auto-close parameter and read-later flag: | |
if(readlater) { | |
args = args.concat([ | |
'&later=', 'yes', | |
'&jump=', 'close' | |
]); | |
} | |
if(appUrl) { | |
args = args.concat([ | |
'&x-source=Safari', | |
'&x-success=',encodeURIComponent(location.href), | |
'&x-cancel=',encodeURIComponent(location.href) | |
]); | |
window.location = appUrl+args.join(''); | |
} | |
else { | |
var pin = unsafeWindow.open('http://pinboard.in/add?'+args.join(''), 'Pinboard', 'toolbar=no,width=610,height=350'); | |
// Send the window to the background if readlater mode. | |
if(readlater) { | |
pin.blur(); | |
} | |
} | |
})(); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment