Commit bdca61bfc92f2aeb35c6b85bc2794d87c833b55a

Golmote 2016-07-14T12:01:52

Merge pull request #996 from Golmote/data-uri-highlight Data-URI Highlight plugin Fix #485

diff --git a/components.js b/components.js
index 0674d04..3541708 100644
--- a/components.js
+++ b/components.js
@@ -645,6 +645,11 @@ var components = {
 			"owner": "zeitgeist87",
 			"after": "unescaped-markup",
 			"noCSS": true
+		},
+		"data-uri-highlight": {
+			"title": "Data-URI Highlight",
+			"owner": "Golmote",
+			"noCSS": true
 		}
 	}
 };
diff --git a/plugins/autolinker/prism-autolinker.js b/plugins/autolinker/prism-autolinker.js
index e56303f..03b6815 100644
--- a/plugins/autolinker/prism-autolinker.js
+++ b/plugins/autolinker/prism-autolinker.js
@@ -14,36 +14,42 @@ var url = /\b([a-z]{3,7}:\/\/|tel:)[\w\-+%~/.:#=?&]+/,
 	// Tokens that may contain URLs and emails
     candidates = ['comment', 'url', 'attr-value', 'string'];
 
-Prism.hooks.add('before-highlight', function(env) {
-	// Abort if grammar has already been processed
-	if (!env.grammar || env.grammar['url-link']) {
-		return;
-	}
-	Prism.languages.DFS(env.grammar, function (key, def, type) {
-		if (candidates.indexOf(type) > -1 && Prism.util.type(def) !== 'Array') {
-			if (!def.pattern) {
-				def = this[key] = {
-					pattern: def
-				};
-			}
+Prism.plugins.autolinker = {
+	processGrammar: function (grammar) {
+		// Abort if grammar has already been processed
+		if (!grammar || grammar['url-link']) {
+			return;
+		}
+		Prism.languages.DFS(grammar, function (key, def, type) {
+			if (candidates.indexOf(type) > -1 && Prism.util.type(def) !== 'Array') {
+				if (!def.pattern) {
+					def = this[key] = {
+						pattern: def
+					};
+				}
 
-			def.inside = def.inside || {};
+				def.inside = def.inside || {};
 
-			if (type == 'comment') {
-				def.inside['md-link'] = linkMd;
-			}
-			if (type == 'attr-value') {
-				Prism.languages.insertBefore('inside', 'punctuation', { 'url-link': url }, def);
-			}
-			else {
-				def.inside['url-link'] = url;
+				if (type == 'comment') {
+					def.inside['md-link'] = linkMd;
+				}
+				if (type == 'attr-value') {
+					Prism.languages.insertBefore('inside', 'punctuation', { 'url-link': url }, def);
+				}
+				else {
+					def.inside['url-link'] = url;
+				}
+
+				def.inside['email-link'] = email;
 			}
+		});
+		grammar['url-link'] = url;
+		grammar['email-link'] = email;
+	}
+};
 
-			def.inside['email-link'] = email;
-		}
-	});
-	env.grammar['url-link'] = url;
-	env.grammar['email-link'] = email;
+Prism.hooks.add('before-highlight', function(env) {
+	Prism.plugins.autolinker.processGrammar(env.grammar);
 });
 
 Prism.hooks.add('wrap', function(env) {
diff --git a/plugins/autolinker/prism-autolinker.min.js b/plugins/autolinker/prism-autolinker.min.js
index 3e2aece..de389b8 100644
--- a/plugins/autolinker/prism-autolinker.min.js
+++ b/plugins/autolinker/prism-autolinker.min.js
@@ -1 +1 @@
-!function(){if(("undefined"==typeof self||self.Prism)&&("undefined"==typeof global||global.Prism)){var i=/\b([a-z]{3,7}:\/\/|tel:)[\w\-+%~\/.:#=?&]+/,n=/\b\S+@[\w.]+[a-z]{2}/,e=/\[([^\]]+)]\(([^)]+)\)/,t=["comment","url","attr-value","string"];Prism.hooks.add("before-highlight",function(a){a.grammar&&!a.grammar["url-link"]&&(Prism.languages.DFS(a.grammar,function(a,r,l){t.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"]=e),"attr-value"==l?Prism.languages.insertBefore("inside","punctuation",{"url-link":i},r):r.inside["url-link"]=i,r.inside["email-link"]=n)}),a.grammar["url-link"]=i,a.grammar["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(("undefined"==typeof self||self.Prism)&&("undefined"==typeof global||global.Prism)){var i=/\b([a-z]{3,7}:\/\/|tel:)[\w\-+%~\/.:#=?&]+/,n=/\b\S+@[\w.]+[a-z]{2}/,e=/\[([^\]]+)]\(([^)]+)\)/,t=["comment","url","attr-value","string"];Prism.plugins.autolinker={processGrammar:function(a){a&&!a["url-link"]&&(Prism.languages.DFS(a,function(a,r,l){t.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"]=e),"attr-value"==l?Prism.languages.insertBefore("inside","punctuation",{"url-link":i},r):r.inside["url-link"]=i,r.inside["email-link"]=n)}),a["url-link"]=i,a["email-link"]=n)}},Prism.hooks.add("before-highlight",function(i){Prism.plugins.autolinker.processGrammar(i.grammar)}),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
diff --git a/plugins/data-uri-highlight/index.html b/plugins/data-uri-highlight/index.html
new file mode 100644
index 0000000..ac817e4
--- /dev/null
+++ b/plugins/data-uri-highlight/index.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+
+<meta charset="utf-8" />
+<link rel="shortcut icon" href="favicon.png" />
+<title>Data-URI Highlight ▲ Prism plugins</title>
+<base href="../.." />
+<link rel="stylesheet" href="style.css" />
+<link rel="stylesheet" href="themes/prism.css" data-noprefix />
+<link rel="stylesheet" href="plugins/autolinker/prism-autolinker.css" data-noprefix />
+<script src="prefixfree.min.js"></script>
+
+<script>var _gaq = [['_setAccount', 'UA-33746269-1'], ['_trackPageview']];</script>
+<script src="http://www.google-analytics.com/ga.js" async></script>
+</head>
+<body>
+
+<header>
+	<div class="intro" data-src="templates/header-plugins.html" data-type="text/html"></div>
+
+	<h2>Data-URI Highlight</h2>
+	<p>Highlights data-URI contents.</p>
+</header>
+
+<section>
+	<h1>How to use</h1>
+	<p>Data-URIs will be highlighted automatically, provided the needed grammar is loaded.
+	The grammar to use is guessed using the MIME type information.</p>
+</section>
+
+<section>
+	<h1>Example</h1>
+	
+	<pre><code class="language-css">div {
+    border: 40px solid transparent;
+    border-image: 33.334% url('data:image/svg+xml,&lt;svg xmlns="http://www.w3.org/2000/svg" width="30" height="30"> \
+                          &lt;circle cx="5" cy="5" r="5" fill="%23ab4"/>&lt;circle cx="15" cy="5" r="5" fill="%23655"/> \
+                          &lt;circle cx="25" cy="5" r="5" fill="%23e07"/>&lt;circle cx="5" cy="15" r="5" fill="%23655"/> \
+                          &lt;circle cx="15" cy="15" r="5" fill="hsl(15, 25%, 75%)"/> \
+                          &lt;circle cx="25" cy="15" r="5" fill="%23655"/>&lt;circle cx="5" cy="25" r="5" fill="%23fb3"/> \
+                          &lt;circle cx="15" cy="25" r="5" fill="%23655"/>&lt;circle cx="25" cy="25" r="5" fill="%2358a"/>&lt;/svg>');
+    padding: 1em;
+    max-width: 20em;
+    font: 130%/1.6 Baskerville, Palatino, serif;
+}</code></pre>
+
+</section>
+
+<footer data-src="templates/footer.html" data-type="text/html"></footer>
+
+<script src="prism.js"></script>
+<script src="plugins/data-uri-highlight/prism-data-uri-highlight.js"></script>
+<script src="utopia.js"></script>
+<script src="components.js"></script>
+<script src="code.js"></script>
+
+
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/data-uri-highlight/prism-data-uri-highlight.js b/plugins/data-uri-highlight/prism-data-uri-highlight.js
new file mode 100644
index 0000000..7ff8d1f
--- /dev/null
+++ b/plugins/data-uri-highlight/prism-data-uri-highlight.js
@@ -0,0 +1,98 @@
+(function () {
+
+	if (
+		typeof self !== 'undefined' && !self.Prism ||
+		typeof global !== 'undefined' && !global.Prism
+	) {
+		return;
+	}
+
+	var autoLinkerProcess = function (grammar) {
+		if (Prism.plugins.autolinker) {
+			Prism.plugins.autolinker.processGrammar(grammar);
+		}
+		return grammar;
+	};
+	var dataURI = {
+		pattern: /(.)\bdata:[^\/]+\/[^,]+,(?:(?!\1)[\s\S]|\\\1)+(?=\1)/,
+		lookbehind: true,
+		inside: {
+			'language-css': {
+				pattern: /(data:[^\/]+\/(?:[^+,]+\+)?css,)[\s\S]+/,
+				lookbehind: true
+			},
+			'language-javascript': {
+				pattern: /(data:[^\/]+\/(?:[^+,]+\+)?javascript,)[\s\S]+/,
+				lookbehind: true
+			},
+			'language-json': {
+				pattern: /(data:[^\/]+\/(?:[^+,]+\+)?json,)[\s\S]+/,
+				lookbehind: true
+			},
+			'language-markup': {
+				pattern: /(data:[^\/]+\/(?:[^+,]+\+)?(?:html|xml),)[\s\S]+/,
+				lookbehind: true
+			}
+		}
+	};
+
+	// Tokens that may contain URLs
+	var candidates = ['url', 'attr-value', 'string'];
+
+	Prism.plugins.dataURIHighlight = {
+		processGrammar: function (grammar) {
+			// Abort if grammar has already been processed
+			if (!grammar || grammar['data-uri']) {
+				return;
+			}
+
+			Prism.languages.DFS(grammar, function (key, def, type) {
+				if (candidates.indexOf(type) > -1 && Prism.util.type(def) !== 'Array') {
+					if (!def.pattern) {
+						def = this[key] = {
+							pattern: def
+						};
+					}
+
+					def.inside = def.inside || {};
+
+					if (type == 'attr-value') {
+						Prism.languages.insertBefore('inside', def.inside['url-link'] ? 'url-link' : 'punctuation', {
+							'data-uri': dataURI
+						}, def);
+					}
+					else {
+						if (def.inside['url-link']) {
+							Prism.languages.insertBefore('inside', 'url-link', {
+								'data-uri': dataURI
+							}, def);
+						} else {
+							def.inside['data-uri'] = dataURI;
+						}
+					}
+				}
+			});
+			grammar['data-uri'] = dataURI;
+		}
+	};
+
+	Prism.hooks.add('before-highlight', function (env) {
+		// Prepare the needed grammars for this code block
+		if (dataURI.pattern.test(env.code)) {
+			for (var p in dataURI.inside) {
+				if (dataURI.inside.hasOwnProperty(p)) {
+					if (!dataURI.inside[p].inside && dataURI.inside[p].pattern.test(env.code)) {
+						var lang = p.match(/^language-(.+)/)[1];
+						if (Prism.languages[lang]) {
+							dataURI.inside[p].inside = {
+								rest: autoLinkerProcess(Prism.languages[lang])
+							};
+						}
+					}
+				}
+			}
+		}
+
+		Prism.plugins.dataURIHighlight.processGrammar(env.grammar);
+	});
+}());
\ No newline at end of file
diff --git a/plugins/data-uri-highlight/prism-data-uri-highlight.min.js b/plugins/data-uri-highlight/prism-data-uri-highlight.min.js
new file mode 100644
index 0000000..479828d
--- /dev/null
+++ b/plugins/data-uri-highlight/prism-data-uri-highlight.min.js
@@ -0,0 +1 @@
+!function(){if(("undefined"==typeof self||self.Prism)&&("undefined"==typeof global||global.Prism)){var i=function(i){return Prism.plugins.autolinker&&Prism.plugins.autolinker.processGrammar(i),i},a={pattern:/(.)\bdata:[^\/]+\/[^,]+,(?:(?!\1)[\s\S]|\\\1)+(?=\1)/,lookbehind:!0,inside:{"language-css":{pattern:/(data:[^\/]+\/(?:[^+,]+\+)?css,)[\s\S]+/,lookbehind:!0},"language-javascript":{pattern:/(data:[^\/]+\/(?:[^+,]+\+)?javascript,)[\s\S]+/,lookbehind:!0},"language-json":{pattern:/(data:[^\/]+\/(?:[^+,]+\+)?json,)[\s\S]+/,lookbehind:!0},"language-markup":{pattern:/(data:[^\/]+\/(?:[^+,]+\+)?(?:html|xml),)[\s\S]+/,lookbehind:!0}}},n=["url","attr-value","string"];Prism.plugins.dataURIHighlight={processGrammar:function(i){i&&!i["data-uri"]&&(Prism.languages.DFS(i,function(i,e,r){n.indexOf(r)>-1&&"Array"!==Prism.util.type(e)&&(e.pattern||(e=this[i]={pattern:e}),e.inside=e.inside||{},"attr-value"==r?Prism.languages.insertBefore("inside",e.inside["url-link"]?"url-link":"punctuation",{"data-uri":a},e):e.inside["url-link"]?Prism.languages.insertBefore("inside","url-link",{"data-uri":a},e):e.inside["data-uri"]=a)}),i["data-uri"]=a)}},Prism.hooks.add("before-highlight",function(n){if(a.pattern.test(n.code))for(var e in a.inside)if(a.inside.hasOwnProperty(e)&&!a.inside[e].inside&&a.inside[e].pattern.test(n.code)){var r=e.match(/^language-(.+)/)[1];Prism.languages[r]&&(a.inside[e].inside={rest:i(Prism.languages[r])})}Prism.plugins.dataURIHighlight.processGrammar(n.grammar)})}}();
\ No newline at end of file