(function(){ if (typeof self === 'undefined' || !self.Prism || !self.document || !document.querySelector) { return; } function $$(expr, con) { return Array.prototype.slice.call((con || document).querySelectorAll(expr)); } function hasClass(element, className) { className = " " + className + " "; return (" " + element.className + " ").replace(/[\n\t]/g, " ").indexOf(className) > -1 } // Some browsers round the line-height, others don't. // We need to test for it to position the elements properly. var isLineHeightRounded = (function() { var res; return function() { if(typeof res === 'undefined') { var d = document.createElement('div'); d.style.fontSize = '13px'; d.style.lineHeight = '1.5'; d.style.padding = 0; d.style.border = 0; d.innerHTML = ' 
 '; document.body.appendChild(d); // Browsers that round the line-height should have offsetHeight === 38 // The others should have 39. res = d.offsetHeight === 38; document.body.removeChild(d); } return res; } }()); function highlightLines(pre, lines, classes) { lines = typeof lines === 'string' ? lines : pre.getAttribute('data-line'); var ranges = lines.replace(/\s+/g, '').split(','), offset = +pre.getAttribute('data-line-offset') || 0; var parseMethod = isLineHeightRounded() ? parseInt : parseFloat; var lineHeight = parseMethod(getComputedStyle(pre).lineHeight); var hasLineNumbers = hasClass(pre, 'line-numbers'); for (var i=0, currentRange; currentRange = ranges[i++];) { var range = currentRange.split('-'); var start = +range[0], end = +range[1] || start; var line = pre.querySelector('.line-highlight[data-range="' + currentRange + '"]') || document.createElement('div'); line.setAttribute('aria-hidden', 'true'); line.setAttribute('data-range', currentRange); line.className = (classes || '') + ' line-highlight'; //if the line-numbers plugin is enabled, then there is no reason for this plugin to display the line numbers if(hasLineNumbers && Prism.plugins.lineNumbers) { var startNode = Prism.plugins.lineNumbers.getLine(pre, start); var endNode = Prism.plugins.lineNumbers.getLine(pre, end); if (startNode) { line.style.top = startNode.offsetTop + 'px'; } if (endNode) { line.style.height = (endNode.offsetTop - startNode.offsetTop) + endNode.offsetHeight + 'px'; } } else { line.setAttribute('data-start', start); if(end > start) { line.setAttribute('data-end', end); } line.style.top = (start - offset - 1) * lineHeight + 'px'; line.textContent = new Array(end - start + 2).join(' \n'); } //allow this to play nicely with the line-numbers plugin if(hasLineNumbers) { //need to attack to pre as when line-numbers is enabled, the code tag is relatively which screws up the positioning pre.appendChild(line); } else { (pre.querySelector('code') || pre).appendChild(line); } } } function applyHash() { var hash = location.hash.slice(1); // Remove pre-existing temporary lines $$('.temporary.line-highlight').forEach(function (line) { line.parentNode.removeChild(line); }); var range = (hash.match(/\.([\d,-]+)$/) || [,''])[1]; if (!range || document.getElementById(hash)) { return; } var id = hash.slice(0, hash.lastIndexOf('.')), pre = document.getElementById(id); if (!pre) { return; } if (!pre.hasAttribute('data-line')) { pre.setAttribute('data-line', ''); } highlightLines(pre, range, 'temporary '); document.querySelector('.temporary.line-highlight').scrollIntoView(); } var fakeTimer = 0; // Hack to limit the number of times applyHash() runs Prism.hooks.add('before-sanity-check', function(env) { var pre = env.element.parentNode; var lines = pre && pre.getAttribute('data-line'); if (!pre || !lines || !/pre/i.test(pre.nodeName)) { return; } /* * Cleanup for other plugins (e.g. autoloader). * * Sometimes blocks are highlighted multiple times. It is necessary * to cleanup any left-over tags, because the whitespace inside of the
* tags change the content of the tag. */ var num = 0; $$('.line-highlight', pre).forEach(function (line) { num += line.textContent.length; line.parentNode.removeChild(line); }); // Remove extra whitespace if (num && /^( \n)+$/.test(env.code.slice(-num))) { env.code = env.code.slice(0, -num); } }); Prism.hooks.add('complete', function completeHook(env) { var pre = env.element.parentNode; var lines = pre && pre.getAttribute('data-line'); if (!pre || !lines || !/pre/i.test(pre.nodeName)) { return; } clearTimeout(fakeTimer); var hasLineNumbers = Prism.plugins.lineNumbers; var isLineNumbersLoaded = env.plugins && env.plugins.lineNumbers; if (hasClass(pre, 'line-numbers') && hasLineNumbers && !isLineNumbersLoaded) { Prism.hooks.add('line-numbers', completeHook); } else { highlightLines(pre, lines); fakeTimer = setTimeout(applyHash, 1); } }); window.addEventListener('hashchange', applyHash); window.addEventListener('resize', function () { var preElements = document.querySelectorAll('pre[data-line]'); Array.prototype.forEach.call(preElements, function (pre) { highlightLines(pre); }); }); })();