The Code
This user script runs on http://msdn.microsoft.com. The biggest question for overlaying the feature on top of MSDN is, "How structured is the content? How easy is it to identify sections showing a specific language?" Even though the markup isn't as clean as I had hoped, it is barely regular enough that I was able to filter code examples by language.
When I looked at the source of some MSDN reference pages, the markup for code snippets read something like this:
<grouping>
<span class="lang">C#</span> …many nodes…
<span class="lang">JScript</span> …many nodes…
</grouping>
The grouping tag varies from page to page. Sometimes it's a <div>, but I also found <pre> elements on some pages. Although this markup is good enough for styling the page, it doesn't lend itself to easy filtering. Each language section doesn't have its own container, which makes it difficult to identify all the DOM nodes for the code sample.
The script starts by finding all the span elements that have a class="lang" attribute. It then scans the content of each <span> to identify known language names. The ShowCS, ShowVB, ShowCPP, and ShowJScript variables let you customize which languages to show or hide. If the code sample is an identifiable language and the corresponding Show variable is true, we keep it; otherwise, we remove it.
Finally, the CleanSpan function handles filtering out a language section, for a given starting <span>, by also providing the next known language <span> (if any). It removes all the sibling nodes that follow the starting <span>, until it reaches the <span> for the following language section or until there is no next sibling node (i.e., until we reach the end of the grouping). This is the best we can do, given the paucity of structured markup.
Save the following user script as MSDNLanguageFilter.user.js:
// ==UserScript==
// @name MSDN Language Filter
// @namespace http://blog.monstuff.com/archives/cat_greasemonkey.html
// @description Allows you to filter the samples on MSDN for certain
languages
// @include http://msdn.microsoft.com/*
// ==/UserScript==
// based on code by Julien Couvreur
// and included here with his gracious permission
var ShowCPP = false;
var ShowVB = false;
var ShowJScript = false;
var ShowCS = true;
var MSDNLanguageFilter = {
FilterLanguages: function()
{
var xpath = "//span[@class = 'lang']";
var res = document.evaluate(xpath, document, null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0; i < res.snapshotLength; i++)
{
var spanHTML = res.snapshotItem(i).innerHTML;
var isVB = (spanHTML.match(/Visual.*Basic/i) != null);
var isCS = (spanHTML.match(/C#/i) != null);
var isCPP = (spanHTML.match(/C\+\+/i) != null);
var isJScript = (spanHTML.match(/JScript/i) != null);
if (!isVB && !isCS && !isCPP && !isJScript)
{
return;
}
var keepLang =
(isCPP && ShowCPP) ||
(isCS && ShowCS) ||
(isVB && ShowVB) ||
(isJScript && ShowJScript) ||
(!isCPP && !isCS && !isVB && !isJScript);
if (!keepLang)
{
this.CleanSpan(res.snapshotItem(i), res.snapshotItem(i+1));
}
}
},
CleanSpan: function(startSpan, endSpan)
{
var currentNode = startSpan;
while (currentNode != null &&
(endSpan == null || currentNode != endSpan))
{
var nextNode = currentNode.nextSibling;
currentNode.parentNode.removeChild(currentNode);
currentNode = nextNode;
}
}
}
MSDNLanguageFilter.FilterLanguages();