So Stackoverflow Documentation has added "Contributor Breakdown". For any given topic (and example) people can display who contributed in which way.
That page is only available if you know the link though. And it's not linked publicly in any way. Since I like these hidden pages, but I keep forgetting the correct URLs to use, I wrote a short userscript to insert these links where relevant:
// ==UserScript==
// @name Documentation contributor links
// @namespace http://github.com/Vogel612/mini-se-userscripts/documentation-contributor-breakdown
// @version 0.1
// @description Add links to the contributor breakdown for topics and examples on stackoverflow documentation.
// @author Vogel612
// @include /https?:\/\/stackoverflow\.com\/documentation\/.*
// @grant none
// @run-at document-end
// ==/UserScript==
(function() {
// these are in here for debugging purposes
document.addLinks = addLinks;
document.addContributorLink = addContributorLink;
})();
// because the page is modified on SE side after loading. 2 secs should be enough to wait
setTimeout(addLinks, 2000);
function addLinks() {
'use strict';
let topicLink = document.querySelectorAll("a.doc-topic-link")[0];
let topicMenuContainer = document.querySelector("div.docs-menu.topic-menu");
addContributorLink("topic", topicLink.href.split('/')[5], topicMenuContainer);
let exampleLinks = document.querySelectorAll(".example-link a.doc-example-link");
let exampleMenus = document.querySelectorAll(".example-link div.example-menu.docs-menu");
for (var i = 0; i < exampleLinks.length; i++) {
let currentLink = exampleLinks[i];
let currentMenuContainer = exampleMenus[i];
addContributorLink("example", currentLink.href.split('/')[7], currentMenuContainer);
}
}
function addContributorLink(section, linkId, menu) {
'use strict';
let href = `/documentation/contributors/${section}/${linkId}`;
let elem = document.createElement("A");
elem.href = href;
elem.innerHTML = "CB";
elem.title = "Contributor Breakdown";
menu.insertBefore(elem, menu.children[0]);
}
Note that the documentation pages are modified by StackOverflow after loading and that removes the link, if I add it before the page is completely built. That's why I run addLinks()
with a 2 second delay.
Any and all aspects are up for critique, as always :)
2 Answers 2
- No need for timeout, just attach in a place that doesn't get overwritten: after the title.
- Since the extracted link id number is always the last, we can process all links in one go, extracting section name from a link's class name via
doc-(\w+)-link
to make the pattern self-evident. - Instead of magic split indexes I suggest using a simple
\d
regexp to extract all digits. - Building DOM elements by individual properties is unreadable, it's a thing from '00s, I suggest using the equally fast (or faster) and much more readable
insertAdjacentHTML
.
The entire code boils down to:
for (let link of document.querySelectorAll("a.doc-topic-link, a.doc-example-link")) {
let section = link.className.match(/doc-(\w+)-link/).pop();
let lastNumber = new URL(link.href).pathname.match(/(\d+)/g).pop();
link.insertAdjacentHTML('afterend', `
<a href="/documentation/contributors/${section}/${lastNumber}"
title="Contributor Breakdown">CB</a>
`);
}
-
\$\begingroup\$ re your third point ... thinking about it a little more it's unfortunately not quite as simple as you make it to be, because the link to examples still contains the id of the containing topic. Accordingly what you recommend doesn't work quite as easily there :) Adding it after the title is a somewhat interesting idea, but I think it's semantically incorrect to do so, so I won't do it ... \$\endgroup\$Vogel612– Vogel6122016年10月03日 11:27:23 +00:00Commented Oct 3, 2016 at 11:27
-
\$\begingroup\$ #3 is okay because it gets the last number, although I can make it more reliable:
let lastNumber = new URL(link.href).pathname.match(/\/(\d+)\//g).pop().slice(1, -1);
As for #1, it's now invalid since the updated docs site overrides the click event, but semantic considerations are much less important when hacking something. \$\endgroup\$woxxom– woxxom2016年10月03日 11:41:52 +00:00Commented Oct 3, 2016 at 11:41 -
\$\begingroup\$ For example, #1 can be implemented by inserting the link into a topic/example container: p.ip.fi/Tu8L \$\endgroup\$woxxom– woxxom2016年10月03日 12:00:07 +00:00Commented Oct 3, 2016 at 12:00
You're using 'use strict';
in all functions except the top one. Why not declare it at the top of your file?
You seem to have thought about readability. You're declaring variables for just that purpose here:
let currentLink = exampleLinks[i];
let currentMenuContainer = exampleMenus[i];
So why oh why do I see magic numbers in your code?
setTimeout(addLinks, 2000);
let topicLink = document.querySelectorAll("a.doc-topic-link")[0];
topicLink.href.split('/')[5]
currentLink.href.split('/')[7]
menu.insertBefore(elem, menu.children[0]);
Of those 5, arguably the first and latter are acceptable. The 3rd and 4th are the most magical of the lot. You explained the first in a comment, but I'd personally move it to a variable.
-
\$\begingroup\$ Because if you put it at the top of the file outside a function you get
use the function form of "use strict";
which is annoying with linters \$\endgroup\$cat– cat2016年09月13日 18:07:53 +00:00Commented Sep 13, 2016 at 18:07 -
1\$\begingroup\$ there's also a technical reason. unless you wrap the userscript in an IIFE, putting 'use strict' at the top of the file will cause all following scripts to execute in strict mode - and some of them may not have been designed to! Granted in 2016 this shouldn't be an issue, but you never know. Vogel should still wrap his code in an IIFE and use the 'use strict' prologue there, which is what the linter warning refers to \$\endgroup\$Dan– Dan2016年09月13日 19:00:13 +00:00Commented Sep 13, 2016 at 19:00
Explore related questions
See similar questions with these tags.
document.querySelectorAll("a.doc-topic-link")[0]
==>document.querySelector("a.doc-topic-link")
\$\endgroup\$