From 5f1b3826ca906d9ddb3d04489d4393b45778a936 Mon Sep 17 00:00:00 2001 From: Golmote Date: Sun, 10 Jul 2016 13:56:08 +0200 Subject: [PATCH 1/2] Data-URI Highlight plugin --- components.js | 5 + plugins/autolinker/prism-autolinker.js | 58 ++++++----- plugins/autolinker/prism-autolinker.min.js | 2 +- plugins/data-uri-highlight/index.html | 60 ++++++++++++ .../prism-data-uri-highlight.js | 98 +++++++++++++++++++ .../prism-data-uri-highlight.min.js | 1 + 6 files changed, 197 insertions(+), 27 deletions(-) create mode 100644 plugins/data-uri-highlight/index.html create mode 100644 plugins/data-uri-highlight/prism-data-uri-highlight.js create mode 100644 plugins/data-uri-highlight/prism-data-uri-highlight.min.js diff --git a/components.js b/components.js index db90cc284f..1c2f756c38 100644 --- a/components.js +++ b/components.js @@ -641,6 +641,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 e56303f8ed..03b6815b77 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 3e2aeced56..de389b8c0f 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 0000000000..ac817e44b3 --- /dev/null +++ b/plugins/data-uri-highlight/index.html @@ -0,0 +1,60 @@ + + + + + + +Data-URI Highlight ▲ Prism plugins + + + + + + + + + + + +
+
+ +

Data-URI Highlight

+

Highlights data-URI contents.

+
+ +
+

How to use

+

Data-URIs will be highlighted automatically, provided the needed grammar is loaded. + The grammar to use is guessed using the MIME type information.

+
+ +
+

Example

+ +
div {
+    border: 40px solid transparent;
+    border-image: 33.334% url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30"> \
+                          <circle cx="5" cy="5" r="5" fill="%23ab4"/><circle cx="15" cy="5" r="5" fill="%23655"/> \
+                          <circle cx="25" cy="5" r="5" fill="%23e07"/><circle cx="5" cy="15" r="5" fill="%23655"/> \
+                          <circle cx="15" cy="15" r="5" fill="hsl(15, 25%, 75%)"/> \
+                          <circle cx="25" cy="15" r="5" fill="%23655"/><circle cx="5" cy="25" r="5" fill="%23fb3"/> \
+                          <circle cx="15" cy="25" r="5" fill="%23655"/><circle cx="25" cy="25" r="5" fill="%2358a"/></svg>');
+    padding: 1em;
+    max-width: 20em;
+    font: 130%/1.6 Baskerville, Palatino, serif;
+}
+ +
+ + + + + + + + + + + + \ 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 0000000000..467c1f2c59 --- /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 = ['comment', '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 0000000000..8538b55a24 --- /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=["comment","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 From b6ab75b697fc264ee9e5e7fefc0c9e3f9d9ea5bb Mon Sep 17 00:00:00 2001 From: Golmote Date: Mon, 11 Jul 2016 07:56:02 +0200 Subject: [PATCH 2/2] Comment are not candidates for data-uri highlight plugin --- plugins/data-uri-highlight/prism-data-uri-highlight.js | 2 +- plugins/data-uri-highlight/prism-data-uri-highlight.min.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/data-uri-highlight/prism-data-uri-highlight.js b/plugins/data-uri-highlight/prism-data-uri-highlight.js index 467c1f2c59..7ff8d1fd5f 100644 --- a/plugins/data-uri-highlight/prism-data-uri-highlight.js +++ b/plugins/data-uri-highlight/prism-data-uri-highlight.js @@ -37,7 +37,7 @@ }; // Tokens that may contain URLs - var candidates = ['comment', 'url', 'attr-value', 'string']; + var candidates = ['url', 'attr-value', 'string']; Prism.plugins.dataURIHighlight = { processGrammar: function (grammar) { diff --git a/plugins/data-uri-highlight/prism-data-uri-highlight.min.js b/plugins/data-uri-highlight/prism-data-uri-highlight.min.js index 8538b55a24..479828d93f 100644 --- a/plugins/data-uri-highlight/prism-data-uri-highlight.min.js +++ b/plugins/data-uri-highlight/prism-data-uri-highlight.min.js @@ -1 +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=["comment","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 +!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