Commit 04f72b1495278dccea1d6d994fbc885d5f841692

Golmote 2015-06-14T18:26:16

ES6: Template strings + interpolation

diff --git a/components/prism-javascript.js b/components/prism-javascript.js
index 863f3af..f4139f2 100644
--- a/components/prism-javascript.js
+++ b/components/prism-javascript.js
@@ -11,6 +11,25 @@ Prism.languages.insertBefore('javascript', 'keyword', {
 	}
 });
 
+Prism.languages.insertBefore('javascript', 'string', {
+	'template-string': {
+		pattern: /`(?:\\`|\\?[^`])*`/,
+		inside: {
+			'interpolation': {
+				pattern: /\$\{[^}]+\}/,
+				inside: {
+					'interpolation-punctuation': {
+						pattern: /^\$\{|\}$/,
+						alias: 'punctuation'
+					},
+					rest: Prism.languages.javascript
+				}
+			},
+			'string': /[\s\S]+/
+		}
+	}
+});
+
 if (Prism.languages.markup) {
 	Prism.languages.insertBefore('markup', 'tag', {
 		'script': {
diff --git a/components/prism-javascript.min.js b/components/prism-javascript.min.js
index 655d780..da70a1b 100644
--- a/components/prism-javascript.min.js
+++ b/components/prism-javascript.min.js
@@ -1 +1 @@
-Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(as|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|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|true|try|typeof|var|void|while|with|yield)\b/,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|-?Infinity)\b/,"function":/(?!\d)[a-z0-9_$]+(?=\()/i}),Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/<script[\w\W]*?>[\w\W]*?<\/script>/i,inside:{tag:{pattern:/<script[\w\W]*?>|<\/script>/i,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript},alias:"language-javascript"}});
\ No newline at end of file
+Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(as|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|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|true|try|typeof|var|void|while|with|yield)\b/,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|-?Infinity)\b/,"function":/(?!\d)[a-z0-9_$]+(?=\()/i}),Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0}}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\`|\\?[^`])*`/,inside:{interpolation:{pattern:/\$\{[^}]+\}/,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/<script[\w\W]*?>[\w\W]*?<\/script>/i,inside:{tag:{pattern:/<script[\w\W]*?>|<\/script>/i,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript},alias:"language-javascript"}});
\ No newline at end of file
diff --git a/examples/prism-javascript.html b/examples/prism-javascript.html
index 213969f..5bd11e3 100644
--- a/examples/prism-javascript.html
+++ b/examples/prism-javascript.html
@@ -50,6 +50,24 @@ var foo = "http://prismjs.com"; // Strings are strings and comments are comments
 <pre><code>var foo = 1/2, bar = /a/g;
 var foo = /a/, bar = 3/4;</code></pre>
 
+<h2>ES6 features</h2>
+<pre><code>// Regex "y" and "u" flags
+/[a-zA-Z]+/gimyu
+
+// for..of loops
+for(let x of y) { }
+
+// Modules: import
+import { foo as bar } from "file.js"
+
+// Template strings
+`Only on ${y} one line`
+`This template string ${x} is on
+
+multiple lines.`
+`40 + 2 = ${ 40 + 2 }`
+`The squares of the first 3 natural integers are ${[for (x of [1,2,3]) x*x].join(', ')}`</code></pre>
+
 <h2>Known failures</h2>
 <p>There are certain edge cases where Prism will fail.
 	There are always such cases in every regex-based syntax highlighter.
@@ -61,4 +79,11 @@ var foo = /a/, bar = 3/4;</code></pre>
 <pre><code>"foo /* bar */ baz"; "foo // bar";</code></pre>
 
 <h3>Two quotes of the same type (i.e. both single or both double) inside a regex</h3>
-<pre><code>foo = /"foo"/;</code></pre>
\ No newline at end of file
+<pre><code>foo = /"foo"/;</code></pre>
+
+<h3>String interpolation containing a closing brace</h3>
+<pre><code>`${ {foo:'bar'}.foo }`
+`${ '}' }`</code></pre>
+
+<h3>String interpolation containing an unescaped back-tick</h3>
+<pre><code>`${ '`' }`</code></pre>
\ No newline at end of file
diff --git a/prism.js b/prism.js
index 0a62921..8e27b9f 100644
--- a/prism.js
+++ b/prism.js
@@ -588,6 +588,25 @@ Prism.languages.insertBefore('javascript', 'keyword', {
 	}
 });
 
+Prism.languages.insertBefore('javascript', 'string', {
+	'template-string': {
+		pattern: /`(?:\\`|\\?[^`])*`/,
+		inside: {
+			'interpolation': {
+				pattern: /\$\{[^}]+\}/,
+				inside: {
+					'interpolation-punctuation': {
+						pattern: /^\$\{|\}$/,
+						alias: 'punctuation'
+					},
+					rest: Prism.languages.javascript
+				}
+			},
+			'string': /[\s\S]+/
+		}
+	}
+});
+
 if (Prism.languages.markup) {
 	Prism.languages.insertBefore('markup', 'tag', {
 		'script': {