1 | (function () {
|
2 |
|
3 | if (typeof self === 'undefined' || !self.Prism || !self.document || !document.querySelector) {
|
4 | return;
|
5 | }
|
6 |
|
7 | |
8 |
|
9 |
|
10 |
|
11 |
|
12 | function $$(selector, container) {
|
13 | return Array.prototype.slice.call((container || document).querySelectorAll(selector));
|
14 | }
|
15 |
|
16 | |
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 | function hasClass(element, className) {
|
24 | className = " " + className + " ";
|
25 | return (" " + element.className + " ").replace(/[\n\t]/g, " ").indexOf(className) > -1
|
26 | }
|
27 |
|
28 | |
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 | function callFunction(func) {
|
35 | func();
|
36 | }
|
37 |
|
38 |
|
39 |
|
40 | var isLineHeightRounded = (function () {
|
41 | var res;
|
42 | return function () {
|
43 | if (typeof res === 'undefined') {
|
44 | var d = document.createElement('div');
|
45 | d.style.fontSize = '13px';
|
46 | d.style.lineHeight = '1.5';
|
47 | d.style.padding = '0';
|
48 | d.style.border = '0';
|
49 | d.innerHTML = ' <br /> ';
|
50 | document.body.appendChild(d);
|
51 |
|
52 |
|
53 | res = d.offsetHeight === 38;
|
54 | document.body.removeChild(d);
|
55 | }
|
56 | return res;
|
57 | }
|
58 | }());
|
59 |
|
60 | |
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 | function highlightLines(pre, lines, classes) {
|
72 | lines = typeof lines === 'string' ? lines : pre.getAttribute('data-line');
|
73 |
|
74 | var ranges = lines.replace(/\s+/g, '').split(',').filter(Boolean);
|
75 | var offset = +pre.getAttribute('data-line-offset') || 0;
|
76 |
|
77 | var parseMethod = isLineHeightRounded() ? parseInt : parseFloat;
|
78 | var lineHeight = parseMethod(getComputedStyle(pre).lineHeight);
|
79 | var hasLineNumbers = hasClass(pre, 'line-numbers');
|
80 | var parentElement = hasLineNumbers ? pre : pre.querySelector('code') || pre;
|
81 | var mutateActions = ([]);
|
82 |
|
83 | ranges.forEach(function (currentRange) {
|
84 | var range = currentRange.split('-');
|
85 |
|
86 | var start = +range[0];
|
87 | var end = +range[1] || start;
|
88 |
|
89 |
|
90 | var line = pre.querySelector('.line-highlight[data-range="' + currentRange + '"]') || document.createElement('div');
|
91 |
|
92 | mutateActions.push(function () {
|
93 | line.setAttribute('aria-hidden', 'true');
|
94 | line.setAttribute('data-range', currentRange);
|
95 | line.className = (classes || '') + ' line-highlight';
|
96 | });
|
97 |
|
98 |
|
99 | if (hasLineNumbers && Prism.plugins.lineNumbers) {
|
100 | var startNode = Prism.plugins.lineNumbers.getLine(pre, start);
|
101 | var endNode = Prism.plugins.lineNumbers.getLine(pre, end);
|
102 |
|
103 | if (startNode) {
|
104 | var top = startNode.offsetTop + 'px';
|
105 | mutateActions.push(function () {
|
106 | line.style.top = top;
|
107 | });
|
108 | }
|
109 |
|
110 | if (endNode) {
|
111 | var height = (endNode.offsetTop - startNode.offsetTop) + endNode.offsetHeight + 'px';
|
112 | mutateActions.push(function () {
|
113 | line.style.height = height;
|
114 | });
|
115 | }
|
116 | } else {
|
117 | mutateActions.push(function () {
|
118 | line.setAttribute('data-start', start);
|
119 |
|
120 | if (end > start) {
|
121 | line.setAttribute('data-end', end);
|
122 | }
|
123 |
|
124 | line.style.top = (start - offset - 1) * lineHeight + 'px';
|
125 |
|
126 | line.textContent = new Array(end - start + 2).join(' \n');
|
127 | });
|
128 | }
|
129 |
|
130 | mutateActions.push(function () {
|
131 |
|
132 |
|
133 | parentElement.appendChild(line);
|
134 | });
|
135 | });
|
136 |
|
137 | var id = pre.id;
|
138 | if (hasLineNumbers && id) {
|
139 |
|
140 |
|
141 |
|
142 |
|
143 |
|
144 |
|
145 | var linkableLineNumbersClass = 'linkable-line-numbers';
|
146 | var linkableLineNumbers = false;
|
147 | var node = pre;
|
148 | while (node) {
|
149 | if (hasClass(node, linkableLineNumbersClass)) {
|
150 | linkableLineNumbers = true;
|
151 | break;
|
152 | }
|
153 | node = node.parentElement;
|
154 | }
|
155 |
|
156 | if (linkableLineNumbers) {
|
157 | if (!hasClass(pre, linkableLineNumbersClass)) {
|
158 |
|
159 | mutateActions.push(function () {
|
160 | pre.className = (pre.className + ' ' + linkableLineNumbersClass).trim();
|
161 | });
|
162 | }
|
163 |
|
164 | var start = parseInt(pre.getAttribute('data-start') || '1');
|
165 |
|
166 |
|
167 | $$('.line-numbers-rows > span', pre).forEach(function (lineSpan, i) {
|
168 | var lineNumber = i + start;
|
169 | lineSpan.onclick = function () {
|
170 | var hash = id + '.' + lineNumber;
|
171 |
|
172 |
|
173 | scrollIntoView = false;
|
174 | location.hash = hash;
|
175 | setTimeout(function () {
|
176 | scrollIntoView = true;
|
177 | }, 1);
|
178 | };
|
179 | });
|
180 | }
|
181 | }
|
182 |
|
183 | return function () {
|
184 | mutateActions.forEach(callFunction);
|
185 | };
|
186 | }
|
187 |
|
188 | var scrollIntoView = true;
|
189 | function applyHash() {
|
190 | var hash = location.hash.slice(1);
|
191 |
|
192 |
|
193 | $$('.temporary.line-highlight').forEach(function (line) {
|
194 | line.parentNode.removeChild(line);
|
195 | });
|
196 |
|
197 | var range = (hash.match(/\.([\d,-]+)$/) || [, ''])[1];
|
198 |
|
199 | if (!range || document.getElementById(hash)) {
|
200 | return;
|
201 | }
|
202 |
|
203 | var id = hash.slice(0, hash.lastIndexOf('.')),
|
204 | pre = document.getElementById(id);
|
205 |
|
206 | if (!pre) {
|
207 | return;
|
208 | }
|
209 |
|
210 | if (!pre.hasAttribute('data-line')) {
|
211 | pre.setAttribute('data-line', '');
|
212 | }
|
213 |
|
214 | var mutateDom = highlightLines(pre, range, 'temporary ');
|
215 | mutateDom();
|
216 |
|
217 | if (scrollIntoView) {
|
218 | document.querySelector('.temporary.line-highlight').scrollIntoView();
|
219 | }
|
220 | }
|
221 |
|
222 | var fakeTimer = 0;
|
223 |
|
224 | Prism.hooks.add('before-sanity-check', function (env) {
|
225 | var pre = env.element.parentNode;
|
226 | var lines = pre && pre.getAttribute('data-line');
|
227 |
|
228 | if (!pre || !lines || !/pre/i.test(pre.nodeName)) {
|
229 | return;
|
230 | }
|
231 |
|
232 | |
233 |
|
234 |
|
235 |
|
236 |
|
237 |
|
238 |
|
239 | var num = 0;
|
240 | $$('.line-highlight', pre).forEach(function (line) {
|
241 | num += line.textContent.length;
|
242 | line.parentNode.removeChild(line);
|
243 | });
|
244 |
|
245 | if (num && /^( \n)+$/.test(env.code.slice(-num))) {
|
246 | env.code = env.code.slice(0, -num);
|
247 | }
|
248 | });
|
249 |
|
250 | Prism.hooks.add('complete', function completeHook(env) {
|
251 | var pre = env.element.parentNode;
|
252 | var lines = pre && pre.getAttribute('data-line');
|
253 |
|
254 | if (!pre || !lines || !/pre/i.test(pre.nodeName)) {
|
255 | return;
|
256 | }
|
257 |
|
258 | clearTimeout(fakeTimer);
|
259 |
|
260 | var hasLineNumbers = Prism.plugins.lineNumbers;
|
261 | var isLineNumbersLoaded = env.plugins && env.plugins.lineNumbers;
|
262 |
|
263 | if (hasClass(pre, 'line-numbers') && hasLineNumbers && !isLineNumbersLoaded) {
|
264 | Prism.hooks.add('line-numbers', completeHook);
|
265 | } else {
|
266 | var mutateDom = highlightLines(pre, lines);
|
267 | mutateDom();
|
268 | fakeTimer = setTimeout(applyHash, 1);
|
269 | }
|
270 | });
|
271 |
|
272 | window.addEventListener('hashchange', applyHash);
|
273 | window.addEventListener('resize', function () {
|
274 | var actions = $$('pre[data-line]').map(function (pre) {
|
275 | return highlightLines(pre);
|
276 | });
|
277 | actions.forEach(callFunction);
|
278 | });
|
279 |
|
280 | })();
|