1 | (function () {
|
2 |
|
3 | if (typeof Prism === 'undefined' || typeof document === 'undefined') {
|
4 | return;
|
5 | }
|
6 |
|
7 | |
8 |
|
9 |
|
10 |
|
11 |
|
12 | var PLUGIN_NAME = 'line-numbers';
|
13 |
|
14 | |
15 |
|
16 |
|
17 |
|
18 |
|
19 | var NEW_LINE_EXP = /\n(?!$)/g;
|
20 |
|
21 |
|
22 | |
23 |
|
24 |
|
25 | var config = Prism.plugins.lineNumbers = {
|
26 | |
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 | getLine: function (element, number) {
|
34 | if (element.tagName !== 'PRE' || !element.classList.contains(PLUGIN_NAME)) {
|
35 | return;
|
36 | }
|
37 |
|
38 | var lineNumberRows = element.querySelector('.line-numbers-rows');
|
39 | if (!lineNumberRows) {
|
40 | return;
|
41 | }
|
42 | var lineNumberStart = parseInt(element.getAttribute('data-start'), 10) || 1;
|
43 | var lineNumberEnd = lineNumberStart + (lineNumberRows.children.length - 1);
|
44 |
|
45 | if (number < lineNumberStart) {
|
46 | number = lineNumberStart;
|
47 | }
|
48 | if (number > lineNumberEnd) {
|
49 | number = lineNumberEnd;
|
50 | }
|
51 |
|
52 | var lineIndex = number - lineNumberStart;
|
53 |
|
54 | return lineNumberRows.children[lineIndex];
|
55 | },
|
56 |
|
57 | |
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 | resize: function (element) {
|
66 | resizeElements([element]);
|
67 | },
|
68 |
|
69 | |
70 |
|
71 |
|
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 | assumeViewportIndependence: true
|
80 | };
|
81 |
|
82 | |
83 |
|
84 |
|
85 |
|
86 |
|
87 | function resizeElements(elements) {
|
88 | elements = elements.filter(function (e) {
|
89 | var codeStyles = getStyles(e);
|
90 | var whiteSpace = codeStyles['white-space'];
|
91 | return whiteSpace === 'pre-wrap' || whiteSpace === 'pre-line';
|
92 | });
|
93 |
|
94 | if (elements.length == 0) {
|
95 | return;
|
96 | }
|
97 |
|
98 | var infos = elements.map(function (element) {
|
99 | var codeElement = element.querySelector('code');
|
100 | var lineNumbersWrapper = element.querySelector('.line-numbers-rows');
|
101 | if (!codeElement || !lineNumbersWrapper) {
|
102 | return undefined;
|
103 | }
|
104 |
|
105 |
|
106 | var lineNumberSizer = element.querySelector('.line-numbers-sizer');
|
107 | var codeLines = codeElement.textContent.split(NEW_LINE_EXP);
|
108 |
|
109 | if (!lineNumberSizer) {
|
110 | lineNumberSizer = document.createElement('span');
|
111 | lineNumberSizer.className = 'line-numbers-sizer';
|
112 |
|
113 | codeElement.appendChild(lineNumberSizer);
|
114 | }
|
115 |
|
116 | lineNumberSizer.innerHTML = '0';
|
117 | lineNumberSizer.style.display = 'block';
|
118 |
|
119 | var oneLinerHeight = lineNumberSizer.getBoundingClientRect().height;
|
120 | lineNumberSizer.innerHTML = '';
|
121 |
|
122 | return {
|
123 | element: element,
|
124 | lines: codeLines,
|
125 | lineHeights: [],
|
126 | oneLinerHeight: oneLinerHeight,
|
127 | sizer: lineNumberSizer,
|
128 | };
|
129 | }).filter(Boolean);
|
130 |
|
131 | infos.forEach(function (info) {
|
132 | var lineNumberSizer = info.sizer;
|
133 | var lines = info.lines;
|
134 | var lineHeights = info.lineHeights;
|
135 | var oneLinerHeight = info.oneLinerHeight;
|
136 |
|
137 | lineHeights[lines.length - 1] = undefined;
|
138 | lines.forEach(function (line, index) {
|
139 | if (line && line.length > 1) {
|
140 | var e = lineNumberSizer.appendChild(document.createElement('span'));
|
141 | e.style.display = 'block';
|
142 | e.textContent = line;
|
143 | } else {
|
144 | lineHeights[index] = oneLinerHeight;
|
145 | }
|
146 | });
|
147 | });
|
148 |
|
149 | infos.forEach(function (info) {
|
150 | var lineNumberSizer = info.sizer;
|
151 | var lineHeights = info.lineHeights;
|
152 |
|
153 | var childIndex = 0;
|
154 | for (var i = 0; i < lineHeights.length; i++) {
|
155 | if (lineHeights[i] === undefined) {
|
156 | lineHeights[i] = lineNumberSizer.children[childIndex++].getBoundingClientRect().height;
|
157 | }
|
158 | }
|
159 | });
|
160 |
|
161 | infos.forEach(function (info) {
|
162 | var lineNumberSizer = info.sizer;
|
163 | var wrapper = info.element.querySelector('.line-numbers-rows');
|
164 |
|
165 | lineNumberSizer.style.display = 'none';
|
166 | lineNumberSizer.innerHTML = '';
|
167 |
|
168 | info.lineHeights.forEach(function (height, lineNumber) {
|
169 | wrapper.children[lineNumber].style.height = height + 'px';
|
170 | });
|
171 | });
|
172 | }
|
173 |
|
174 | |
175 |
|
176 |
|
177 |
|
178 |
|
179 | function getStyles(element) {
|
180 | if (!element) {
|
181 | return null;
|
182 | }
|
183 |
|
184 | return window.getComputedStyle ? getComputedStyle(element) : (element.currentStyle || null);
|
185 | }
|
186 |
|
187 | var lastWidth = undefined;
|
188 | window.addEventListener('resize', function () {
|
189 | if (config.assumeViewportIndependence && lastWidth === window.innerWidth) {
|
190 | return;
|
191 | }
|
192 | lastWidth = window.innerWidth;
|
193 |
|
194 | resizeElements(Array.prototype.slice.call(document.querySelectorAll('pre.' + PLUGIN_NAME)));
|
195 | });
|
196 |
|
197 | Prism.hooks.add('complete', function (env) {
|
198 | if (!env.code) {
|
199 | return;
|
200 | }
|
201 |
|
202 | var code = (env.element);
|
203 | var pre = (code.parentNode);
|
204 |
|
205 |
|
206 | if (!pre || !/pre/i.test(pre.nodeName)) {
|
207 | return;
|
208 | }
|
209 |
|
210 |
|
211 | if (code.querySelector('.line-numbers-rows')) {
|
212 | return;
|
213 | }
|
214 |
|
215 |
|
216 | if (!Prism.util.isActive(code, PLUGIN_NAME)) {
|
217 | return;
|
218 | }
|
219 |
|
220 |
|
221 | code.classList.remove(PLUGIN_NAME);
|
222 |
|
223 | pre.classList.add(PLUGIN_NAME);
|
224 |
|
225 | var match = env.code.match(NEW_LINE_EXP);
|
226 | var linesNum = match ? match.length + 1 : 1;
|
227 | var lineNumbersWrapper;
|
228 |
|
229 | var lines = new Array(linesNum + 1).join('<span></span>');
|
230 |
|
231 | lineNumbersWrapper = document.createElement('span');
|
232 | lineNumbersWrapper.setAttribute('aria-hidden', 'true');
|
233 | lineNumbersWrapper.className = 'line-numbers-rows';
|
234 | lineNumbersWrapper.innerHTML = lines;
|
235 |
|
236 | if (pre.hasAttribute('data-start')) {
|
237 | pre.style.counterReset = 'linenumber ' + (parseInt(pre.getAttribute('data-start'), 10) - 1);
|
238 | }
|
239 |
|
240 | env.element.appendChild(lineNumbersWrapper);
|
241 |
|
242 | resizeElements([pre]);
|
243 |
|
244 | Prism.hooks.run('line-numbers', env);
|
245 | });
|
246 |
|
247 | Prism.hooks.add('line-numbers', function (env) {
|
248 | env.plugins = env.plugins || {};
|
249 | env.plugins.lineNumbers = true;
|
250 | });
|
251 |
|
252 | }());
|