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