vendor/assets/javascripts/prism.js in highlighting-0.1.2 vs vendor/assets/javascripts/prism.js in highlighting-0.1.3
- old
+ new
@@ -18,11 +18,12 @@
*/
var Prism = (function(){
// Private helper vars
-var lang = /\blang(?:uage)?-(?!\*)(\w+)\b/i;
+var lang = /\blang(?:uage)?-(\w+)\b/i;
+var uniqueId = 0;
var _ = _self.Prism = {
util: {
encode: function (tokens) {
if (tokens instanceof Token) {
@@ -36,10 +37,17 @@
type: function (o) {
return Object.prototype.toString.call(o).match(/\[object (\w+)\]/)[1];
},
+ objId: function (obj) {
+ if (!obj['__id']) {
+ Object.defineProperty(obj, '__id', { value: ++uniqueId });
+ }
+ return obj['__id'];
+ },
+
// Deep clone a language definition (e.g. to extend it)
clone: function (o) {
var type = _.util.type(o);
switch (type) {
@@ -84,23 +92,23 @@
* @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)) {
@@ -116,11 +124,11 @@
}
ret[token] = grammar[token];
}
}
-
+
// Update references in other language definitions
_.languages.DFS(_.languages, function(key, value) {
if (value === root[inside] && key != inside) {
this[key] = ret;
}
@@ -128,32 +136,42 @@
return root[inside] = ret;
},
// Traverse a language definition with Depth First Search
- DFS: function(o, callback, type) {
+ 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') {
- _.languages.DFS(o[i], callback);
+ 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') {
- _.languages.DFS(o[i], callback, i);
+ else if (_.util.type(o[i]) === 'Array' && !visited[_.util.objId(o[i])]) {
+ visited[_.util.objId(o[i])] = true;
+ _.languages.DFS(o[i], callback, i, visited);
}
}
}
}
},
plugins: {},
-
+
highlightAll: function(async, callback) {
- var elements = document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code');
+ var env = {
+ callback: callback,
+ selector: 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'
+ };
+ _.hooks.run("before-highlightall", env);
+
+ var elements = env.elements || document.querySelectorAll(env.selector);
+
for (var i=0, element; element = elements[i++];) {
- _.highlightElement(element, async === true, callback);
+ _.highlightElement(element, async === true, env.callback);
}
},
highlightElement: function(element, async, callback) {
// Find language
@@ -185,11 +203,13 @@
language: language,
grammar: grammar,
code: code
};
- if (!code || !grammar) {
+ _.hooks.run('before-sanity-check', env);
+
+ if (!env.code || !env.grammar) {
_.hooks.run('complete', env);
return;
}
_.hooks.run('before-highlight', env);
@@ -259,10 +279,11 @@
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;
pattern = pattern.pattern || pattern;
@@ -279,40 +300,80 @@
continue;
}
pattern.lastIndex = 0;
- var match = pattern.exec(str);
+ var match = pattern.exec(str),
+ delNum = 1;
- if (match) {
- if(lookbehind) {
- lookbehindLength = match[1].length;
+ // Greedy patterns can override/remove up to two previously matched tokens
+ if (!match && greedy && i != strarr.length - 1) {
+ // Reconstruct the original text using the next two tokens
+ var nextToken = strarr[i + 1].matchedStr || strarr[i + 1],
+ combStr = str + nextToken;
+
+ if (i < strarr.length - 2) {
+ combStr += strarr[i + 2].matchedStr || strarr[i + 2];
}
- var from = match.index - 1 + lookbehindLength,
- match = match[0].slice(lookbehindLength),
- len = match.length,
- to = from + len,
- before = str.slice(0, from + 1),
- after = str.slice(to + 1);
+ // Try the pattern again on the reconstructed text
+ pattern.lastIndex = 0;
+ match = pattern.exec(combStr);
+ if (!match) {
+ continue;
+ }
- var args = [i, 1];
+ var from = match.index + (lookbehind ? match[1].length : 0);
+ // To be a valid candidate, the new match has to start inside of str
+ if (from >= str.length) {
+ continue;
+ }
+ var to = match.index + match[0].length,
+ len = str.length + nextToken.length;
- if (before) {
- args.push(before);
+ // Number of tokens to delete and replace with the new match
+ delNum = 3;
+
+ if (to <= len) {
+ if (strarr[i + 1].greedy) {
+ continue;
+ }
+ delNum = 2;
+ combStr = combStr.slice(0, len);
}
+ str = combStr;
+ }
- var wrapped = new Token(token, inside? _.tokenize(match, inside) : match, alias);
+ if (!match) {
+ continue;
+ }
- args.push(wrapped);
+ if(lookbehind) {
+ lookbehindLength = match[1].length;
+ }
- if (after) {
- args.push(after);
- }
+ var from = match.index + lookbehindLength,
+ match = match[0].slice(lookbehindLength),
+ to = from + match.length,
+ before = str.slice(0, from),
+ after = str.slice(to);
- Array.prototype.splice.apply(strarr, args);
+ var args = [i, delNum];
+
+ if (before) {
+ 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);
}
}
}
return strarr;
@@ -341,14 +402,17 @@
}
}
}
};
-var Token = _.Token = function(type, content, alias) {
+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.matchedStr = matchedStr || null;
+ this.greedy = !!greedy;
};
Token.stringify = function(o, language, parent) {
if (typeof o == 'string') {
return o;
@@ -410,15 +474,13 @@
}, false);
return _self.Prism;
}
-// Get current script and highlight
-var script = document.getElementsByTagName('script');
+//Get current script and highlight
+var script = document.currentScript || [].slice.call(document.getElementsByTagName("script")).pop();
-script = script[script.length - 1];
-
if (script) {
_.filename = script.src;
if (document.addEventListener && !script.hasAttribute('data-manual')) {
document.addEventListener('DOMContentLoaded', _.highlightAll);
@@ -557,11 +619,14 @@
{
pattern: /(^|[^\\:])\/\/.*/,
lookbehind: true
}
],
- 'string': /(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
+ 'string': {
+ pattern: /(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
+ greedy: true
+ },
'class-name': {
pattern: /((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i,
lookbehind: true,
inside: {
punctuation: /(\.|\\)/
@@ -588,17 +653,19 @@
});
Prism.languages.insertBefore('javascript', 'keyword', {
'regex': {
pattern: /(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\\\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/,
- lookbehind: true
+ lookbehind: true,
+ greedy: true
}
});
Prism.languages.insertBefore('javascript', 'class-name', {
'template-string': {
- pattern: /`(?:\\`|\\?[^`])*`/,
+ pattern: /`(?:\\\\|\\?[^\\])*?`/,
+ greedy: true,
inside: {
'interpolation': {
pattern: /\$\{[^}]+\}/,
inside: {
'interpolation-punctuation': {
@@ -637,17 +704,18 @@
self.Prism.fileHighlight = function() {
var Extensions = {
'js': 'javascript',
- 'html': 'markup',
- 'svg': 'markup',
- 'xml': 'markup',
'py': 'python',
'rb': 'ruby',
'ps1': 'powershell',
- 'psm1': 'powershell'
+ 'psm1': 'powershell',
+ 'sh': 'bash',
+ 'bat': 'batch',
+ 'h': 'c',
+ 'tex': 'latex'
};
if(Array.prototype.forEach) { // Check to prevent error in IE8
Array.prototype.slice.call(document.querySelectorAll('pre[data-src]')).forEach(function (pre) {
var src = pre.getAttribute('data-src');
@@ -701,8 +769,8 @@
});
}
};
- self.Prism.fileHighlight();
+ document.addEventListener('DOMContentLoaded', self.Prism.fileHighlight);
})();