(function () {
// ==UserScript==
// @name uso - Anchor Bookmarks
// @namespace http://userscripts.org/users/37004
// @description Converts anchor tags with no attributes into bookmarks via the next available text node line
// @copyright 2010+, Marti Martz (http://userscripts.org/users/37004)
// @contributor sizzlemctwizzle (http://userscripts.org/users/27715)
// @license CC-BY-NC-SA-4.0; https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
// @license GPL-3.0-or-later; http://www.gnu.org/licenses/gpl-3.0.txt
// @version 0.5.10.1eol
// @icon https://www.gravatar.com/avatar/e615596ec6d7191ab628a1f0cec0006d?r=PG&s=48&default=identicon
// @homepageURL https://github.com/Martii/UserScripts/tree/master/src/uso/Anchor%20Bookmarks
// @homepageURL https://openuserjs.org/scripts/Marti/uso_-_Anchor_Bookmarks
// @homepageURL http://userscripts.org/scripts/show/69725
// @supportURL http://userscripts.org/topics/46795
// @include /^https?://userscripts\.org(?::\d{1,5})?//
// @exclude /^https?://userscripts\.org(?::\d{1,5})?/login/
// @exclude /^https?://userscripts\.org(?::\d{1,5})?/scripts/diff//
// @exclude /^https?://userscripts\.org(?::\d{1,5})?/scripts/version//
// @include http://userscripts.org:8080/*
// @include http://userscripts.org/*
// @include https://userscripts.org/*
// @exclude http://userscripts.org:8080/login*
// @exclude http://userscripts.org:8080/scripts/diff/*
// @exclude http://userscripts.org:8080/scripts/version/*
// @exclude http://userscripts.org/login*
// @exclude http://userscripts.org/scripts/diff/*
// @exclude http://userscripts.org/scripts/version/*
// @exclude https://userscripts.org/login*
// @exclude https://userscripts.org/scripts/diff/*
// @exclude https://userscripts.org/scripts/version/*
// ==/UserScript==
var img = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAl2cEFnAAAAEAAAABAAXMatwwAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAAN1wAADdcBQiibeAAAAlNJREFUOE+Nk+tLU3EYx+3+v6RRb3tXEAhBBDWjzK03Um+VirI0IWr3c+ZYURJJsTHnSJshdH3TtNoNZLY1zV3Y3TkvZ3rm1G1++/1+mey0ih74nHHg+X7OzvP8TgOABo1OeVLPa1Jq7X38Ca1etaXj1OsGo95J7o/TzC/YhYSz8/kc/lWRaBhfA34YTbzIGbScRECfQms6HMT0bODnL2GmhuGRISws5SEIyyD/ZI1kmusEs9EQYZoRjlFmdhgZtSOVTkAoLMPrc0Fv0LjrBNH47DZhxBK1RPDFM8Ek9mEbPF4XnctmnSCejCKeisE7FURrlxlNMg5NLRwUty2Y/BbCVGASLs9nlNZLIENFnSCVicMXCOHIOR06jQ/w/LUSL5zjuDtgwOHzPPyh78jMpVjv9oZ2SQTZXBoXuizo7b8C24dOqGx+2MZteOs7DeWzq1B0W5HLZ1kvWf0Wye2WCOYX5nDwDIfHL6+j4+FHdDxyY8x7GcMTcpjfyNEo47FINlEj2CMR0DVRQZ99FPygHO36MZgcN/Dq01H0O0xMIBSWWC89XHWCZWERrTctkJHXeOI4hjtPu3FJ/R7WdydwsXcAip5BrIorrJcMsUpyeyWCwoqAYDiJxrN6dPDXoDY7oba40X5PhUMtPCLJHNZKxVrBPomA2sXiKkLRDNpuWYmIZ8h7hhBL57G5ucGgRY5/heT2SwQ0XFwT2VPorjc21lmgXC6jUqmgWq0yaJHvgQoOMAG5yQgFAf9bYlGkgvzOOSATbeb7dIm/fc6/Q3rTZAanaPYH/jkU5snfMgQAAAAASUVORK5CYII=";
var headNode = document.evaluate(
"//head",
document.documentElement,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
);
if (headNode && headNode.singleNodeValue) {
var styleNode = document.createElement("style");
styleNode.setAttribute("type", "text/css");
styleNode.setAttribute("media", "screen, projection");
styleNode.textContent = ".bookmark { width: 16px; height: 16px; margin: 0.1em 0.2em 0; float: left; background: transparent url(" + img + ") no-repeat top left; opacity: 0.4; } .bookmark:hover { opacity: 1.0; }";
headNode.singleNodeValue.appendChild(styleNode);
}
var xpr = document.evaluate(
"//a[starts-with(@name,'comment-')]",
document.body,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null
);
if (xpr)
for (var i = 0, thisNode; thisNode = xpr.snapshotItem(i++);) {
var imgNode = document.createElement("img");
imgNode.setAttribute("class", "bookmark");
imgNode.setAttribute("src", "data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==");
imgNode.setAttribute("title", "link");
thisNode.appendChild(imgNode);
if (window.location.pathname.match(/^\/comments(.*)/i)) {
var userid, useridNode = document.evaluate(
".//a[@user_id]",
thisNode.parentNode,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
);
if (useridNode && useridNode.singleNodeValue) {
var thatNode = useridNode.singleNodeValue;
userid = thatNode.getAttribute("user_id");
if (userid)
thisNode.setAttribute("href", "/users/" + userid + "/comments#" + thisNode.name); // NOTE: Comments are not fully linked to source page so use public profile comments
}
if (!userid)
thisNode.setAttribute("href", window.location.pathname + window.location.search + "#" + thisNode.name); // NOTE: Fallback to actual fragment in case of USO gen err
}
else
thisNode.setAttribute("href", window.location.pathname + "#" + thisNode.name); // NOTE: Fallback for no pagination
}
// Fix missing recent /posts linkage if still missing
if (window.location.pathname.match(/(.*)\/posts\/?$/i)) {
var xpr = document.evaluate(
"//tr[starts-with(@id,'posts-')]",
document.body,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null
);
if (xpr)
for (var i = 0, thisNode; thisNode = xpr.snapshotItem(i++);) {
var targetNode = document.evaluate(
".//abbr[@class='updated']",
thisNode,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
);
if (targetNode && targetNode.singleNodeValue) {
var abbrNode = targetNode.singleNodeValue;
if (abbrNode.parentNode.getAttribute("rel") != "bookmark") {
var aNode = document.createElement("a");
aNode.setAttribute("rel", "bookmark");
aNode.setAttribute("href", "/" + thisNode.getAttribute("id").replace("-", "/"));
abbrNode.parentNode.appendChild(aNode);
aNode.appendChild(abbrNode);
}
}
}
}
// Add custom bookmarks if present
var pathname, portion;
switch ((pathname = window.location.pathname)) {
case undefined:
default:
break;
case (portion = pathname.match(/^\/scripts(.*)/i)) ? portion[0] : undefined:
var tabid = (portion = portion[1].match(/^\/(show|reviews|issues)\/(.*)/i)) ? portion[1] : undefined;
switch (tabid) {
case "show":
var contextNode = document.evaluate(
"//div[@id='full_description']",
document.body,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
);
if (contextNode && contextNode.singleNodeValue) {
contextNode = contextNode.singleNodeValue;
addBookmarks(contextNode, "bookmark-");
}
break;
case "reviews":
var contextNode = document.evaluate(
"//div[@class='review']/div[@class='body']",
document.body,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null
);
for (var i = 0; i < contextNode.snapshotLength; ++i) {
var thisNode = contextNode.snapshotItem(i);
var reviewid = thisNode.previousSibling.previousSibling.previousSibling.previousSibling.getAttribute("id").match(/reviews-(\d+)-status/i)[1];
addBookmarks(thisNode, "bookmark-" + reviewid + "-");
}
break;
case "issues":
var contextNode = document.evaluate(
"//p[contains(@id, 'issuecomments-')]",
document.body,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null
);
for (var i = 0; i < contextNode.snapshotLength; ++i) {
var thisNode = contextNode.snapshotItem(i);
var commentid = thisNode.getAttribute("id").match(/issuecomments-(\d+)/i)[1];
addBookmarks(thisNode.nextSibling, "bookmark-" + commentid + "-");
}
break;
}
break;
case (portion = pathname.match(/^\/jetpacks(.*)/i)) ? portion[0] : undefined:
var jetpackid = (portion = portion[1].match(/^\/(.*)/i)) ? portion[1] : undefined;
if (jetpackid) {
var contextNode = document.evaluate(
"//p/b/text()['Summary:']",
document.body,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
);
if (contextNode && contextNode.singleNodeValue) {
contextNode = contextNode.singleNodeValue.parentNode.parentNode;
addBookmarks(contextNode, "bookmark-");
}
}
break;
case (portion = pathname.match(/^\/articles(.*)/i)) ? portion[0] : undefined:
var articleid = (portion = portion[1].match(/^\/(\d+).*/i)) ? portion[1] : undefined;
if (articleid) {
var contextNode = document.evaluate(
"//div[contains(@id, 'comment-body')]",
document.body,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null
);
for (var i = 0; i < contextNode.snapshotLength; ++i) {
var thisNode = contextNode.snapshotItem(i);
var commentid = thisNode.getAttribute("id").match(/comment-body-(\d+)/i)[1];
addBookmarks(thisNode, "bookmark-" + commentid + "-");
}
contextNode = document.evaluate(
"//p[@class='summary']",
document.body,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
);
if (contextNode && contextNode.singleNodeValue) {
contextNode = contextNode.singleNodeValue;
addBookmarks(contextNode, "bookmark-");
}
}
break;
case (portion = pathname.match(/(.*)\/comments\/?$/i)) ? portion[0] : undefined:
var contextNode = document.evaluate(
"//div[contains(@id, 'comment-body')]",
document.body,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null
);
for (var i = 0; i < contextNode.snapshotLength; ++i) {
var thisNode = contextNode.snapshotItem(i);
var commentid = thisNode.getAttribute("id").match(/comment-body-(\d+)/i)[1];
addBookmarks(thisNode, "bookmark-" + commentid + "-");
}
contextNode = document.evaluate(
"//p[@class='summary']",
document,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
);
if (contextNode && contextNode.singleNodeValue) {
contextNode = contextNode.singleNodeValue;
addBookmarks(contextNode, "bookmark-");
}
break;
case (portion = pathname.match(/^\/groups(.*)/i)) ? portion[0] : undefined:
var groupid = (portion = portion[1].match(/^\/(\d+)\/?$/i)) ? portion[1] : undefined;
if (groupid) {
var contextNode = document.evaluate(
"//div[@class='description']",
document.body,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
);
if (contextNode && contextNode.singleNodeValue) {
contextNode = contextNode.singleNodeValue;
addBookmarks(contextNode, "bookmark-");
}
}
break;
case (portion = pathname.match(/^\/guides(.*)/i)) ? portion[0] : undefined:
var guideid = (portion = portion[1].match(/^\/(\d+)\/?$/i)) ? portion[1] : undefined;
if (guideid) {
var contextNode = document.evaluate(
"//div[@id='content']",
document.body,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
);
if (contextNode && contextNode.singleNodeValue) {
contextNode = contextNode.singleNodeValue;
addBookmarks(contextNode, "bookmark-");
}
}
break;
case (portion = pathname.match(/^\/topics(.*)/i)) ? portion[0] : undefined:
var topicid = (portion = portion[1].match(/^\/(\d+)\/?$/i)) ? portion[1] : undefined;
if (topicid) {
var contextNode = document.evaluate(
"//td[contains(@id, 'post-body')]",
document.body,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null
);
for (var i = 0; i < contextNode.snapshotLength; ++i) {
var thisNode = contextNode.snapshotItem(i);
var postid = thisNode.getAttribute("id").match(/post-body-(\d+)/i)[1];
addBookmarks(thisNode, "bookmark-" + postid + "-");
}
}
break;
case (portion = pathname.match(/^\/reviews(.*)/i)) ? portion[0] : undefined:
var reviewid = (portion = portion[1].match(/^\/(\d+)\/?$/i)) ? portion[1] : undefined;
if (reviewid) {
var contextNode = document.evaluate(
"//div[@class='body']",
document.body,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
);
if (contextNode && contextNode.singleNodeValue) {
contextNode = contextNode.singleNodeValue;
addBookmarks(contextNode, "bookmark-");
}
contextNode = document.evaluate(
"//div[contains(@id, 'comment-body')]",
document.body,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null
);
for (var i = 0; i < contextNode.snapshotLength; ++i) {
var thisNode = contextNode.snapshotItem(i);
var commentid = thisNode.getAttribute("id").match(/comment-body-(\d+)/i)[1];
addBookmarks(thisNode, "bookmark-" + commentid + "-");
}
}
break;
}
function addBookmarks(contextNode, prefixAttribute) {
var xpr = document.evaluate(
"../descendant::a[not(@href)][not(@name)][not(@id)]",
contextNode,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null
);
var thisNode, thatNode;
if (xpr) {
var bookmarks = {};
function checkBookmark(bookmarks, newbookmark, suffix) {
for (var bookmark in bookmarks) {
if (newbookmark + ((suffix) ? "-" + suffix : "") == bookmarks[bookmark]) {
suffix = (suffix) ? suffix + 1 : 1;
checkBookmark(bookmarks, newbookmark, suffix);
}
}
return suffix;
}
for (var i = 0; i < xpr.snapshotLength; ++i) {
var thatNode = thisNode = xpr.snapshotItem(i);
while (thatNode) {
if (thatNode.textContent != "") {
var newbookmark = thatNode.textContent;
if (!newbookmark.match(/^about:.*/i)) {
newbookmark = newbookmark.replace(/^\s*/, "");
if (newbookmark.match(/(.{1,64})/i)) {
newbookmark = newbookmark.match(/(.{1,64})/i)[1];
newbookmark = newbookmark.replace(/\s*$/, "");
newbookmark = newbookmark.replace(/\s{2,}/g, " ");
newbookmark = newbookmark.replace(/\.*/g, "");
newbookmark = encodeURIComponent(newbookmark.toLowerCase());
newbookmark = newbookmark.replace(/\%20/g, "-");
newbookmark = newbookmark.replace(/\%/g, ".");
newbookmark = prefixAttribute + newbookmark;
var suffix;
if ((suffix = checkBookmark(bookmarks, newbookmark)))
newbookmark += "-" + suffix;
bookmarks[newbookmark] = newbookmark;
}
thisNode.setAttribute("name", newbookmark);
thisNode.setAttribute("id", newbookmark);
var imgNode = document.createElement("img");
imgNode.setAttribute("class", "bookmark");
imgNode.setAttribute("title", "link");
imgNode.setAttribute("alt", "link");
imgNode.setAttribute("src", "data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==");
var anchorNode = document.createElement("a");
anchorNode.setAttribute("href", "#" + newbookmark);
anchorNode.appendChild(imgNode);
thisNode.parentNode.insertBefore(anchorNode, thisNode);
}
break;
}
thatNode = thatNode.nextSibling;
}
}
}
}
var hash = window.location.hash.match(/^#(bookmark-.*)/);
if (hash) {
var anchorNode = document.evaluate(
"//a[@id='" + hash[1] + "']",
document.body,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
);
if (anchorNode && anchorNode.singleNodeValue)
setTimeout(function () { anchorNode.singleNodeValue.scrollIntoView(); }, 1000);
}
})();
Donate for the site OpenUserJS
Are you sure you want to go to an external site to donate a monetary value?
WARNING: Some countries laws may supersede the payment processors policy such as the GDPR and PayPal. While it is highly appreciated to donate, please check with your countries privacy and identity laws regarding privacy of information first. Use at your utmost discretion.