Skip to content

Instantly share code, notes, and snippets.

@robjwells
Last active December 19, 2015 10:29
Show Gist options
  • Save robjwells/5940383 to your computer and use it in GitHub Desktop.
Save robjwells/5940383 to your computer and use it in GitHub Desktop.
robjwells.com syntax highlighting

This is essentially Dr Drang’s script for syntax highlighting and adding line numbers to code snippets, which calls highlight.js to do the colouring.

My code is largely the same, but rewritten to not require JQuery and done so in the module pattern to keep functions out of the global namespace. (On my site this is my personal JavaScript file, so I’d also stick any other functions I write myself inside the module.)

/*jslint browser: true, maxlen: 79 */
/*globals hljs, window*/
var RJW = (function (document, window, hljs) {
'use strict';
var getKids,
addNumbers,
formatCode;
getKids = function (parentTag, childTag) {
var parents = document.getElementsByTagName(parentTag),
children = [];
childTag = childTag.toUpperCase();
[].slice.call(parents).forEach(function (parent) {
if (parent.firstChild.tagName === childTag) {
children.push(parent.firstChild);
}
});
return children;
};
addNumbers = function (lineArray, firstLine) {
var currentLine = firstLine,
endLine = firstLine + lineArray.length - 1,
lineWidth = endLine.toString().length,
numberedLines = [],
padOut = function (string, targetWidth) {
while (string.length < targetWidth) {
string = ' ' + string;
}
return string;
};
lineArray.forEach(function (line) {
numberedLines.push('<span class="line-number">' +
padOut(currentLine.toString(), lineWidth) +
' {2}</span>' + line);
currentLine += 1;
});
return numberedLines;
};
formatCode = function () {
var codeBlocks = getKids('pre', 'code'),
languages = Object.keys(hljs.LANGUAGES),
// This will need changing when I upgrade to the new hljs API
langRegex = new RegExp('^(' + languages.join('|') + '):\\n');
codeBlocks.forEach(function (el) {
var oldContent = el.innerHTML,
newContent,
lang = oldContent.match(langRegex),
line;
// Language line found, so strip it and set class
if (lang) {
lang = lang[1];
el.setAttribute('class', 'language-' + lang);
oldContent = oldContent.split('\n').slice(1).join('\n');
}
// Detect line numbers
line = oldContent.match(/^\ *(\d+):\ {2}/);
if (line) {
// Get numbering start point
line = parseInt(line[1], 10);
// Remove line numbers
oldContent = oldContent.replace(/^\ *\d+:\ {2}/mg, '');
}
// Strip empty lines
oldContent = oldContent.replace(/\n+$/, '');
// Returned cleaned-up code to element
el.innerHTML = oldContent;
// Highlight code if language was given
if (lang) {
hljs.highlightBlock(el);
}
// Add line numbers to highlighted code, add plain link
if (line) {
newContent = el.innerHTML.split('\n');
newContent = addNumbers(newContent, line);
newContent.push('\n<a href="#" class="code-link">' +
'Show without line numbers</a>');
el.innerHTML = newContent.join('\n');
el.lastChild.addEventListener('click', function (e) {
var w = window.open(),
d = w.document,
codePage = '<html><head><title>Code</title></head>' +
'<body><pre><code>' + oldContent +
'</code></pre></body></html>';
// Cancel triggering event
if (e.preventDefault) {
e.preventDefault();
}
d.open();
d.write(codePage);
d.close();
}, false);
}
}); // End of .forEach
}; // End of formatCode
window.addEventListener('load', formatCode, false);
return true;
}(document, window, hljs));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment