Package_html_static.mk        |    2 
 help3xsl/README.prism.js.txt  |   39 +
 help3xsl/default.css          |   31 -
 help3xsl/online_transform.xsl |   14 
 help3xsl/prism.css            |  270 +++++++++
 help3xsl/prism.js             | 1190 ++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 1508 insertions(+), 38 deletions(-)

New commits:
commit 635750a0cda2e9f6f906e10e33a087b579a74ba8
Author:     Olivier Hallot <olivier.hal...@libreoffice.org>
AuthorDate: Thu Nov 29 11:09:15 2018 -0200
Commit:     Olivier Hallot <olivier.hal...@libreoffice.org>
CommitDate: Thu Nov 29 21:41:54 2018 +0100

    tdf#115663 Syntax highlight in BASIC code examples
    
    Use prism.js to highlight BASIC code in help pages
    See README.prism.js.txt for details
    
    added normalize-whitespaces plugin to remove extra 1st line
    cleaned some useless css class
    
    Change-Id: I6dde4d217a29f485199ced462b896ee1b500fba0
    Reviewed-on: https://gerrit.libreoffice.org/64252
    Tested-by: Jenkins
    Reviewed-by: Olivier Hallot <olivier.hal...@libreoffice.org>

diff --git a/Package_html_static.mk b/Package_html_static.mk
index 59941b020..a53929878 100644
--- a/Package_html_static.mk
+++ b/Package_html_static.mk
@@ -23,6 +23,8 @@ $(eval $(call 
gb_Package_add_files,helpcontent2_html_static,$(LIBO_SHARE_HELP_FO
        help2.js \
        normalize.css \
        paginathing.js \
+       prism.js \
+        prism.css \
 ))
 
 # vim: set noet sw=4 ts=4:
diff --git a/help3xsl/README.prism.js.txt b/help3xsl/README.prism.js.txt
new file mode 100644
index 000000000..581a1fe71
--- /dev/null
+++ b/help3xsl/README.prism.js.txt
@@ -0,0 +1,39 @@
+Using prism.js for Basic code highlight
+
+http://prismjs.com
+
+License MIT (see prism.js)
+
+Download page http://prismjs.com/download
+
+Theme: Coy
+
+Languages to download: Visual Basic + Python + defaults pre-sets
+
+Plugins: line numbers,
+
+normalize-whitespace: configure after 
https://prismjs.com/plugins/normalize-whitespace/
+
+Prism.plugins.NormalizeWhitespace = new NormalizeWhitespace({
+'remove-trailing': true,
+'remove-indent': true,
+'left-trim': true,
+'right-trim': true,
+/*'break-lines': 80,
+'indent': 2,*/
+'remove-initial-line-feed': true,
+/*'tabs-to-spaces': 4,
+'spaces-to-tabs': 4*/
+});
+
+
+Usage:
+
+Add prism.js and prism.css to html page,
+
+Add class 'language-visual-basic' and 'line-numbers' to <code> as in
+
+<xsl:template match="bascode">
+    <div class="bascode" itemscope="true" 
itemtype="http://schema.org/SoftwareSourceCode"; itemprop="codeSampleType" 
content="snippet">
+   <pre><code class="language-visual-basic line-numbers"><xsl:apply-templates 
/></code></pre></div>
+</xsl:template>
diff --git a/help3xsl/default.css b/help3xsl/default.css
index 285d1e900..6cb76ce38 100644
--- a/help3xsl/default.css
+++ b/help3xsl/default.css
@@ -314,37 +314,10 @@ h6 {
     font-size:1.2rem;
 }
 .bascode {
-    background-color: #fafafa;
-    margin-left: 30px;
-    margin-right: 30px;
+    margin-top:15px;
+    margin-bottom: 15px;
 }
-.bascodepar {
-    font-family: monospace;
-}
-
-/* Basic code syntax highlight */
 
-.identifier,
-.unknown {
-    color: green;
-}
-.keyword {
-    color: blue;
-}
-.comment {
-    color: gray;
-}
-.number,
-.string {
-    color: red;
-}
-.operator,
-.parameter {
-    color: black;
-}
-.hotlink {
-    color: blue;
-}
 .infopage {
     color: green;
     font-size: 1.33rem;
diff --git a/help3xsl/online_transform.xsl b/help3xsl/online_transform.xsl
index 59eb5120a..e5671e22f 100644
--- a/help3xsl/online_transform.xsl
+++ b/help3xsl/online_transform.xsl
@@ -152,11 +152,13 @@
         <link rel="shortcut icon" href="{$target}media/navigation/favicon.ico" 
/>
         <link  type="text/css" href="{$target}normalize.css" rel="Stylesheet" 
/>
         <link  type="text/css" href="{$target}default.css" rel="Stylesheet" />
+        <link  type="text/css" href="{$target}prism.css" rel="Stylesheet" />
         <script type="text/javascript" src="{$target}help2.js"></script>
         <script type="text/javascript" src="{$target}languages.js"></script>
         <script type="text/javascript" 
src="{$target}{$lang}/langnames.js"></script>
         <script type="text/javascript" src="{$target}fuzzysort.js"></script>
         <script type="text/javascript" src="{$target}paginathing.js"></script>
+        <script type="text/javascript" src="{$target}prism.js"></script>
         <meta name="viewport" content="width=device-width,initial-scale=1"/>
     </head>
     <body itemscope="true" itemtype="http://schema.org/TechArticle";>
@@ -552,7 +554,7 @@
         </xsl:when>
 
         <xsl:when test="@role='bascode'">
-            <xsl:call-template name="insertbascode" />
+            <xsl:value-of select="." />
         </xsl:when>
 
         <xsl:when test="@role='logocode'">
@@ -925,7 +927,6 @@
 
 </xsl:template>
 
-
 <!-- Insert Paragraph -->
 <xsl:template name="insertpara">
     <xsl:variable name="role">
@@ -942,15 +943,10 @@
 </xsl:template>
 
 <xsl:template match="bascode">
-    <div class="bascode" itemscope="true" 
itemtype="http://schema.org/SoftwareSourceCode"; itemprop="codeSampleType" 
content="snippet"><xsl:apply-templates /></div>
+    <div class="bascode" itemscope="true" 
itemtype="http://schema.org/SoftwareSourceCode"; itemprop="codeSampleType" 
content="snippet"><pre><code class="language-visual-basic 
line-numbers"><xsl:apply-templates /></code></pre></div>
 </xsl:template>
 <xsl:template match="bascode" mode="embedded">
-    <div class="bascode" itemscope="true" 
itemtype="http://schema.org/SoftwareSourceCode"; itemprop="codeSampleType" 
content="snippet"><xsl:apply-templates /></div>
-</xsl:template>
-
-<!-- Insert Basic code snippet  -->
-<xsl:template name="insertbascode">
-    <pre class="bascodepar"><xsl:apply-templates /></pre><br/>
+    <div class="bascode" itemscope="true" 
itemtype="http://schema.org/SoftwareSourceCode"; itemprop="codeSampleType" 
content="snippet"><pre><code class="language-visual-basic 
line-numbers"><xsl:apply-templates mode="embedded" /></code></pre></div>
 </xsl:template>
 
 <!-- Insert Logo code snippet  -->
diff --git a/help3xsl/prism.css b/help3xsl/prism.css
new file mode 100644
index 000000000..6e31d4d8f
--- /dev/null
+++ b/help3xsl/prism.css
@@ -0,0 +1,270 @@
+/* PrismJS 1.15.0
+https://prismjs.com/download.html#themes=prism-coy&languages=markup+css+clike+javascript+python+visual-basic&plugins=line-numbers+normalize-whitespace
 */
+/**
+ * prism.js Coy theme for JavaScript, CoffeeScript, CSS and HTML
+ * Based on https://github.com/tshedor/workshop-wp-theme (Example: 
http://workshop.kansan.com/category/sessions/basics or 
http://workshop.timshedor.com/category/sessions/basics);
+ * @author Tim  Shedor
+ */
+
+code[class*="language-"],
+pre[class*="language-"] {
+       color: black;
+       background: none;
+       font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+       text-align: left;
+       white-space: pre;
+       word-spacing: normal;
+       word-break: normal;
+       word-wrap: normal;
+       line-height: 1.5;
+
+       -moz-tab-size: 4;
+       -o-tab-size: 4;
+       tab-size: 4;
+
+       -webkit-hyphens: none;
+       -moz-hyphens: none;
+       -ms-hyphens: none;
+       hyphens: none;
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+       position: relative;
+       margin: .5em 0;
+       overflow: visible;
+       padding: 0;
+}
+pre[class*="language-"]>code {
+       position: relative;
+       border-left: 10px solid #358ccb;
+       box-shadow: -1px 0px 0px 0px #358ccb, 0px 0px 0px 1px #dfdfdf;
+       background-color: #fdfdfd;
+       background-image: linear-gradient(transparent 50%, rgba(69, 142, 209, 
0.04) 50%);
+       background-size: 3em 3em;
+       background-origin: content-box;
+       background-attachment: local;
+}
+
+code[class*="language"] {
+       max-height: inherit;
+       height: inherit;
+       padding: 0 1em;
+       display: block;
+       overflow: auto;
+}
+
+/* Margin bottom to accommodate shadow */
+:not(pre) > code[class*="language-"],
+pre[class*="language-"] {
+       background-color: #fdfdfd;
+       -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+       box-sizing: border-box;
+       margin-bottom: 1em;
+}
+
+/* Inline code */
+:not(pre) > code[class*="language-"] {
+       position: relative;
+       padding: .2em;
+       border-radius: 0.3em;
+       color: #c92c2c;
+       border: 1px solid rgba(0, 0, 0, 0.1);
+       display: inline;
+       white-space: normal;
+}
+
+pre[class*="language-"]:before,
+pre[class*="language-"]:after {
+       content: '';
+       z-index: -2;
+       display: block;
+       position: absolute;
+       bottom: 0.75em;
+       left: 0.18em;
+       width: 40%;
+       height: 20%;
+       max-height: 13em;
+       box-shadow: 0px 13px 8px #979797;
+       -webkit-transform: rotate(-2deg);
+       -moz-transform: rotate(-2deg);
+       -ms-transform: rotate(-2deg);
+       -o-transform: rotate(-2deg);
+       transform: rotate(-2deg);
+}
+
+:not(pre) > code[class*="language-"]:after,
+pre[class*="language-"]:after {
+       right: 0.75em;
+       left: auto;
+       -webkit-transform: rotate(2deg);
+       -moz-transform: rotate(2deg);
+       -ms-transform: rotate(2deg);
+       -o-transform: rotate(2deg);
+       transform: rotate(2deg);
+}
+
+.token.comment,
+.token.block-comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+       color: #7D8B99;
+}
+
+.token.punctuation {
+       color: #5F6364;
+}
+
+.token.property,
+.token.tag,
+.token.boolean,
+.token.number,
+.token.function-name,
+.token.constant,
+.token.symbol,
+.token.deleted {
+       color: #c92c2c;
+}
+
+.token.selector,
+.token.attr-name,
+.token.string,
+.token.char,
+.token.function,
+.token.builtin,
+.token.inserted {
+       color: #2f9c0a;
+}
+
+.token.operator,
+.token.entity,
+.token.url,
+.token.variable {
+       color: #a67f59;
+       background: rgba(255, 255, 255, 0.5);
+}
+
+.token.atrule,
+.token.attr-value,
+.token.keyword,
+.token.class-name {
+       color: #1990b8;
+}
+
+.token.regex,
+.token.important {
+       color: #e90;
+}
+
+.language-css .token.string,
+.style .token.string {
+       color: #a67f59;
+       background: rgba(255, 255, 255, 0.5);
+}
+
+.token.important {
+       font-weight: normal;
+}
+
+.token.bold {
+       font-weight: bold;
+}
+.token.italic {
+       font-style: italic;
+}
+
+.token.entity {
+       cursor: help;
+}
+
+.namespace {
+       opacity: .7;
+}
+
+@media screen and (max-width: 767px) {
+       pre[class*="language-"]:before,
+       pre[class*="language-"]:after {
+               bottom: 14px;
+               box-shadow: none;
+       }
+
+}
+
+/* Plugin styles */
+.token.tab:not(:empty):before,
+.token.cr:before,
+.token.lf:before {
+       color: #e0d7d1;
+}
+
+/* Plugin styles: Line Numbers */
+pre[class*="language-"].line-numbers.line-numbers {
+       padding-left: 0;
+}
+
+pre[class*="language-"].line-numbers.line-numbers code {
+       padding-left: 3.8em;
+}
+
+pre[class*="language-"].line-numbers.line-numbers .line-numbers-rows {
+       left: 0;
+}
+
+/* Plugin styles: Line Highlight */
+pre[class*="language-"][data-line] {
+       padding-top: 0;
+       padding-bottom: 0;
+       padding-left: 0;
+}
+pre[data-line] code {
+       position: relative;
+       padding-left: 4em;
+}
+pre .line-highlight {
+       margin-top: 0;
+}
+
+pre[class*="language-"].line-numbers {
+       position: relative;
+       padding-left: 3.8em;
+       counter-reset: linenumber;
+}
+
+pre[class*="language-"].line-numbers > code {
+       position: relative;
+       white-space: inherit;
+}
+
+.line-numbers .line-numbers-rows {
+       position: absolute;
+       pointer-events: none;
+       top: 0;
+       font-size: 100%;
+       left: -3.8em;
+       width: 3em; /* works for line-numbers below 1000 lines */
+       letter-spacing: -1px;
+       border-right: 1px solid #999;
+
+       -webkit-user-select: none;
+       -moz-user-select: none;
+       -ms-user-select: none;
+       user-select: none;
+
+}
+
+       .line-numbers-rows > span {
+               pointer-events: none;
+               display: block;
+               counter-increment: linenumber;
+       }
+
+               .line-numbers-rows > span:before {
+                       content: counter(linenumber);
+                       color: #999;
+                       display: block;
+                       padding-right: 0.8em;
+                       text-align: right;
+               }
+
diff --git a/help3xsl/prism.js b/help3xsl/prism.js
new file mode 100644
index 000000000..c085b09b0
--- /dev/null
+++ b/help3xsl/prism.js
@@ -0,0 +1,1190 @@
+/* PrismJS 1.15.0
+https://prismjs.com/download.html#themes=prism-coy&languages=markup+css+clike+javascript+python+visual-basic&plugins=line-numbers+normalize-whitespace
 */
+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,
+       disableWorkerMessageHandler: _self.Prism && 
_self.Prism.disableWorkerMessageHandler,
+       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, 
'&amp;').replace(/</g, '&lt;').replace(/\u00a0/g, ' ');
+                       }
+               },
+
+               type: function (o) {
+                       return Object.prototype.toString.call(o).slice(8, -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, visited) {
+                       var type = _.util.type(o);
+                       visited = visited || {};
+
+                       switch (type) {
+                               case 'Object':
+                                       if (visited[_.util.objId(o)]) {
+                                               return visited[_.util.objId(o)];
+                                       }
+                                       var clone = {};
+                                       visited[_.util.objId(o)] = clone;
+
+                                       for (var key in o) {
+                                               if (o.hasOwnProperty(key)) {
+                                                       clone[key] = 
_.util.clone(o[key], visited);
+                                               }
+                                       }
+
+                                       return clone;
+
+                               case 'Array':
+                                       if (visited[_.util.objId(o)]) {
+                                               return visited[_.util.objId(o)];
+                                       }
+                                       var clone = [];
+                                       visited[_.util.objId(o)] = clone;
+
+                                       o.forEach(function (v, i) {
+                                               clone[i] = _.util.clone(v, 
visited);
+                                       });
+
+                                       return clone;
+                       }
+
+                       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];
+                               }
+                       }
+
+                       var old = root[inside];
+                       root[inside] = ret;
+
+                       // Update references in other language definitions
+                       _.languages.DFS(_.languages, function(key, value) {
+                               if (value === old && key != inside) {
+                                       this[key] = ret;
+                               }
+                       });
+
+                       return 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) {
+               _.highlightAllUnder(document, async, callback);
+       },
+
+       highlightAllUnder: function(container, 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 || 
container.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;
+
+               if (element.parentNode) {
+                       // 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;
+
+                               _.hooks.run('after-highlight', env);
+                               _.hooks.run('complete', env);
+                               callback && callback.call(env.element);
+                       };
+
+                       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;
+
+                       _.hooks.run('after-highlight', env);
+
+                       _.hooks.run('complete', env);
+
+                       callback && callback.call(element);
+               }
+       },
+
+       highlight: function (text, grammar, language) {
+               var env = {
+                       code: text,
+                       grammar: grammar,
+                       language: language
+               };
+               _.hooks.run('before-tokenize', env);
+               env.tokens = _.tokenize(env.code, env.grammar);
+               _.hooks.run('after-tokenize', env);
+               return Token.stringify(_.util.encode(env.tokens), env.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;
+                                       }
+
+                                       if (greedy && i != strarr.length - 1) {
+                                               pattern.lastIndex = pos;
+                                               var 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[i] instanceof Token) 
{
+                                                       continue;
+                                               }
+
+                                               // Number of tokens to delete 
and replace with the new match
+                                               delNum = k - i;
+                                               str = text.slice(pos, p);
+                                               match.index -= pos;
+                                       } else {
+                                               pattern.lastIndex = 0;
+
+                                               var match = pattern.exec(str),
+                                                       delNum = 1;
+                                       }
+
+                                       if (!match) {
+                                               if (oneshot) {
+                                                       break;
+                                               }
+
+                                               continue;
+                                       }
+
+                                       if(lookbehind) {
+                                               lookbehindLength = match[1] ? 
match[1].length : 0;
+                                       }
+
+                                       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 (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, 
'&quot;') + '"';
+       }).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;
+       }
+
+       if (!_.disableWorkerMessageHandler) {
+               // 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 (!_.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.markup = {
+       'comment': /<!--[\s\S]*?-->/,
+       'prolog': /<\?[\s\S]+?\?>/,
+       'doctype': /<!DOCTYPE[\s\S]+?>/i,
+       'cdata': /<!\[CDATA\[[\s\S]*?]]>/i,
+       'tag': {
+               pattern: 
/<\/?(?!\d)[^\s>\/=$<%]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i,
+               greedy: true,
+               inside: {
+                       'tag': {
+                               pattern: /^<\/?[^\s>\/]+/i,
+                               inside: {
+                                       'punctuation': /^<\/?/,
+                                       'namespace': /^[^\s>\/:]+:/
+                               }
+                       },
+                       'attr-value': {
+                               pattern: 
/=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+)/i,
+                               inside: {
+                                       'punctuation': [
+                                               /^=/,
+                                               {
+                                                       pattern: 
/(^|[^\\])["']/,
+                                                       lookbehind: true
+                                               }
+                                       ]
+                               }
+                       },
+                       'punctuation': /\/?>/,
+                       'attr-name': {
+                               pattern: /[^\s>\/]+/,
+                               inside: {
+                                       'namespace': /^[^\s>\/:]+:/
+                               }
+                       }
+
+               }
+       },
+       'entity': /&#?[\da-z]{1,8};/i
+};
+
+Prism.languages.markup['tag'].inside['attr-value'].inside['entity'] =
+       Prism.languages.markup['entity'];
+
+// Plugin to make entity title show the real entity, idea by Roman Komarov
+Prism.hooks.add('wrap', function(env) {
+
+       if (env.type === 'entity') {
+               env.attributes['title'] = env.content.replace(/&amp;/, '&');
+       }
+});
+
+Prism.languages.xml = Prism.languages.markup;
+Prism.languages.html = Prism.languages.markup;
+Prism.languages.mathml = Prism.languages.markup;
+Prism.languages.svg = Prism.languages.markup;
+
+Prism.languages.css = {
+       'comment': /\/\*[\s\S]*?\*\//,
+       'atrule': {
+               pattern: /@[\w-]+?.*?(?:;|(?=\s*\{))/i,
+               inside: {
+                       'rule': /@[\w-]+/
+                       // See rest below
+               }
+       },
+       'url': /url\((?:(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,
+       'selector': /[^{}\s][^{};]*?(?=\s*\{)/,
+       'string': {
+               pattern: /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
+               greedy: true
+       },
+       'property': /[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,
+       'important': /!important\b/i,
+       'function': /[-a-z0-9]+(?=\()/i,
+       'punctuation': /[(){};:]/
+};
+
+Prism.languages.css['atrule'].inside.rest = Prism.languages.css;
+
+if (Prism.languages.markup) {
+       Prism.languages.insertBefore('markup', 'tag', {
+               'style': {
+                       pattern: /(<style[\s\S]*?>)[\s\S]*?(?=<\/style>)/i,
+                       lookbehind: true,
+                       inside: Prism.languages.css,
+                       alias: 'language-css',
+                       greedy: true
+               }
+       });
+
+       Prism.languages.insertBefore('inside', 'attr-value', {
+               'style-attr': {
+                       pattern: /\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,
+                       inside: {
+                               'attr-name': {
+                                       pattern: /^\s*style/i,
+                                       inside: 
Prism.languages.markup.tag.inside
+                               },
+                               'punctuation': /^\s*=\s*['"]|['"]\s*$/,
+                               'attr-value': {
+                                       pattern: /.+/i,
+                                       inside: Prism.languages.css
+                               }
+                       },
+                       alias: 'language-css'
+               }
+       }, Prism.languages.markup.tag);
+}
+;
+Prism.languages.clike = {
+       'comment': [
+               {
+                       pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,
+                       lookbehind: true
+               },
+               {
+                       pattern: /(^|[^\\:])\/\/.*/,
+                       lookbehind: true,
+                       greedy: 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+\())[\w.\\]+/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': /\w+(?=\()/,
+       'number': /\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,
+       'operator': /--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,
+       'punctuation': /[{}[\];(),.:]/
+};
+
+Prism.languages.javascript = Prism.languages.extend('clike', {
+       'class-name': [
+               Prism.languages.clike['class-name'],
+               {
+                       pattern: 
/(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/,
+                       lookbehind: true
+               }
+       ],
+       'keyword': [
+               {
+                       pattern: /((?:^|})\s*)(?:catch|finally)\b/,
+                       lookbehind: true
+               },
+               
/\b(?:as|async|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/
+       ],
+       'number': 
/\b(?:(?:0[xX][\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+)n?|\d+n|NaN|Infinity)\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee][+-]?\d+)?/,
+       // Allow for all non-ASCII characters (See 
http://stackoverflow.com/a/2008444)
+       'function': 
/[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*\(|\.(?:apply|bind|call)\()/,
+       'operator': 
/-[-=]?|\+[+=]?|!=?=?|<<?=?|>>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/
+});
+
+Prism.languages.javascript['class-name'][0].pattern = 
/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/
+
+Prism.languages.insertBefore('javascript', 'keyword', {
+       'regex': {
+               pattern: 
/((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(\[[^\]\r\n]+]|\\.|[^/\\\[\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})\]]))/,
+               lookbehind: true,
+               greedy: true
+       },
+       // This must be declared before keyword because we use "function" 
inside the look-forward
+       'function-variable': {
+               pattern: 
/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:function\b|(?:\([^()]*\)|[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/i,
+               alias: 'function'
+       },
+       'constant': /\b[A-Z][A-Z\d_]*\b/
+});
+
+Prism.languages.insertBefore('javascript', 'string', {
+       'template-string': {
+               pattern: /`(?:\\[\s\S]|\${[^}]+}|[^\\`])*`/,
+               greedy: true,
+               inside: {
+                       'interpolation': {
+                               pattern: /\${[^}]+}/,
+                               inside: {
+                                       'interpolation-punctuation': {
+                                               pattern: /^\${|}$/,
+                                               alias: 'punctuation'
+                                       },
+                                       rest: Prism.languages.javascript
+                               }
+                       },
+                       'string': /[\s\S]+/
+               }
+       }
+});
+
+if (Prism.languages.markup) {
+       Prism.languages.insertBefore('markup', 'tag', {
+               'script': {
+                       pattern: /(<script[\s\S]*?>)[\s\S]*?(?=<\/script>)/i,
+                       lookbehind: true,
+                       inside: Prism.languages.javascript,
+                       alias: 'language-javascript',
+                       greedy: true
+               }
+       });
+}
+
+Prism.languages.js = Prism.languages.javascript;
+
+Prism.languages.python = {
+       'comment': {
+               pattern: /(^|[^\\])#.*/,
+               lookbehind: true
+       },
+       'triple-quoted-string': {
+               pattern: /("""|''')[\s\S]+?\1/,
+               greedy: true,
+               alias: 'string'
+       },
+       'string': {
+               pattern: /("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,
+               greedy: true
+       },
+       'function': {
+               pattern: /((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,
+               lookbehind: true
+       },
+       'class-name': {
+               pattern: /(\bclass\s+)\w+/i,
+               lookbehind: true
+       },
+       'keyword': 
/\b(?:and|as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,
+       
'builtin':/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,
+       'boolean': /\b(?:True|False|None)\b/,
+       'number': 
/(?:\b(?=\d)|\B(?=\.))(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*\.?\d*|\.\d+)(?:e[+-]?\d+)?j?\b/i,
+       'operator': /[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,
+       'punctuation': /[{}[\];(),.:]/
+};
+
+Prism.languages['visual-basic'] = {
+       'comment': {
+               pattern: /(?:['‘’]|REM\b).*/i,
+               inside: {
+                       'keyword': /^REM/i
+               }
+       },
+       'directive': {
+               pattern: 
/#(?:Const|Else|ElseIf|End|ExternalChecksum|ExternalSource|If|Region)(?:[^\S\r\n]_[^\S\r\n]*(?:\r\n?|\n)|.)+/i,
+               alias: 'comment',
+               greedy: true
+       },
+       'string': {
+               pattern: /["“”](?:["“”]{2}|[^"“”])*["“”]C?/i,
+               greedy: true
+       },
+       'date': {
+               pattern: 
/#[^\S\r\n]*(?:\d+([/-])\d+\1\d+(?:[^\S\r\n]+(?:\d+[^\S\r\n]*(?:AM|PM)|\d+:\d+(?::\d+)?(?:[^\S\r\n]*(?:AM|PM))?))?|(?:\d+[^\S\r\n]*(?:AM|PM)|\d+:\d+(?::\d+)?(?:[^\S\r\n]*(?:AM|PM))?))[^\S\r\n]*#/i,
+               alias: 'builtin'
+       },
+       'number': 
/(?:(?:\b\d+(?:\.\d+)?|\.\d+)(?:E[+-]?\d+)?|&[HO][\dA-F]+)(?:U?[ILS]|[FRD])?/i,
+       'boolean': /\b(?:True|False|Nothing)\b/i,
+       'keyword': 
/\b(?:AddHandler|AddressOf|Alias|And(?:Also)?|As|Boolean|ByRef|Byte|ByVal|Call|Case|Catch|C(?:Bool|Byte|Char|Date|Dbl|Dec|Int|Lng|Obj|SByte|Short|Sng|Str|Type|UInt|ULng|UShort)|Char|Class|Const|Continue|Date|Decimal|Declare|Default|Delegate|Dim|DirectCast|Do|Double|Each|Else(?:If)?|End(?:If)?|Enum|Erase|Error|Event|Exit|Finally|For|Friend|Function|Get(?:Type|XMLNamespace)?|Global|GoSub|GoTo|Handles|If|Implements|Imports|In|Inherits|Integer|Interface|Is|IsNot|Let|Lib|Like|Long|Loop|Me|Mod|Module|Must(?:Inherit|Override)|My(?:Base|Class)|Namespace|Narrowing|New|Next|Not(?:Inheritable|Overridable)?|Object|Of|On|Operator|Option(?:al)?|Or(?:Else)?|Out|Overloads|Overridable|Overrides|ParamArray|Partial|Private|Property|Protected|Public|RaiseEvent|ReadOnly|ReDim|RemoveHandler|Resume|Return|SByte|Select|Set|Shadows|Shared|short|Single|Static|Step|Stop|String|Structure|Sub|SyncLock|Then|Throw|To|Try|TryCast|TypeOf|U(?:Integer|Long|Short)|Using|Variant|Wend|When|While|Widening|Wit
 h(?:Events)?|WriteOnly|Xor)\b/i,
+       'operator': [
+               /[+\-*/\\^<=>&#@$%!]/,
+               {
+                       pattern: /([^\S\r\n])_(?=[^\S\r\n]*[\r\n])/,
+                       lookbehind: true
+               }
+       ],
+       'punctuation': /[{}().,:?]/
+};
+
+Prism.languages.vb = Prism.languages['visual-basic'];
+(function () {
+
+       if (typeof self === 'undefined' || !self.Prism || !self.document) {
+               return;
+       }
+
+       /**
+        * Plugin name which is used as a class name for <pre> which is 
activating the plugin
+        * @type {String}
+        */
+       var PLUGIN_NAME = 'line-numbers';
+
+       /**
+        * Regular expression used for determining line breaks
+        * @type {RegExp}
+        */
+       var NEW_LINE_EXP = /\n(?!$)/g;
+
+       /**
+        * Resizes line numbers spans according to height of line of code
+        * @param {Element} element <pre> element
+        */
+       var _resizeElement = function (element) {
+               var codeStyles = getStyles(element);
+               var whiteSpace = codeStyles['white-space'];
+
+               if (whiteSpace === 'pre-wrap' || whiteSpace === 'pre-line') {
+                       var codeElement = element.querySelector('code');
+                       var lineNumbersWrapper = 
element.querySelector('.line-numbers-rows');
+                       var lineNumberSizer = 
element.querySelector('.line-numbers-sizer');
+                       var codeLines = 
codeElement.textContent.split(NEW_LINE_EXP);
+
+                       if (!lineNumberSizer) {
+                               lineNumberSizer = 
document.createElement('span');
+                               lineNumberSizer.className = 
'line-numbers-sizer';
+
+                               codeElement.appendChild(lineNumberSizer);
+                       }
+
+                       lineNumberSizer.style.display = 'block';
+
+                       codeLines.forEach(function (line, lineNumber) {
+                               lineNumberSizer.textContent = line || '\n';
+                               var lineSize = 
lineNumberSizer.getBoundingClientRect().height;
+                               
lineNumbersWrapper.children[lineNumber].style.height = lineSize + 'px';
+                       });
+
+                       lineNumberSizer.textContent = '';
+                       lineNumberSizer.style.display = 'none';
+               }
+       };
+
+       /**
+        * Returns style declarations for the element
+        * @param {Element} element
+        */
+       var getStyles = function (element) {
+               if (!element) {
+                       return null;
+               }
+
+               return window.getComputedStyle ? getComputedStyle(element) : 
(element.currentStyle || null);
+       };
+
+       window.addEventListener('resize', function () {
+               Array.prototype.forEach.call(document.querySelectorAll('pre.' + 
PLUGIN_NAME), _resizeElement);
+       });
+
+       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(NEW_LINE_EXP);
+               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);
+
+               _resizeElement(pre);
+
+               Prism.hooks.run('line-numbers', env);
+       });
+
+       Prism.hooks.add('line-numbers', function (env) {
+               env.plugins = env.plugins || {};
+               env.plugins.lineNumbers = true;
+       });
+
+       /**
+        * Global exports
+        */
+       Prism.plugins.lineNumbers = {
+               /**
+                * Get node for provided line number
+                * @param {Element} element pre element
+                * @param {Number} number line number
+                * @return {Element|undefined}
+                */
+               getLine: function (element, number) {
+                       if (element.tagName !== 'PRE' || 
!element.classList.contains(PLUGIN_NAME)) {
+                               return;
+                       }
+
+                       var lineNumberRows = 
element.querySelector('.line-numbers-rows');
+                       var lineNumberStart = 
parseInt(element.getAttribute('data-start'), 10) || 1;
+                       var lineNumberEnd = lineNumberStart + 
(lineNumberRows.children.length - 1);
+
+                       if (number < lineNumberStart) {
+                               number = lineNumberStart;
+                       }
+                       if (number > lineNumberEnd) {
+                               number = lineNumberEnd;
+                       }
+
+                       var lineIndex = number - lineNumberStart;
+
+                       return lineNumberRows.children[lineIndex];
+               }
+       };
+
+}());
+(function() {
+
+var assign = Object.assign || function (obj1, obj2) {
+       for (var name in obj2) {
+               if (obj2.hasOwnProperty(name))
+                       obj1[name] = obj2[name];
+       }
+       return obj1;
+}
+
+function NormalizeWhitespace(defaults) {
+       this.defaults = assign({}, defaults);
+}
+
+function toCamelCase(value) {
+       return value.replace(/-(\w)/g, function(match, firstChar) {
+               return firstChar.toUpperCase();
+       });
+}
+
+function tabLen(str) {
+       var res = 0;
+       for (var i = 0; i < str.length; ++i) {
+               if (str.charCodeAt(i) == '\t'.charCodeAt(0))
+                       res += 3;
+       }
+       return str.length + res;
+}
+
+NormalizeWhitespace.prototype = {
+       setDefaults: function (defaults) {
+               this.defaults = assign(this.defaults, defaults);
+       },
+       normalize: function (input, settings) {
+               settings = assign(this.defaults, settings);
+
+               for (var name in settings) {
+                       var methodName = toCamelCase(name);
+                       if (name !== "normalize" && methodName !== 
'setDefaults' &&
+                                       settings[name] && this[methodName]) {
+                               input = this[methodName].call(this, input, 
settings[name]);
+                       }
+               }
+
+               return input;
+       },
+
+       /*
+        * Normalization methods
+        */
+       leftTrim: function (input) {
+               return input.replace(/^\s+/, '');
+       },
+       rightTrim: function (input) {
+               return input.replace(/\s+$/, '');
+       },
+       tabsToSpaces: function (input, spaces) {
+               spaces = spaces|0 || 4;
+               return input.replace(/\t/g, new Array(++spaces).join(' '));
+       },
+       spacesToTabs: function (input, spaces) {
+               spaces = spaces|0 || 4;
+               return input.replace(RegExp(' {' + spaces + '}', 'g'), '\t');
+       },
+       removeTrailing: function (input) {
+               return input.replace(/\s*?$/gm, '');
+       },
+       // Support for deprecated plugin remove-initial-line-feed
+       removeInitialLineFeed: function (input) {
+               return input.replace(/^(?:\r?\n|\r)/, '');
+       },
+       removeIndent: function (input) {
+               var indents = input.match(/^[^\S\n\r]*(?=\S)/gm);
+
+               if (!indents || !indents[0].length)
+                       return input;
+
+               indents.sort(function(a, b){return a.length - b.length; });
+
+               if (!indents[0].length)
+                       return input;
+
+               return input.replace(RegExp('^' + indents[0], 'gm'), '');
+       },
+       indent: function (input, tabs) {
+               return input.replace(/^[^\S\n\r]*(?=\S)/gm, new 
Array(++tabs).join('\t') + '$&');
+       },
+       breakLines: function (input, characters) {
+               characters = (characters === true) ? 80 : characters|0 || 80;
+
+               var lines = input.split('\n');
+               for (var i = 0; i < lines.length; ++i) {
+                       if (tabLen(lines[i]) <= characters)
+                               continue;
+
+                       var line = lines[i].split(/(\s+)/g),
+                           len = 0;
+
+                       for (var j = 0; j < line.length; ++j) {
+                               var tl = tabLen(line[j]);
+                               len += tl;
+                               if (len > characters) {
+                                       line[j] = '\n' + line[j];
+                                       len = tl;
+                               }
+                       }
+                       lines[i] = line.join('');
+               }
+               return lines.join('\n');
+       }
+};
+
+// Support node modules
+if (typeof module !== 'undefined' && module.exports) {
+       module.exports = NormalizeWhitespace;
+}
+
+// Exit if prism is not loaded
+if (typeof Prism === 'undefined') {
+       return;
+}
+
+Prism.plugins.NormalizeWhitespace = new NormalizeWhitespace({
+       'remove-trailing': true,
+       'remove-indent': true,
+       'left-trim': true,
+       'right-trim': true,
+       /*'break-lines': 80,
+       'indent': 2,*/
+       'remove-initial-line-feed': true,
+       /*'tabs-to-spaces': 4,
+       'spaces-to-tabs': 4*/
+});
+
+Prism.hooks.add('before-sanity-check', function (env) {
+       var Normalizer = Prism.plugins.NormalizeWhitespace;
+
+       // Check settings
+       if (env.settings && env.settings['whitespace-normalization'] === false) 
{
+               return;
+       }
+
+       // Simple mode if there is no env.element
+       if ((!env.element || !env.element.parentNode) && env.code) {
+               env.code = Normalizer.normalize(env.code, env.settings);
+               return;
+       }
+
+       // Normal mode
+       var pre = env.element.parentNode;
+       var clsReg = /\bno-whitespace-normalization\b/;
+       if (!env.code || !pre || pre.nodeName.toLowerCase() !== 'pre' ||
+                       clsReg.test(pre.className) || 
clsReg.test(env.element.className))
+               return;
+
+       var children = pre.childNodes,
+           before = '',
+           after = '',
+           codeFound = false;
+
+       // Move surrounding whitespace from the <pre> tag into the <code> tag
+       for (var i = 0; i < children.length; ++i) {
+               var node = children[i];
+
+               if (node == env.element) {
+                       codeFound = true;
+               } else if (node.nodeName === "#text") {
+                       if (codeFound) {
+                               after += node.nodeValue;
+                       } else {
+                               before += node.nodeValue;
+                       }
+
+                       pre.removeChild(node);
+                       --i;
+               }
+       }
+
+       if (!env.element.children.length || !Prism.plugins.KeepMarkup) {
+               env.code = before + env.code + after;
+               env.code = Normalizer.normalize(env.code, env.settings);
+       } else {
+               // Preserve markup for keep-markup plugin
+               var html = before + env.element.innerHTML + after;
+               env.element.innerHTML = Normalizer.normalize(html, 
env.settings);
+               env.code = env.element.textContent;
+       }
+});
+
+}());
+
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to