3
if (typeof self === 'undefined' || !self.Prism || !self.document || !document.querySelector) {
7
function $$(expr, con) {
8
return Array.prototype.slice.call((con || document).querySelectorAll(expr));
11
function hasClass(element, className) {
12
className = " " + className + " ";
13
return (" " + element.className + " ").replace(/[\n\t]/g, " ").indexOf(className) > -1
16
// Some browsers round the line-height, others don't.
17
// We need to test for it to position the elements properly.
18
var isLineHeightRounded = (function() {
21
if(typeof res === 'undefined') {
22
var d = document.createElement('div');
23
d.style.fontSize = '13px';
24
d.style.lineHeight = '1.5';
27
d.innerHTML = ' <br /> ';
28
document.body.appendChild(d);
29
// Browsers that round the line-height should have offsetHeight === 38
30
// The others should have 39.
31
res = d.offsetHeight === 38;
32
document.body.removeChild(d);
38
function highlightLines(pre, lines, classes) {
39
var ranges = lines.replace(/\s+/g, '').split(','),
40
offset = +pre.getAttribute('data-line-offset') || 0;
42
var parseMethod = isLineHeightRounded() ? parseInt : parseFloat;
43
var lineHeight = parseMethod(getComputedStyle(pre).lineHeight);
45
for (var i=0, range; range = ranges[i++];) {
46
range = range.split('-');
48
var start = +range[0],
49
end = +range[1] || start;
51
var line = document.createElement('div');
53
line.textContent = Array(end - start + 2).join(' \n');
54
line.className = (classes || '') + ' line-highlight';
56
//if the line-numbers plugin is enabled, then there is no reason for this plugin to display the line numbers
57
if(!hasClass(pre, 'line-numbers')) {
58
line.setAttribute('data-start', start);
61
line.setAttribute('data-end', end);
65
line.style.top = (start - offset - 1) * lineHeight + 'px';
67
//allow this to play nicely with the line-numbers plugin
68
if(hasClass(pre, 'line-numbers')) {
69
//need to attack to pre as when line-numbers is enabled, the code tag is relatively which screws up the positioning
70
pre.appendChild(line);
72
(pre.querySelector('code') || pre).appendChild(line);
77
function applyHash() {
78
var hash = location.hash.slice(1);
80
// Remove pre-existing temporary lines
81
$$('.temporary.line-highlight').forEach(function (line) {
82
line.parentNode.removeChild(line);
85
var range = (hash.match(/\.([\d,-]+)$/) || [,''])[1];
87
if (!range || document.getElementById(hash)) {
91
var id = hash.slice(0, hash.lastIndexOf('.')),
92
pre = document.getElementById(id);
98
if (!pre.hasAttribute('data-line')) {
99
pre.setAttribute('data-line', '');
102
highlightLines(pre, range, 'temporary ');
104
document.querySelector('.temporary.line-highlight').scrollIntoView();
107
var fakeTimer = 0; // Hack to limit the number of times applyHash() runs
109
Prism.hooks.add('complete', function(env) {
110
var pre = env.element.parentNode;
111
var lines = pre && pre.getAttribute('data-line');
113
if (!pre || !lines || !/pre/i.test(pre.nodeName)) {
117
clearTimeout(fakeTimer);
119
$$('.line-highlight', pre).forEach(function (line) {
120
line.parentNode.removeChild(line);
123
highlightLines(pre, lines);
125
fakeTimer = setTimeout(applyHash, 1);
128
if(window.addEventListener) {
129
window.addEventListener('hashchange', applyHash);