From 08037e5b419f8d35167aea24d368174d1cefe98a Mon Sep 17 00:00:00 2001 From: Andreas Rohner Date: Fri, 5 Sep 2014 11:01:02 +0200 Subject: [PATCH] Fix for DFS bug with new pattern array feature This patch implements support for the new pattern array feature in the Prism.languages.DFS function and fixes a bug in the autolinker plugin. It adds an optional parameter to the callback of Prism.languages.DFS, which contains the type of the current object as oposed to the key in the parent. In most cases both key and type are exactly the same. Only if the parent is an array the key will contain the index number and the type will contain the attribute name of the array in the parent object. The key can be used to replace the object in the parent and the type can be used to provide the necessary context. --- components/prism-core.js | 12 ++++++++---- components/prism-core.min.js | 2 +- plugins/autolinker/prism-autolinker.js | 6 +++--- plugins/autolinker/prism-autolinker.min.js | 2 +- prism.js | 12 ++++++++---- 5 files changed, 21 insertions(+), 13 deletions(-) diff --git a/components/prism-core.js b/components/prism-core.js index fc4cec792f..65f2b5f73e 100644 --- a/components/prism-core.js +++ b/components/prism-core.js @@ -96,12 +96,16 @@ var _ = self.Prism = { }, // Traverse a language definition with Depth First Search - DFS: function(o, callback) { + DFS: function(o, callback, type) { for (var i in o) { - callback.call(o, i, o[i]); + if (o.hasOwnProperty(i)) { + callback.call(o, i, o[i], type || i); - if (_.util.type(o) === 'Object') { - _.languages.DFS(o[i], callback); + if (_.util.type(o[i]) === 'Object') { + _.languages.DFS(o[i], callback); + } else if (_.util.type(o[i]) === 'Array') { + _.languages.DFS(o[i], callback, i); + } } } } diff --git a/components/prism-core.min.js b/components/prism-core.min.js index 71651d565c..b733864f59 100644 --- a/components/prism-core.min.js +++ b/components/prism-core.min.js @@ -1 +1 @@ -self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{};var Prism=function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={util:{encode:function(e){return e instanceof n?new n(e.type,t.util.encode(e.content),e.alias):"Array"===t.util.type(e)?e.map(t.util.encode):e.replace(/&/g,"&").replace(/e.length)break e;if(!(d instanceof a)){c.lastIndex=0;var m=c.exec(d);if(m){u&&(f=m[1].length);var y=m.index-1+f,m=m[0].slice(f),v=m.length,k=y+v,b=d.slice(0,y+1),w=d.slice(k+1),N=[p,1];b&&N.push(b);var O=new a(l,g?t.tokenize(m,g):m,h);N.push(O),w&&N.push(w),Array.prototype.splice.apply(r,N)}}}}}return r},hooks:{all:{},add:function(e,n){var a=t.hooks.all;a[e]=a[e]||[],a[e].push(n)},run:function(e,n){var a=t.hooks.all[e];if(a&&a.length)for(var r,i=0;r=a[i++];)r(n)}}},n=t.Token=function(e,t,n){this.type=e,this.content=t,this.alias=n};if(n.stringify=function(e,a,r){if("string"==typeof e)return e;if("[object Array]"==Object.prototype.toString.call(e))return e.map(function(t){return n.stringify(t,a,e)}).join("");var i={type:e.type,content:n.stringify(e.content,a,r),tag:"span",classes:["token",e.type],attributes:{},language:a,parent:r};if("comment"==i.type&&(i.attributes.spellcheck="true"),e.alias){var l="Array"===t.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(i.classes,l)}t.hooks.run("wrap",i);var o="";for(var s in i.attributes)o+=s+'="'+(i.attributes[s]||"")+'"';return"<"+i.tag+' class="'+i.classes.join(" ")+'" '+o+">"+i.content+""},!self.document)return self.addEventListener?(self.addEventListener("message",function(e){var n=JSON.parse(e.data),a=n.language,r=n.code;self.postMessage(JSON.stringify(t.util.encode(t.tokenize(r,t.languages[a])))),self.close()},!1),self.Prism):self.Prism;var a=document.getElementsByTagName("script");return a=a[a.length-1],a&&(t.filename=a.src,document.addEventListener&&!a.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)),self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism); \ No newline at end of file +self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{};var Prism=function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={util:{encode:function(e){return e instanceof n?new n(e.type,t.util.encode(e.content),e.alias):"Array"===t.util.type(e)?e.map(t.util.encode):e.replace(/&/g,"&").replace(/e.length)break e;if(!(d instanceof a)){c.lastIndex=0;var m=c.exec(d);if(m){u&&(f=m[1].length);var y=m.index-1+f,m=m[0].slice(f),v=m.length,k=y+v,b=d.slice(0,y+1),w=d.slice(k+1),N=[p,1];b&&N.push(b);var O=new a(l,g?t.tokenize(m,g):m,h);N.push(O),w&&N.push(w),Array.prototype.splice.apply(r,N)}}}}}return r},hooks:{all:{},add:function(e,n){var a=t.hooks.all;a[e]=a[e]||[],a[e].push(n)},run:function(e,n){var a=t.hooks.all[e];if(a&&a.length)for(var r,i=0;r=a[i++];)r(n)}}},n=t.Token=function(e,t,n){this.type=e,this.content=t,this.alias=n};if(n.stringify=function(e,a,r){if("string"==typeof e)return e;if("[object Array]"==Object.prototype.toString.call(e))return e.map(function(t){return n.stringify(t,a,e)}).join("");var i={type:e.type,content:n.stringify(e.content,a,r),tag:"span",classes:["token",e.type],attributes:{},language:a,parent:r};if("comment"==i.type&&(i.attributes.spellcheck="true"),e.alias){var l="Array"===t.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(i.classes,l)}t.hooks.run("wrap",i);var o="";for(var s in i.attributes)o+=s+'="'+(i.attributes[s]||"")+'"';return"<"+i.tag+' class="'+i.classes.join(" ")+'" '+o+">"+i.content+""},!self.document)return self.addEventListener?(self.addEventListener("message",function(e){var n=JSON.parse(e.data),a=n.language,r=n.code;self.postMessage(JSON.stringify(t.util.encode(t.tokenize(r,t.languages[a])))),self.close()},!1),self.Prism):self.Prism;var a=document.getElementsByTagName("script");return a=a[a.length-1],a&&(t.filename=a.src,document.addEventListener&&!a.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)),self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism); \ No newline at end of file diff --git a/plugins/autolinker/prism-autolinker.js b/plugins/autolinker/prism-autolinker.js index 49871763b7..8123861627 100644 --- a/plugins/autolinker/prism-autolinker.js +++ b/plugins/autolinker/prism-autolinker.js @@ -14,10 +14,10 @@ var url = /\b([a-z]{3,7}:\/\/|tel:)[\w-+%~/.:#=?&]+/, for (var language in Prism.languages) { var tokens = Prism.languages[language]; - Prism.languages.DFS(tokens, function (type, def) { - if (candidates.indexOf(type) > -1) { + Prism.languages.DFS(tokens, function (key, def, type) { + if (candidates.indexOf(type) > -1 && Prism.util.type(def) !== 'Array') { if (!def.pattern) { - def = this[type] = { + def = this[key] = { pattern: def }; } diff --git a/plugins/autolinker/prism-autolinker.min.js b/plugins/autolinker/prism-autolinker.min.js index a53ef61b41..80f30dfdf2 100644 --- a/plugins/autolinker/prism-autolinker.min.js +++ b/plugins/autolinker/prism-autolinker.min.js @@ -1 +1 @@ -!function(){if(self.Prism){var i=/\b([a-z]{3,7}:\/\/|tel:)[\w-+%~/.:#=?&]+/,n=/\b\S+@[\w.]+[a-z]{2}/,e=/\[([^\]]+)]\(([^)]+)\)/,t=["comment","url","attr-value","string"];for(var a in Prism.languages){var l=Prism.languages[a];Prism.languages.DFS(l,function(a,l){t.indexOf(a)>-1&&(l.pattern||(l=this[a]={pattern:l}),l.inside=l.inside||{},"comment"==a&&(l.inside["md-link"]=e),"attr-value"==a?Prism.languages.insertBefore("inside","punctuation",{"url-link":i},l):l.inside["url-link"]=i,l.inside["email-link"]=n)}),l["url-link"]=i,l["email-link"]=n}Prism.hooks.add("wrap",function(i){if(/-link$/.test(i.type)){i.tag="a";var n=i.content;if("email-link"==i.type&&0!=n.indexOf("mailto:"))n="mailto:"+n;else if("md-link"==i.type){var t=i.content.match(e);n=t[2],i.content=t[1]}i.attributes.href=n}})}}(); \ No newline at end of file +!function(){if(self.Prism){var i=/\b([a-z]{3,7}:\/\/|tel:)[\w-+%~/.:#=?&]+/,n=/\b\S+@[\w.]+[a-z]{2}/,t=/\[([^\]]+)]\(([^)]+)\)/,e=["comment","url","attr-value","string"];for(var a in Prism.languages){var r=Prism.languages[a];Prism.languages.DFS(r,function(a,r,l){e.indexOf(l)>-1&&"Array"!==Prism.util.type(r)&&(r.pattern||(r=this[a]={pattern:r}),r.inside=r.inside||{},"comment"==l&&(r.inside["md-link"]=t),"attr-value"==l?Prism.languages.insertBefore("inside","punctuation",{"url-link":i},r):r.inside["url-link"]=i,r.inside["email-link"]=n)}),r["url-link"]=i,r["email-link"]=n}Prism.hooks.add("wrap",function(i){if(/-link$/.test(i.type)){i.tag="a";var n=i.content;if("email-link"==i.type&&0!=n.indexOf("mailto:"))n="mailto:"+n;else if("md-link"==i.type){var e=i.content.match(t);n=e[2],i.content=e[1]}i.attributes.href=n}})}}(); \ No newline at end of file diff --git a/prism.js b/prism.js index 5069ad6b7b..28738699ba 100644 --- a/prism.js +++ b/prism.js @@ -101,12 +101,16 @@ var _ = self.Prism = { }, // Traverse a language definition with Depth First Search - DFS: function(o, callback) { + DFS: function(o, callback, type) { for (var i in o) { - callback.call(o, i, o[i]); + if (o.hasOwnProperty(i)) { + callback.call(o, i, o[i], type || i); - if (_.util.type(o) === 'Object') { - _.languages.DFS(o[i], callback); + if (_.util.type(o[i]) === 'Object') { + _.languages.DFS(o[i], callback); + } else if (_.util.type(o[i]) === 'Array') { + _.languages.DFS(o[i], callback, i); + } } } }