| /* http://prismjs.com/download.html?themes=prism-coy&languages=clike+c&plugins=line-highlight+line-numbers */ |
| var _self = (typeof window !== 'undefined') |
| ? window // if in browser |
| : ( |
| (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) |
| ? self // if in worker |
| : {} // if in node js |
| ); |
| |
| /** |
| * Prism: Lightweight, robust, elegant syntax highlighting |
| * MIT license http://www.opensource.org/licenses/mit-license.php/ |
| * @author Lea Verou http://lea.verou.me |
| */ |
| |
| var Prism = (function(){ |
| |
| // Private helper vars |
| var lang = /\blang(?:uage)?-(\w+)\b/i; |
| var uniqueId = 0; |
| |
| var _ = _self.Prism = { |
| manual: _self.Prism && _self.Prism.manual, |
| util: { |
| encode: function (tokens) { |
| if (tokens instanceof Token) { |
| return new Token(tokens.type, _.util.encode(tokens.content), tokens.alias); |
| } else if (_.util.type(tokens) === 'Array') { |
| return tokens.map(_.util.encode); |
| } else { |
| return tokens.replace(/&/g, '&').replace(/</g, '<').replace(/\u00a0/g, ' '); |
| } |
| }, |
| |
| type: function (o) { |
| return Object.prototype.toString.call(o).match(/\[object (\w+)\]/)[1]; |
| }, |
| |
| objId: function (obj) { |
| if (!obj['__id']) { |
| Object.defineProperty(obj, '__id', { value: ++uniqueId }); |
| } |
| return obj['__id']; |
| }, |
| |
| // Deep clone a language definition (e.g. to extend it) |
| clone: function (o) { |
| var type = _.util.type(o); |
| |
| switch (type) { |
| case 'Object': |
| var clone = {}; |
| |
| for (var key in o) { |
| if (o.hasOwnProperty(key)) { |
| clone[key] = _.util.clone(o[key]); |
| } |
| } |
| |
| return clone; |
| |
| case 'Array': |
| // Check for existence for IE8 |
| return o.map && o.map(function(v) { return _.util.clone(v); }); |
| } |
| |
| return o; |
| } |
| }, |
| |
| languages: { |
| extend: function (id, redef) { |
| var lang = _.util.clone(_.languages[id]); |
| |
| for (var key in redef) { |
| lang[key] = redef[key]; |
| } |
| |
| return lang; |
| }, |
| |
| /** |
| * Insert a token before another token in a language literal |
| * As this needs to recreate the object (we cannot actually insert before keys in object literals), |
| * we cannot just provide an object, we need anobject and a key. |
| * @param inside The key (or language id) of the parent |
| * @param before The key to insert before. If not provided, the function appends instead. |
| * @param insert Object with the key/value pairs to insert |
| * @param root The object that contains `inside`. If equal to Prism.languages, it can be omitted. |
| */ |
| insertBefore: function (inside, before, insert, root) { |
| root = root || _.languages; |
| var grammar = root[inside]; |
| |
| if (arguments.length == 2) { |
| insert = arguments[1]; |
| |
| for (var newToken in insert) { |
| if (insert.hasOwnProperty(newToken)) { |
| grammar[newToken] = insert[newToken]; |
| } |
| } |
| |
| return grammar; |
| } |
| |
| var ret = {}; |
| |
| for (var token in grammar) { |
| |
| if (grammar.hasOwnProperty(token)) { |
| |
| if (token == before) { |
| |
| for (var newToken in insert) { |
| |
| if (insert.hasOwnProperty(newToken)) { |
| ret[newToken] = insert[newToken]; |
| } |
| } |
| } |
| |
| ret[token] = grammar[token]; |
| } |
| } |
| |
| // Update references in other language definitions |
| _.languages.DFS(_.languages, function(key, value) { |
| if (value === root[inside] && key != inside) { |
| this[key] = ret; |
| } |
| }); |
| |
| return root[inside] = ret; |
| }, |
| |
| // Traverse a language definition with Depth First Search |
| DFS: function(o, callback, type, visited) { |
| visited = visited || {}; |
| for (var i in o) { |
| if (o.hasOwnProperty(i)) { |
| callback.call(o, i, o[i], type || i); |
| |
| if (_.util.type(o[i]) === 'Object' && !visited[_.util.objId(o[i])]) { |
| visited[_.util.objId(o[i])] = true; |
| _.languages.DFS(o[i], callback, null, visited); |
| } |
| else if (_.util.type(o[i]) === 'Array' && !visited[_.util.objId(o[i])]) { |
| visited[_.util.objId(o[i])] = true; |
| _.languages.DFS(o[i], callback, i, visited); |
| } |
| } |
| } |
| } |
| }, |
| plugins: {}, |
| |
| highlightAll: function(async, callback) { |
| var env = { |
| callback: callback, |
| selector: 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code' |
| }; |
| |
| _.hooks.run("before-highlightall", env); |
| |
| var elements = env.elements || document.querySelectorAll(env.selector); |
| |
| for (var i=0, element; element = elements[i++];) { |
| _.highlightElement(element, async === true, env.callback); |
| } |
| }, |
| |
| highlightElement: function(element, async, callback) { |
| // Find language |
| var language, grammar, parent = element; |
| |
| while (parent && !lang.test(parent.className)) { |
| parent = parent.parentNode; |
| } |
| |
| if (parent) { |
| language = (parent.className.match(lang) || [,''])[1].toLowerCase(); |
| grammar = _.languages[language]; |
| } |
| |
| // Set language on the element, if not present |
| element.className = element.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language; |
| |
| // Set language on the parent, for styling |
| parent = element.parentNode; |
| |
| if (/pre/i.test(parent.nodeName)) { |
| parent.className = parent.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language; |
| } |
| |
| var code = element.textContent; |
| |
| var env = { |
| element: element, |
| language: language, |
| grammar: grammar, |
| code: code |
| }; |
| |
| _.hooks.run('before-sanity-check', env); |
| |
| if (!env.code || !env.grammar) { |
| if (env.code) { |
| _.hooks.run('before-highlight', env); |
| env.element.textContent = env.code; |
| _.hooks.run('after-highlight', env); |
| } |
| _.hooks.run('complete', env); |
| return; |
| } |
| |
| _.hooks.run('before-highlight', env); |
| |
| if (async && _self.Worker) { |
| var worker = new Worker(_.filename); |
| |
| worker.onmessage = function(evt) { |
| env.highlightedCode = evt.data; |
| |
| _.hooks.run('before-insert', env); |
| |
| env.element.innerHTML = env.highlightedCode; |
| |
| callback && callback.call(env.element); |
| _.hooks.run('after-highlight', env); |
| _.hooks.run('complete', env); |
| }; |
| |
| worker.postMessage(JSON.stringify({ |
| language: env.language, |
| code: env.code, |
| immediateClose: true |
| })); |
| } |
| else { |
| env.highlightedCode = _.highlight(env.code, env.grammar, env.language); |
| |
| _.hooks.run('before-insert', env); |
| |
| env.element.innerHTML = env.highlightedCode; |
| |
| callback && callback.call(element); |
| |
| _.hooks.run('after-highlight', env); |
| _.hooks.run('complete', env); |
| } |
| }, |
| |
| highlight: function (text, grammar, language) { |
| var tokens = _.tokenize(text, grammar); |
| return Token.stringify(_.util.encode(tokens), language); |
| }, |
| |
| matchGrammar: function (text, strarr, grammar, index, startPos, oneshot, target) { |
| var Token = _.Token; |
| |
| for (var token in grammar) { |
| if(!grammar.hasOwnProperty(token) || !grammar[token]) { |
| continue; |
| } |
| |
| if (token == target) { |
| return; |
| } |
| |
| var patterns = grammar[token]; |
| patterns = (_.util.type(patterns) === "Array") ? patterns : [patterns]; |
| |
| for (var j = 0; j < patterns.length; ++j) { |
| var pattern = patterns[j], |
| inside = pattern.inside, |
| lookbehind = !!pattern.lookbehind, |
| greedy = !!pattern.greedy, |
| lookbehindLength = 0, |
| alias = pattern.alias; |
| |
| if (greedy && !pattern.pattern.global) { |
| // Without the global flag, lastIndex won't work |
| var flags = pattern.pattern.toString().match(/[imuy]*$/)[0]; |
| pattern.pattern = RegExp(pattern.pattern.source, flags + "g"); |
| } |
| |
| pattern = pattern.pattern || pattern; |
| |
| // Don’t cache length as it changes during the loop |
| for (var i = index, pos = startPos; i < strarr.length; pos += strarr[i].length, ++i) { |
| |
| var str = strarr[i]; |
| |
| if (strarr.length > text.length) { |
| // Something went terribly wrong, ABORT, ABORT! |
| return; |
| } |
| |
| if (str instanceof Token) { |
| continue; |
| } |
| |
| pattern.lastIndex = 0; |
| |
| var match = pattern.exec(str), |
| delNum = 1; |
| |
| // Greedy patterns can override/remove up to two previously matched tokens |
| if (!match && greedy && i != strarr.length - 1) { |
| pattern.lastIndex = pos; |
| match = pattern.exec(text); |
| if (!match) { |
| break; |
| } |
| |
| var from = match.index + (lookbehind ? match[1].length : 0), |
| to = match.index + match[0].length, |
| k = i, |
| p = pos; |
| |
| for (var len = strarr.length; k < len && (p < to || (!strarr[k].type && !strarr[k - 1].greedy)); ++k) { |
| p += strarr[k].length; |
| // Move the index i to the element in strarr that is closest to from |
| if (from >= p) { |
| ++i; |
| pos = p; |
| } |
| } |
| |
| /* |
| * If strarr[i] is a Token, then the match starts inside another Token, which is invalid |
| * If strarr[k - 1] is greedy we are in conflict with another greedy pattern |
| */ |
| if (strarr[i] instanceof Token || strarr[k - 1].greedy) { |
| continue; |
| } |
| |
| // Number of tokens to delete and replace with the new match |
| delNum = k - i; |
| str = text.slice(pos, p); |
| match.index -= pos; |
| } |
| |
| if (!match) { |
| if (oneshot) { |
| break; |
| } |
| |
| continue; |
| } |
| |
| if(lookbehind) { |
| lookbehindLength = match[1].length; |
| } |
| |
| var from = match.index + lookbehindLength, |
| match = match[0].slice(lookbehindLength), |
| to = from + match.length, |
| before = str.slice(0, from), |
| after = str.slice(to); |
| |
| var args = [i, delNum]; |
| |
| if (before) { |
| ++i; |
| pos += before.length; |
| args.push(before); |
| } |
| |
| var wrapped = new Token(token, inside? _.tokenize(match, inside) : match, alias, match, greedy); |
| |
| args.push(wrapped); |
| |
| if (after) { |
| args.push(after); |
| } |
| |
| Array.prototype.splice.apply(strarr, args); |
| |
| if (delNum != 1) |
| _.matchGrammar(text, strarr, grammar, i, pos, true, token); |
| |
| if (oneshot) |
| break; |
| } |
| } |
| } |
| }, |
| |
| tokenize: function(text, grammar, language) { |
| var strarr = [text]; |
| |
| var rest = grammar.rest; |
| |
| if (rest) { |
| for (var token in rest) { |
| grammar[token] = rest[token]; |
| } |
| |
| delete grammar.rest; |
| } |
| |
| _.matchGrammar(text, strarr, grammar, 0, 0, false); |
| |
| return strarr; |
| }, |
| |
| hooks: { |
| all: {}, |
| |
| add: function (name, callback) { |
| var hooks = _.hooks.all; |
| |
| hooks[name] = hooks[name] || []; |
| |
| hooks[name].push(callback); |
| }, |
| |
| run: function (name, env) { |
| var callbacks = _.hooks.all[name]; |
| |
| if (!callbacks || !callbacks.length) { |
| return; |
| } |
| |
| for (var i=0, callback; callback = callbacks[i++];) { |
| callback(env); |
| } |
| } |
| } |
| }; |
| |
| var Token = _.Token = function(type, content, alias, matchedStr, greedy) { |
| this.type = type; |
| this.content = content; |
| this.alias = alias; |
| // Copy of the full string this token was created from |
| this.length = (matchedStr || "").length|0; |
| this.greedy = !!greedy; |
| }; |
| |
| Token.stringify = function(o, language, parent) { |
| if (typeof o == 'string') { |
| return o; |
| } |
| |
| if (_.util.type(o) === 'Array') { |
| return o.map(function(element) { |
| return Token.stringify(element, language, o); |
| }).join(''); |
| } |
| |
| var env = { |
| type: o.type, |
| content: Token.stringify(o.content, language, parent), |
| tag: 'span', |
| classes: ['token', o.type], |
| attributes: {}, |
| language: language, |
| parent: parent |
| }; |
| |
| if (env.type == 'comment') { |
| env.attributes['spellcheck'] = 'true'; |
| } |
| |
| if (o.alias) { |
| var aliases = _.util.type(o.alias) === 'Array' ? o.alias : [o.alias]; |
| Array.prototype.push.apply(env.classes, aliases); |
| } |
| |
| _.hooks.run('wrap', env); |
| |
| var attributes = Object.keys(env.attributes).map(function(name) { |
| return name + '="' + (env.attributes[name] || '').replace(/"/g, '"') + '"'; |
| }).join(' '); |
| |
| return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + (attributes ? ' ' + attributes : '') + '>' + env.content + '</' + env.tag + '>'; |
| |
| }; |
| |
| if (!_self.document) { |
| if (!_self.addEventListener) { |
| // in Node.js |
| return _self.Prism; |
| } |
| // In worker |
| _self.addEventListener('message', function(evt) { |
| var message = JSON.parse(evt.data), |
| lang = message.language, |
| code = message.code, |
| immediateClose = message.immediateClose; |
| |
| _self.postMessage(_.highlight(code, _.languages[lang], lang)); |
| if (immediateClose) { |
| _self.close(); |
| } |
| }, false); |
| |
| return _self.Prism; |
| } |
| |
| //Get current script and highlight |
| var script = document.currentScript || [].slice.call(document.getElementsByTagName("script")).pop(); |
| |
| if (script) { |
| _.filename = script.src; |
| |
| if (document.addEventListener && !_.manual && !script.hasAttribute('data-manual')) { |
| if(document.readyState !== "loading") { |
| if (window.requestAnimationFrame) { |
| window.requestAnimationFrame(_.highlightAll); |
| } else { |
| window.setTimeout(_.highlightAll, 16); |
| } |
| } |
| else { |
| document.addEventListener('DOMContentLoaded', _.highlightAll); |
| } |
| } |
| } |
| |
| return _self.Prism; |
| |
| })(); |
| |
| if (typeof module !== 'undefined' && module.exports) { |
| module.exports = Prism; |
| } |
| |
| // hack for components to work correctly in node.js |
| if (typeof global !== 'undefined') { |
| global.Prism = Prism; |
| } |
| ; |
| Prism.languages.clike = { |
| 'comment': [ |
| { |
| pattern: /(^|[^\\])\/\*[\s\S]*?\*\//, |
| lookbehind: true |
| }, |
| { |
| pattern: /(^|[^\\:])\/\/.*/, |
| lookbehind: true |
| } |
| ], |
| 'string': { |
| pattern: /(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, |
| greedy: true |
| }, |
| 'class-name': { |
| pattern: /((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i, |
| lookbehind: true, |
| inside: { |
| punctuation: /(\.|\\)/ |
| } |
| }, |
| 'keyword': /\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/, |
| 'boolean': /\b(true|false)\b/, |
| 'function': /[a-z0-9_]+(?=\()/i, |
| 'number': /\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)\b/i, |
| 'operator': /--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/, |
| 'punctuation': /[{}[\];(),.:]/ |
| }; |
| |
| Prism.languages.c = Prism.languages.extend('clike', { |
| 'keyword': /\b(asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/, |
| 'operator': /\-[>-]?|\+\+?|!=?|<<?=?|>>?=?|==?|&&?|\|?\||[~^%?*\/]/, |
| 'number': /\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)[ful]*\b/i |
| }); |
| |
| Prism.languages.insertBefore('c', 'string', { |
| 'macro': { |
| // allow for multiline macro definitions |
| // spaces after the # character compile fine with gcc |
| pattern: /(^\s*)#\s*[a-z]+([^\r\n\\]|\\.|\\(?:\r\n?|\n))*/im, |
| lookbehind: true, |
| alias: 'property', |
| inside: { |
| // highlight the path of the include statement as a string |
| 'string': { |
| pattern: /(#\s*include\s*)(<.+?>|("|')(\\?.)+?\3)/, |
| lookbehind: true |
| }, |
| // highlight macro directives as keywords |
| 'directive': { |
| pattern: /(#\s*)\b(define|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\b/, |
| lookbehind: true, |
| alias: 'keyword' |
| } |
| } |
| }, |
| // highlight predefined macros as constants |
| 'constant': /\b(__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|stdin|stdout|stderr)\b/ |
| }); |
| |
| delete Prism.languages.c['class-name']; |
| delete Prism.languages.c['boolean']; |
| |
| (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 = ' <br /> '; |
| 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) { |
| 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); |
| |
| for (var i=0, range; range = ranges[i++];) { |
| range = range.split('-'); |
| |
| var start = +range[0], |
| end = +range[1] || start; |
| |
| var line = document.createElement('div'); |
| |
| line.textContent = Array(end - start + 2).join(' \n'); |
| line.setAttribute('aria-hidden', 'true'); |
| 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(!hasClass(pre, 'line-numbers')) { |
| line.setAttribute('data-start', start); |
| |
| if(end > start) { |
| line.setAttribute('data-end', end); |
| } |
| } |
| |
| line.style.top = (start - offset - 1) * lineHeight + 'px'; |
| |
| //allow this to play nicely with the line-numbers plugin |
| if(hasClass(pre, 'line-numbers')) { |
| //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 <code> blocks are highlighted multiple times. It is necessary |
| * to cleanup any left-over tags, because the whitespace inside of the <div> |
| * tags change the content of the <code> 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(env) { |
| var pre = env.element.parentNode; |
| var lines = pre && pre.getAttribute('data-line'); |
| |
| if (!pre || !lines || !/pre/i.test(pre.nodeName)) { |
| return; |
| } |
| |
| clearTimeout(fakeTimer); |
| |
| highlightLines(pre, lines); |
| |
| fakeTimer = setTimeout(applyHash, 1); |
| }); |
| |
| if(window.addEventListener) { |
| window.addEventListener('hashchange', applyHash); |
| } |
| |
| })(); |
| |
| (function() { |
| |
| if (typeof self === 'undefined' || !self.Prism || !self.document) { |
| return; |
| } |
| |
| Prism.hooks.add('complete', function (env) { |
| if (!env.code) { |
| return; |
| } |
| |
| // works only for <code> wrapped inside <pre> (not inline) |
| var pre = env.element.parentNode; |
| var clsReg = /\s*\bline-numbers\b\s*/; |
| if ( |
| !pre || !/pre/i.test(pre.nodeName) || |
| // Abort only if nor the <pre> nor the <code> have the class |
| (!clsReg.test(pre.className) && !clsReg.test(env.element.className)) |
| ) { |
| return; |
| } |
| |
| if (env.element.querySelector(".line-numbers-rows")) { |
| // Abort if line numbers already exists |
| return; |
| } |
| |
| if (clsReg.test(env.element.className)) { |
| // Remove the class "line-numbers" from the <code> |
| env.element.className = env.element.className.replace(clsReg, ''); |
| } |
| if (!clsReg.test(pre.className)) { |
| // Add the class "line-numbers" to the <pre> |
| pre.className += ' line-numbers'; |
| } |
| |
| var match = env.code.match(/\n(?!$)/g); |
| var linesNum = match ? match.length + 1 : 1; |
| var lineNumbersWrapper; |
| |
| var lines = new Array(linesNum + 1); |
| lines = lines.join('<span></span>'); |
| |
| lineNumbersWrapper = document.createElement('span'); |
| lineNumbersWrapper.setAttribute('aria-hidden', 'true'); |
| lineNumbersWrapper.className = 'line-numbers-rows'; |
| lineNumbersWrapper.innerHTML = lines; |
| |
| if (pre.hasAttribute('data-start')) { |
| pre.style.counterReset = 'linenumber ' + (parseInt(pre.getAttribute('data-start'), 10) - 1); |
| } |
| |
| env.element.appendChild(lineNumbersWrapper); |
| |
| }); |
| |
| }()); |