10
\$\begingroup\$

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 :)

asked Sep 13, 2016 at 15:47
\$\endgroup\$
1
  • 1
    \$\begingroup\$ document.querySelectorAll("a.doc-topic-link")[0] ==> document.querySelector("a.doc-topic-link") \$\endgroup\$ Commented Sep 13, 2016 at 15:54

2 Answers 2

4
\$\begingroup\$
  1. No need for timeout, just attach in a place that doesn't get overwritten: after the title.
  2. 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.
  3. Instead of magic split indexes I suggest using a simple \d regexp to extract all digits.
  4. 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>
 `);
}
answered Sep 13, 2016 at 20:00
\$\endgroup\$
3
  • \$\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\$ Commented 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\$ Commented 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\$ Commented Oct 3, 2016 at 12:00
7
\$\begingroup\$

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.

answered Sep 13, 2016 at 15:56
\$\endgroup\$
2
  • \$\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\$ Commented 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\$ Commented Sep 13, 2016 at 19:00

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.