summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Hallot <olivier.hallot@libreoffice.org>2020-05-29 16:45:56 -0300
committerOlivier Hallot <olivier.hallot@libreoffice.org>2020-06-03 14:32:34 +0200
commitebbd4ee99be8172c6c62b8d6963feb7f7b72bfa1 (patch)
tree7d91af4eb85749fbe90d2950ffdd2ff0dcf182a9
parent1369142eae32576f15bc82c59406850a32576fb1 (diff)
Update prism.js to latest version
Update prism.js and companion css to latest version Fixes the Currency and Type keyword highlight Fixes line numbering interference with a11y-toggle.js Change-Id: Ibbb5c95790e1366f0a1dbc497d8741e69a0a3957 Reviewed-on: https://gerrit.libreoffice.org/c/help/+/95173 Tested-by: Jenkins Reviewed-by: Olivier Hallot <olivier.hallot@libreoffice.org> (cherry picked from commit 0c721f4ecf55911d125e33e3afea534d1ffe42b2) Reviewed-on: https://gerrit.libreoffice.org/c/help/+/95129 Reviewed-by: Ilmari Lauhakangas <ilmari.lauhakangas@libreoffice.org>
-rw-r--r--help3xsl/README.prism.js.txt5
-rw-r--r--help3xsl/default.css7
-rw-r--r--help3xsl/prism.css6
-rw-r--r--help3xsl/prism.js1069
4 files changed, 711 insertions, 376 deletions
diff --git a/help3xsl/README.prism.js.txt b/help3xsl/README.prism.js.txt
index 581a1fe71c..fe0acc0d2b 100644
--- a/help3xsl/README.prism.js.txt
+++ b/help3xsl/README.prism.js.txt
@@ -1,3 +1,7 @@
+Latest download version
+
+PrismJS 1.20.0
+
Using prism.js for Basic code highlight
http://prismjs.com
@@ -37,3 +41,4 @@ Add class 'language-visual-basic' and 'line-numbers' to <code> as in
<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 0ae386088a..76bf71c666 100644
--- a/help3xsl/default.css
+++ b/help3xsl/default.css
@@ -361,10 +361,11 @@ header {
height: 60px;
margin-right: 10px;
}
-[aria-hidden='true'],
-[data-a11y-toggle]:not([aria-controls]) {
+
+[data-a11y-toggle]:not([aria-controls]){
display: none;
}
+
#langs-nav:not([aria-hidden='true']), #modules-nav:not([aria-hidden='true']) {
z-index: 100;
/* line them up horizontally */
@@ -739,7 +740,7 @@ li.disabled a {
}
}
@media screen and (min-width: 960px) {
- #langs-nav {
+ #langs-nav, #modules-nav {
display: none;
}
#langs-nav a {
diff --git a/help3xsl/prism.css b/help3xsl/prism.css
index 6e31d4d8fa..8bd96d9cc3 100644
--- a/help3xsl/prism.css
+++ b/help3xsl/prism.css
@@ -1,4 +1,4 @@
-/* PrismJS 1.15.0
+/* PrismJS 1.20.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
@@ -11,6 +11,7 @@ pre[class*="language-"] {
color: black;
background: none;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+ font-size: 1em;
text-align: left;
white-space: pre;
word-spacing: normal;
@@ -179,7 +180,7 @@ pre[class*="language-"]:after {
cursor: help;
}
-.namespace {
+.token.namespace {
opacity: .7;
}
@@ -255,7 +256,6 @@ pre[class*="language-"].line-numbers > code {
}
.line-numbers-rows > span {
- pointer-events: none;
display: block;
counter-increment: linenumber;
}
diff --git a/help3xsl/prism.js b/help3xsl/prism.js
index c085b09b00..1080118885 100644
--- a/help3xsl/prism.js
+++ b/help3xsl/prism.js
@@ -1,4 +1,4 @@
-/* PrismJS 1.15.0
+/* PrismJS 1.20.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
@@ -14,21 +14,22 @@ var _self = (typeof window !== 'undefined')
* @author Lea Verou http://lea.verou.me
*/
-var Prism = (function(){
+var Prism = (function (_self){
// Private helper vars
var lang = /\blang(?:uage)?-([\w-]+)\b/i;
var uniqueId = 0;
-var _ = _self.Prism = {
+
+var _ = {
manual: _self.Prism && _self.Prism.manual,
disableWorkerMessageHandler: _self.Prism && _self.Prism.disableWorkerMessageHandler,
util: {
- encode: function (tokens) {
+ encode: function encode(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);
+ return new Token(tokens.type, encode(tokens.content), tokens.alias);
+ } else if (Array.isArray(tokens)) {
+ return tokens.map(encode);
} else {
return tokens.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/\u00a0/g, ' ');
}
@@ -46,41 +47,104 @@ var _ = _self.Prism = {
},
// Deep clone a language definition (e.g. to extend it)
- clone: function (o, visited) {
- var type = _.util.type(o);
+ clone: function deepClone(o, visited) {
+ var clone, id, type = _.util.type(o);
visited = visited || {};
switch (type) {
case 'Object':
- if (visited[_.util.objId(o)]) {
- return visited[_.util.objId(o)];
+ id = _.util.objId(o);
+ if (visited[id]) {
+ return visited[id];
}
- var clone = {};
- visited[_.util.objId(o)] = clone;
+ clone = {};
+ visited[id] = clone;
for (var key in o) {
if (o.hasOwnProperty(key)) {
- clone[key] = _.util.clone(o[key], visited);
+ clone[key] = deepClone(o[key], visited);
}
}
return clone;
case 'Array':
- if (visited[_.util.objId(o)]) {
- return visited[_.util.objId(o)];
+ id = _.util.objId(o);
+ if (visited[id]) {
+ return visited[id];
}
- var clone = [];
- visited[_.util.objId(o)] = clone;
+ clone = [];
+ visited[id] = clone;
o.forEach(function (v, i) {
- clone[i] = _.util.clone(v, visited);
+ clone[i] = deepClone(v, visited);
});
return clone;
+
+ default:
+ return o;
}
+ },
- return o;
+ /**
+ * Returns the Prism language of the given element set by a `language-xxxx` or `lang-xxxx` class.
+ *
+ * If no language is set for the element or the element is `null` or `undefined`, `none` will be returned.
+ *
+ * @param {Element} element
+ * @returns {string}
+ */
+ getLanguage: function (element) {
+ while (element && !lang.test(element.className)) {
+ element = element.parentElement;
+ }
+ if (element) {
+ return (element.className.match(lang) || [, 'none'])[1].toLowerCase();
+ }
+ return 'none';
+ },
+
+ /**
+ * Returns the script element that is currently executing.
+ *
+ * This does __not__ work for line script element.
+ *
+ * @returns {HTMLScriptElement | null}
+ */
+ currentScript: function () {
+ if (typeof document === 'undefined') {
+ return null;
+ }
+ if ('currentScript' in document) {
+ return document.currentScript;
+ }
+
+ // IE11 workaround
+ // we'll get the src of the current script by parsing IE11's error stack trace
+ // this will not work for inline scripts
+
+ try {
+ throw new Error();
+ } catch (err) {
+ // Get file src url from stack. Specifically works with the format of stack traces in IE.
+ // A stack will look like this:
+ //
+ // Error
+ // at _.util.currentScript (http://localhost/components/prism-core.js:119:5)
+ // at Global code (http://localhost/components/prism-core.js:606:1)
+
+ var src = (/at [^(\r\n]*\((.*):.+:.+\)$/i.exec(err.stack) || [])[1];
+ if (src) {
+ var scripts = document.getElementsByTagName('script');
+ for (var i in scripts) {
+ if (scripts[i].src == src) {
+ return scripts[i];
+ }
+ }
+ }
+ return null;
+ }
}
},
@@ -98,45 +162,32 @@ var _ = _self.Prism = {
/**
* 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.
+ * we cannot just provide an object, we need an object 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 before The key to insert before.
* @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];
+ // Do not insert token which also occur in insert. See #1525
+ if (!insert.hasOwnProperty(token)) {
+ ret[token] = grammar[token];
+ }
}
}
@@ -154,19 +205,25 @@ var _ = _self.Prism = {
},
// Traverse a language definition with Depth First Search
- DFS: function(o, callback, type, visited) {
+ DFS: function DFS(o, callback, type, visited) {
visited = visited || {};
+
+ var objId = _.util.objId;
+
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);
+ var property = o[i],
+ propertyType = _.util.type(property);
+
+ if (propertyType === 'Object' && !visited[objId(property)]) {
+ visited[objId(property)] = true;
+ DFS(property, 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);
+ else if (propertyType === 'Array' && !visited[objId(property)]) {
+ visited[objId(property)] = true;
+ DFS(property, callback, i, visited);
}
}
}
@@ -181,41 +238,33 @@ var _ = _self.Prism = {
highlightAllUnder: function(container, async, callback) {
var env = {
callback: callback,
+ container: container,
selector: 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'
};
- _.hooks.run("before-highlightall", env);
+ _.hooks.run('before-highlightall', env);
- var elements = env.elements || container.querySelectorAll(env.selector);
+ env.elements = Array.prototype.slice.apply(env.container.querySelectorAll(env.selector));
- for (var i=0, element; element = elements[i++];) {
+ _.hooks.run('before-all-elements-highlight', env);
+
+ for (var i = 0, element; element = env.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];
- }
+ var language = _.util.getLanguage(element);
+ var 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;
- }
+ // Set language on the parent, for styling
+ var parent = element.parentNode;
+ if (parent && parent.nodeName.toLowerCase() === 'pre') {
+ parent.className = parent.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language;
}
var code = element.textContent;
@@ -227,33 +276,38 @@ var _ = _self.Prism = {
code: code
};
+ function insertHighlightedCode(highlightedCode) {
+ env.highlightedCode = highlightedCode;
+
+ _.hooks.run('before-insert', env);
+
+ env.element.innerHTML = env.highlightedCode;
+
+ _.hooks.run('after-highlight', env);
+ _.hooks.run('complete', env);
+ callback && callback.call(env.element);
+ }
+
_.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);
- }
+ if (!env.code) {
_.hooks.run('complete', env);
+ callback && callback.call(env.element);
return;
}
_.hooks.run('before-highlight', env);
+ if (!env.grammar) {
+ insertHighlightedCode(_.util.encode(env.code));
+ return;
+ }
+
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);
+ insertHighlightedCode(evt.data);
};
worker.postMessage(JSON.stringify({
@@ -263,17 +317,7 @@ var _ = _self.Prism = {
}));
}
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);
+ insertHighlightedCode(_.highlight(env.code, env.grammar, env.language));
}
},
@@ -289,139 +333,8 @@ var _ = _self.Prism = {
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];
-
+ tokenize: function(text, grammar) {
var rest = grammar.rest;
-
if (rest) {
for (var token in rest) {
grammar[token] = rest[token];
@@ -430,9 +343,12 @@ var _ = _self.Prism = {
delete grammar.rest;
}
- _.matchGrammar(text, strarr, grammar, 0, 0, false);
+ var tokenList = new LinkedList();
+ addAfter(tokenList, tokenList.head, text);
+
+ matchGrammar(text, tokenList, grammar, tokenList.head, 0);
- return strarr;
+ return toArray(tokenList);
},
hooks: {
@@ -457,58 +373,290 @@ var _ = _self.Prism = {
callback(env);
}
}
- }
+ },
+
+ Token: Token
};
-var Token = _.Token = function(type, content, alias, matchedStr, greedy) {
+_self.Prism = _;
+
+function Token(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.length = (matchedStr || '').length|0;
this.greedy = !!greedy;
-};
+}
-Token.stringify = function(o, language, parent) {
+Token.stringify = function stringify(o, language) {
if (typeof o == 'string') {
return o;
}
-
- if (_.util.type(o) === 'Array') {
- return o.map(function(element) {
- return Token.stringify(element, language, o);
- }).join('');
+ if (Array.isArray(o)) {
+ var s = '';
+ o.forEach(function (e) {
+ s += stringify(e, language);
+ });
+ return s;
}
var env = {
type: o.type,
- content: Token.stringify(o.content, language, parent),
+ content: stringify(o.content, language),
tag: 'span',
classes: ['token', o.type],
attributes: {},
- language: language,
- parent: parent
+ language: language
};
- if (o.alias) {
- var aliases = _.util.type(o.alias) === 'Array' ? o.alias : [o.alias];
- Array.prototype.push.apply(env.classes, aliases);
+ var aliases = o.alias;
+ if (aliases) {
+ if (Array.isArray(aliases)) {
+ Array.prototype.push.apply(env.classes, aliases);
+ } else {
+ env.classes.push(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 + '>';
+ var attributes = '';
+ for (var name in env.attributes) {
+ attributes += ' ' + name + '="' + (env.attributes[name] || '').replace(/"/g, '&quot;') + '"';
+ }
+ return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + attributes + '>' + env.content + '</' + env.tag + '>';
};
+/**
+ * @param {string} text
+ * @param {LinkedList<string | Token>} tokenList
+ * @param {any} grammar
+ * @param {LinkedListNode<string | Token>} startNode
+ * @param {number} startPos
+ * @param {boolean} [oneshot=false]
+ * @param {string} [target]
+ */
+function matchGrammar(text, tokenList, grammar, startNode, startPos, oneshot, target) {
+ for (var token in grammar) {
+ if (!grammar.hasOwnProperty(token) || !grammar[token]) {
+ continue;
+ }
+
+ var patterns = grammar[token];
+ patterns = Array.isArray(patterns) ? patterns : [patterns];
+
+ for (var j = 0; j < patterns.length; ++j) {
+ if (target && target == token + ',' + j) {
+ return;
+ }
+
+ 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(/[imsuy]*$/)[0];
+ pattern.pattern = RegExp(pattern.pattern.source, flags + 'g');
+ }
+
+ pattern = pattern.pattern || pattern;
+
+ for ( // iterate the token list and keep track of the current token/string position
+ var currentNode = startNode.next, pos = startPos;
+ currentNode !== tokenList.tail;
+ pos += currentNode.value.length, currentNode = currentNode.next
+ ) {
+
+ var str = currentNode.value;
+
+ if (tokenList.length > text.length) {
+ // Something went terribly wrong, ABORT, ABORT!
+ return;
+ }
+
+ if (str instanceof Token) {
+ continue;
+ }
+
+ var removeCount = 1; // this is the to parameter of removeBetween
+
+ if (greedy && currentNode != tokenList.tail.prev) {
+ pattern.lastIndex = pos;
+ var match = pattern.exec(text);
+ if (!match) {
+ break;
+ }
+
+ var from = match.index + (lookbehind && match[1] ? match[1].length : 0);
+ var to = match.index + match[0].length;
+ var p = pos;
+
+ // find the node that contains the match
+ p += currentNode.value.length;
+ while (from >= p) {
+ currentNode = currentNode.next;
+ p += currentNode.value.length;
+ }
+ // adjust pos (and p)
+ p -= currentNode.value.length;
+ pos = p;
+
+ // the current node is a Token, then the match starts inside another Token, which is invalid
+ if (currentNode.value instanceof Token) {
+ continue;
+ }
+
+ // find the last node which is affected by this match
+ for (
+ var k = currentNode;
+ k !== tokenList.tail && (p < to || (typeof k.value === 'string' && !k.prev.value.greedy));
+ k = k.next
+ ) {
+ removeCount++;
+ p += k.value.length;
+ }
+ removeCount--;
+
+ // replace with the new match
+ str = text.slice(pos, p);
+ match.index -= pos;
+ } else {
+ pattern.lastIndex = 0;
+
+ var match = pattern.exec(str);
+ }
+
+ 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 removeFrom = currentNode.prev;
+
+ if (before) {
+ removeFrom = addAfter(tokenList, removeFrom, before);
+ pos += before.length;
+ }
+
+ removeRange(tokenList, removeFrom, removeCount);
+
+ var wrapped = new Token(token, inside ? _.tokenize(match, inside) : match, alias, match, greedy);
+ currentNode = addAfter(tokenList, removeFrom, wrapped);
+
+ if (after) {
+ addAfter(tokenList, currentNode, after);
+ }
+
+
+ if (removeCount > 1)
+ matchGrammar(text, tokenList, grammar, currentNode.prev, pos, true, token + ',' + j);
+
+ if (oneshot)
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * @typedef LinkedListNode
+ * @property {T} value
+ * @property {LinkedListNode<T> | null} prev The previous node.
+ * @property {LinkedListNode<T> | null} next The next node.
+ * @template T
+ */
+
+/**
+ * @template T
+ */
+function LinkedList() {
+ /** @type {LinkedListNode<T>} */
+ var head = { value: null, prev: null, next: null };
+ /** @type {LinkedListNode<T>} */
+ var tail = { value: null, prev: head, next: null };
+ head.next = tail;
+
+ /** @type {LinkedListNode<T>} */
+ this.head = head;
+ /** @type {LinkedListNode<T>} */
+ this.tail = tail;
+ this.length = 0;
+}
+
+/**
+ * Adds a new node with the given value to the list.
+ * @param {LinkedList<T>} list
+ * @param {LinkedListNode<T>} node
+ * @param {T} value
+ * @returns {LinkedListNode<T>} The added node.
+ * @template T
+ */
+function addAfter(list, node, value) {
+ // assumes that node != list.tail && values.length >= 0
+ var next = node.next;
+
+ var newNode = { value: value, prev: node, next: next };
+ node.next = newNode;
+ next.prev = newNode;
+ list.length++;
+
+ return newNode;
+}
+/**
+ * Removes `count` nodes after the given node. The given node will not be removed.
+ * @param {LinkedList<T>} list
+ * @param {LinkedListNode<T>} node
+ * @param {number} count
+ * @template T
+ */
+function removeRange(list, node, count) {
+ var next = node.next;
+ for (var i = 0; i < count && next !== list.tail; i++) {
+ next = next.next;
+ }
+ node.next = next;
+ next.prev = node;
+ list.length -= i;
+}
+/**
+ * @param {LinkedList<T>} list
+ * @returns {T[]}
+ * @template T
+ */
+function toArray(list) {
+ var array = [];
+ var node = list.head.next;
+ while (node !== list.tail) {
+ array.push(node.value);
+ node = node.next;
+ }
+ return array;
+}
+
+
if (!_self.document) {
if (!_self.addEventListener) {
// in Node.js
- return _self.Prism;
+ return _;
}
if (!_.disableWorkerMessageHandler) {
@@ -526,32 +674,48 @@ if (!_self.document) {
}, false);
}
- return _self.Prism;
+ return _;
}
//Get current script and highlight
-var script = document.currentScript || [].slice.call(document.getElementsByTagName("script")).pop();
+var script = _.util.currentScript();
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);
+ if (script.hasAttribute('data-manual')) {
+ _.manual = true;
+ }
+}
+
+function highlightAutomaticallyCallback() {
+ if (!_.manual) {
+ _.highlightAll();
+ }
+}
+
+if (!_.manual) {
+ // If the document state is "loading", then we'll use DOMContentLoaded.
+ // If the document state is "interactive" and the prism.js script is deferred, then we'll also use the
+ // DOMContentLoaded event because there might be some plugins or languages which have also been deferred and they
+ // might take longer one animation frame to execute which can create a race condition where only some plugins have
+ // been loaded when Prism.highlightAll() is executed, depending on how fast resources are loaded.
+ // See https://github.com/PrismJS/prism/issues/2102
+ var readyState = document.readyState;
+ if (readyState === 'loading' || readyState === 'interactive' && script && script.defer) {
+ document.addEventListener('DOMContentLoaded', highlightAutomaticallyCallback);
+ } else {
+ if (window.requestAnimationFrame) {
+ window.requestAnimationFrame(highlightAutomaticallyCallback);
+ } else {
+ window.setTimeout(highlightAutomaticallyCallback, 16);
}
}
}
-return _self.Prism;
+return _;
-})();
+})(_self);
if (typeof module !== 'undefined' && module.exports) {
module.exports = Prism;
@@ -565,28 +729,47 @@ if (typeof global !== 'undefined') {
Prism.languages.markup = {
'comment': /<!--[\s\S]*?-->/,
'prolog': /<\?[\s\S]+?\?>/,
- 'doctype': /<!DOCTYPE[\s\S]+?>/i,
+ 'doctype': {
+ // https://www.w3.org/TR/xml/#NT-doctypedecl
+ pattern: /<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,
+ greedy: true,
+ inside: {
+ 'internal-subset': {
+ pattern: /(\[)[\s\S]+(?=\]>$)/,
+ lookbehind: true,
+ greedy: true,
+ inside: null // see below
+ },
+ 'string': {
+ pattern: /"[^"]*"|'[^']*'/,
+ greedy: true
+ },
+ 'punctuation': /^<!|>$|[[\]]/,
+ 'doctype-tag': /^DOCTYPE/,
+ 'name': /[^\s<>'"]+/
+ }
+ },
'cdata': /<!\[CDATA\[[\s\S]*?]]>/i,
'tag': {
- pattern: /<\/?(?!\d)[^\s>\/=$<%]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i,
+ pattern: /<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,
greedy: true,
inside: {
'tag': {
- pattern: /^<\/?[^\s>\/]+/i,
+ pattern: /^<\/?[^\s>\/]+/,
inside: {
'punctuation': /^<\/?/,
'namespace': /^[^\s>\/:]+:/
}
},
'attr-value': {
- pattern: /=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+)/i,
+ pattern: /=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,
inside: {
'punctuation': [
- /^=/,
{
- pattern: /(^|[^\\])["']/,
- lookbehind: true
- }
+ pattern: /^=/,
+ alias: 'attr-equals'
+ },
+ /"|'/
]
}
},
@@ -600,78 +783,144 @@ Prism.languages.markup = {
}
},
- 'entity': /&#?[\da-z]{1,8};/i
+ 'entity': [
+ {
+ pattern: /&[\da-z]{1,8};/i,
+ alias: 'named-entity'
+ },
+ /&#x?[\da-f]{1,8};/i
+ ]
};
Prism.languages.markup['tag'].inside['attr-value'].inside['entity'] =
Prism.languages.markup['entity'];
+Prism.languages.markup['doctype'].inside['internal-subset'].inside = Prism.languages.markup;
// Plugin to make entity title show the real entity, idea by Roman Komarov
-Prism.hooks.add('wrap', function(env) {
+Prism.hooks.add('wrap', function (env) {
if (env.type === 'entity') {
env.attributes['title'] = env.content.replace(/&amp;/, '&');
}
});
-Prism.languages.xml = Prism.languages.markup;
+Object.defineProperty(Prism.languages.markup.tag, 'addInlined', {
+ /**
+ * Adds an inlined language to markup.
+ *
+ * An example of an inlined language is CSS with `<style>` tags.
+ *
+ * @param {string} tagName The name of the tag that contains the inlined language. This name will be treated as
+ * case insensitive.
+ * @param {string} lang The language key.
+ * @example
+ * addInlined('style', 'css');
+ */
+ value: function addInlined(tagName, lang) {
+ var includedCdataInside = {};
+ includedCdataInside['language-' + lang] = {
+ pattern: /(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,
+ lookbehind: true,
+ inside: Prism.languages[lang]
+ };
+ includedCdataInside['cdata'] = /^<!\[CDATA\[|\]\]>$/i;
+
+ var inside = {
+ 'included-cdata': {
+ pattern: /<!\[CDATA\[[\s\S]*?\]\]>/i,
+ inside: includedCdataInside
+ }
+ };
+ inside['language-' + lang] = {
+ pattern: /[\s\S]+/,
+ inside: Prism.languages[lang]
+ };
+
+ var def = {};
+ def[tagName] = {
+ pattern: RegExp(/(<__[\s\S]*?>)(?:<!\[CDATA\[(?:[^\]]|\](?!\]>))*\]\]>|(?!<!\[CDATA\[)[\s\S])*?(?=<\/__>)/.source.replace(/__/g, function () { return tagName; }), 'i'),
+ lookbehind: true,
+ greedy: true,
+ inside: inside
+ };
+
+ Prism.languages.insertBefore('markup', 'cdata', def);
+ }
+});
+
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.xml = Prism.languages.extend('markup', {});
+Prism.languages.ssml = Prism.languages.xml;
+Prism.languages.atom = Prism.languages.xml;
+Prism.languages.rss = Prism.languages.xml;
-Prism.languages.css['atrule'].inside.rest = Prism.languages.css;
+(function (Prism) {
-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
- }
- });
+ var string = /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;
- Prism.languages.insertBefore('inside', 'attr-value', {
- 'style-attr': {
- pattern: /\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,
+ Prism.languages.css = {
+ 'comment': /\/\*[\s\S]*?\*\//,
+ 'atrule': {
+ pattern: /@[\w-]+[\s\S]*?(?:;|(?=\s*\{))/,
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
+ 'rule': /^@[\w-]+/,
+ 'selector-function-argument': {
+ pattern: /(\bselector\s*\((?!\s*\))\s*)(?:[^()]|\((?:[^()]|\([^()]*\))*\))+?(?=\s*\))/,
+ lookbehind: true,
+ alias: 'selector'
}
- },
- alias: 'language-css'
- }
- }, Prism.languages.markup.tag);
-}
-;
+ // See rest below
+ }
+ },
+ 'url': {
+ pattern: RegExp('url\\((?:' + string.source + '|[^\n\r()]*)\\)', 'i'),
+ greedy: true,
+ inside: {
+ 'function': /^url/i,
+ 'punctuation': /^\(|\)$/
+ }
+ },
+ 'selector': RegExp('[^{}\\s](?:[^{};"\']|' + string.source + ')*?(?=\\s*\\{)'),
+ 'string': {
+ pattern: string,
+ 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;
+
+ var markup = Prism.languages.markup;
+ if (markup) {
+ markup.tag.addInlined('style', 'css');
+
+ Prism.languages.insertBefore('inside', 'attr-value', {
+ 'style-attr': {
+ pattern: /\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,
+ inside: {
+ 'attr-name': {
+ pattern: /^\s*style/i,
+ inside: markup.tag.inside
+ },
+ 'punctuation': /^\s*=\s*['"]|['"]\s*$/,
+ 'attr-value': {
+ pattern: /.+/i,
+ inside: Prism.languages.css
+ }
+ },
+ alias: 'language-css'
+ }
+ }, markup.tag);
+ }
+
+}(Prism));
+
Prism.languages.clike = {
'comment': [
{
@@ -689,17 +938,17 @@ Prism.languages.clike = {
greedy: true
},
'class-name': {
- pattern: /((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[\w.\\]+/i,
+ pattern: /(\b(?:class|interface|extends|implements|trait|instanceof|new)\s+|\bcatch\s+\()[\w.\\]+/i,
lookbehind: true,
inside: {
- punctuation: /[.\\]/
+ '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': /--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,
+ 'operator': /[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,
'punctuation': /[{}[\];(),.:]/
};
@@ -716,37 +965,66 @@ Prism.languages.javascript = Prism.languages.extend('clike', {
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/
+ {
+ pattern: /(^|[^.]|\.\.\.\s*)\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|(?:get|set)(?=\s*[\[$\w\xA0-\uFFFF])|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,
+ lookbehind: true
+ },
],
- '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+)?/,
+ 'number': /\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\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}/
+ 'function': /#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,
+ 'operator': /--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/
});
-Prism.languages.javascript['class-name'][0].pattern = /(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/
+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,.;})\]]))/,
+ pattern: /((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=(?:\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,
+ pattern: /#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/,
alias: 'function'
},
- 'constant': /\b[A-Z][A-Z\d_]*\b/
+ 'parameter': [
+ {
+ pattern: /(function(?:\s+[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)?\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\))/,
+ lookbehind: true,
+ inside: Prism.languages.javascript
+ },
+ {
+ pattern: /[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=>)/i,
+ inside: Prism.languages.javascript
+ },
+ {
+ pattern: /(\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*=>)/,
+ lookbehind: true,
+ inside: Prism.languages.javascript
+ },
+ {
+ pattern: /((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|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|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*\{)/,
+ lookbehind: true,
+ inside: Prism.languages.javascript
+ }
+ ],
+ 'constant': /\b[A-Z](?:[A-Z_]|\dx?)*\b/
});
Prism.languages.insertBefore('javascript', 'string', {
'template-string': {
- pattern: /`(?:\\[\s\S]|\${[^}]+}|[^\\`])*`/,
+ pattern: /`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/,
greedy: true,
inside: {
+ 'template-punctuation': {
+ pattern: /^`|`$/,
+ alias: 'string'
+ },
'interpolation': {
- pattern: /\${[^}]+}/,
+ pattern: /((?:^|[^\\])(?:\\{2})*)\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}/,
+ lookbehind: true,
inside: {
'interpolation-punctuation': {
pattern: /^\${|}$/,
@@ -761,15 +1039,7 @@ Prism.languages.insertBefore('javascript', 'string', {
});
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.markup.tag.addInlined('script', 'javascript');
}
Prism.languages.js = Prism.languages.javascript;
@@ -779,13 +1049,36 @@ Prism.languages.python = {
pattern: /(^|[^\\])#.*/,
lookbehind: true
},
+ 'string-interpolation': {
+ pattern: /(?:f|rf|fr)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,
+ greedy: true,
+ inside: {
+ 'interpolation': {
+ // "{" <expression> <optional "!s", "!r", or "!a"> <optional ":" format specifier> "}"
+ pattern: /((?:^|[^{])(?:{{)*){(?!{)(?:[^{}]|{(?!{)(?:[^{}]|{(?!{)(?:[^{}])+})+})+}/,
+ lookbehind: true,
+ inside: {
+ 'format-spec': {
+ pattern: /(:)[^:(){}]+(?=}$)/,
+ lookbehind: true
+ },
+ 'conversion-option': {
+ pattern: /![sra](?=[:}]$)/,
+ alias: 'punctuation'
+ },
+ rest: null
+ }
+ },
+ 'string': /[\s\S]+/
+ }
+ },
'triple-quoted-string': {
- pattern: /("""|''')[\s\S]+?\1/,
+ pattern: /(?:[rub]|rb|br)?("""|''')[\s\S]*?\1/i,
greedy: true,
alias: 'string'
},
'string': {
- pattern: /("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,
+ pattern: /(?:[rub]|rb|br)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,
greedy: true
},
'function': {
@@ -796,17 +1089,29 @@ Prism.languages.python = {
pattern: /(\bclass\s+)\w+/i,
lookbehind: true
},
+ 'decorator': {
+ pattern: /(^\s*)@\w+(?:\.\w+)*/im,
+ lookbehind: true,
+ alias: ['annotation', 'punctuation'],
+ inside: {
+ 'punctuation': /\./
+ }
+ },
'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/,
+ '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.python['string-interpolation'].inside['interpolation'].inside.rest = Prism.languages.python;
+
+Prism.languages.py = Prism.languages.python;
+
Prism.languages['visual-basic'] = {
'comment': {
- pattern: /(?:['‘’]|REM\b).*/i,
+ pattern: /(?:['‘’]|REM\b)(?:[^\r\n_]|_(?:\r\n?|\n)?)*/i,
inside: {
'keyword': /^REM/i
}
@@ -817,7 +1122,7 @@ Prism.languages['visual-basic'] = {
greedy: true
},
'string': {
- pattern: /["“”](?:["“”]{2}|[^"“”])*["“”]C?/i,
+ pattern: /\$?["“”](?:["“”]{2}|[^"“”])*["“”]C?/i,
greedy: true
},
'date': {
@@ -826,7 +1131,7 @@ Prism.languages['visual-basic'] = {
},
'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|With(?:Events)?|WriteOnly|Xor)\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|Currency|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|Type|TypeOf|U(?:Integer|Long|Short)|Using|Variant|Wend|When|While|Widening|With(?:Events)?|WriteOnly|Xor)\b/i,
'operator': [
/[+\-*/\\^<=>&#@$%!]/,
{
@@ -838,6 +1143,7 @@ Prism.languages['visual-basic'] = {
};
Prism.languages.vb = Prism.languages['visual-basic'];
+
(function () {
if (typeof self === 'undefined' || !self.Prism || !self.document) {
@@ -867,6 +1173,9 @@ Prism.languages.vb = Prism.languages['visual-basic'];
if (whiteSpace === 'pre-wrap' || whiteSpace === 'pre-line') {
var codeElement = element.querySelector('code');
var lineNumbersWrapper = element.querySelector('.line-numbers-rows');
+ if (!codeElement || !lineNumbersWrapper) {
+ return;
+ }
var lineNumberSizer = element.querySelector('.line-numbers-sizer');
var codeLines = codeElement.textContent.split(NEW_LINE_EXP);
@@ -911,28 +1220,38 @@ Prism.languages.vb = Prism.languages['visual-basic'];
return;
}
+ var code = env.element;
+ var pre = code.parentNode;
+
// 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))
- ) {
+ if (!pre || !/pre/i.test(pre.nodeName)) {
return;
}
- if (env.element.querySelector('.line-numbers-rows')) {
- // Abort if line numbers already exists
+ // Abort if line numbers already exists
+ if (code.querySelector('.line-numbers-rows')) {
return;
}
- if (clsReg.test(env.element.className)) {
- // Remove the class 'line-numbers' from the <code>
- env.element.className = env.element.className.replace(clsReg, ' ');
+ var addLineNumbers = false;
+ var lineNumbersRegex = /(?:^|\s)line-numbers(?:\s|$)/;
+
+ for (var element = code; element; element = element.parentNode) {
+ if (lineNumbersRegex.test(element.className)) {
+ addLineNumbers = true;
+ break;
+ }
+ }
+
+ // only add line numbers if <code> or one of its ancestors has the `line-numbers` class
+ if (!addLineNumbers) {
+ return;
}
- if (!clsReg.test(pre.className)) {
- // Add the class 'line-numbers' to the <pre>
+
+ // Remove the class 'line-numbers' from the <code>
+ code.className = code.className.replace(lineNumbersRegex, ' ');
+ // Add the class 'line-numbers' to the <pre>
+ if (!lineNumbersRegex.test(pre.className)) {
pre.className += ' line-numbers';
}
@@ -940,8 +1259,7 @@ Prism.languages.vb = Prism.languages['visual-basic'];
var linesNum = match ? match.length + 1 : 1;
var lineNumbersWrapper;
- var lines = new Array(linesNum + 1);
- lines = lines.join('<span></span>');
+ var lines = new Array(linesNum + 1).join('<span></span>');
lineNumbersWrapper = document.createElement('span');
lineNumbersWrapper.setAttribute('aria-hidden', 'true');
@@ -969,10 +1287,10 @@ Prism.languages.vb = Prism.languages['visual-basic'];
*/
Prism.plugins.lineNumbers = {
/**
- * Get node for provided line number
- * @param {Element} element pre element
- * @param {Number} number line number
- * @return {Element|undefined}
+ * Returns the node of the given line number in the given element.
+ * @param {Element} element A `<pre>` element with line numbers.
+ * @param {Number} number
+ * @returns {Element | undefined}
*/
getLine: function (element, number) {
if (element.tagName !== 'PRE' || !element.classList.contains(PLUGIN_NAME)) {
@@ -993,10 +1311,21 @@ Prism.languages.vb = Prism.languages['visual-basic'];
var lineIndex = number - lineNumberStart;
return lineNumberRows.children[lineIndex];
+ },
+ /**
+ * Resizes the line numbers of the given element.
+ *
+ * This function will not add line numbers. It will only resize existing ones.
+ * @param {Element} element A `<pre>` element with line numbers.
+ * @returns {void}
+ */
+ resize: function (element) {
+ _resizeElement(element);
}
};
}());
+
(function() {
var assign = Object.assign || function (obj1, obj2) {
@@ -1147,7 +1476,7 @@ Prism.hooks.add('before-sanity-check', function (env) {
// Normal mode
var pre = env.element.parentNode;
- var clsReg = /\bno-whitespace-normalization\b/;
+ var clsReg = /(?:^|\s)no-whitespace-normalization(?:\s|$)/;
if (!env.code || !pre || pre.nodeName.toLowerCase() !== 'pre' ||
clsReg.test(pre.className) || clsReg.test(env.element.className))
return;