Commit c5810498a0acb274b414a7fd246e2dfc99dfa09d

Golmote 2017-10-22T14:55:20

LiveScript: Make interpolated strings greedy + fix variable and identifier regexps

diff --git a/components/prism-livescript.js b/components/prism-livescript.js
index 7a26605..680ddea 100644
--- a/components/prism-livescript.js
+++ b/components/prism-livescript.js
@@ -1,10 +1,23 @@
 Prism.languages.livescript = {
+	'comment': [
+		{
+			pattern: /(^|[^\\])\/\*[\s\S]*?\*\//,
+			lookbehind: true
+		},
+		{
+			pattern: /(^|[^\\])#.*/,
+			lookbehind: true
+		}
+	],
 	'interpolated-string': {
-		pattern: /("""|")(?:\\[\s\S]|(?!\1)[^\\])*\1/,
+		/* Look-behind and look-ahead prevents wrong behavior of the greedy pattern
+		* forcing it to match """-quoted string when it would otherwise match "-quoted first. */
+		pattern: /(^|[^"])("""|")(?:\\[\s\S]|(?!\2)[^\\])*\2(?!")/,
+		lookbehind: true,
 		greedy: true,
 		inside: {
 			'variable': {
-				pattern: /(^|[^\\])#[a-z_](?:-?[a-z]|\d)*/m,
+				pattern: /(^|[^\\])#[a-z_](?:-?[a-z]|[\d_])*/m,
 				lookbehind: true
 			},
 			'interpolation': {
@@ -21,18 +34,6 @@ Prism.languages.livescript = {
 			'string': /[\s\S]+/
 		}
 	},
-	'comment': [
-		{
-			pattern: /(^|[^\\])\/\*[\s\S]*?\*\//,
-			lookbehind: true,
-			greedy: true
-		},
-		{
-			pattern: /(^|[^\\])#.*/,
-			lookbehind: true,
-			greedy: true
-		}
-	],
 	'string': [
 		{
 			pattern: /('''|')(?:\\[\s\S]|(?!\1)[^\\])*\1/,
@@ -80,7 +81,7 @@ Prism.languages.livescript = {
 		alias: 'variable'
 	},
 	'number': /\b(?:\d+~[\da-z]+|\d[\d_]*(?:\.\d[\d_]*)?(?:[a-z]\w*)?)/i,
-	'identifier': /[a-z_](?:-?[a-z]|\d)*/i,
+	'identifier': /[a-z_](?:-?[a-z]|[\d_])*/i,
 	'operator': [
 		// Spaced .
 		{
diff --git a/components/prism-livescript.min.js b/components/prism-livescript.min.js
index 0490d1c..dd59a4e 100644
--- a/components/prism-livescript.min.js
+++ b/components/prism-livescript.min.js
@@ -1 +1 @@
-Prism.languages.livescript={"interpolated-string":{pattern:/("""|")(?:\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0,inside:{variable:{pattern:/(^|[^\\])#[a-z_](?:-?[a-z]|\d)*/m,lookbehind:!0},interpolation:{pattern:/(^|[^\\])#\{[^}]+\}/m,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^#\{|\}$/,alias:"variable"}}},string:/[\s\S]+/}},comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?\*\//,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0}],string:[{pattern:/('''|')(?:\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0},{pattern:/<\[[\s\S]*?\]>/,greedy:!0},/\\[^\s,;\])}]+/],regex:[{pattern:/\/\/(\[.+?]|\\.|(?!\/\/)[^\\])+\/\/[gimyu]{0,5}/,greedy:!0,inside:{comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0}}},{pattern:/\/(\[.+?]|\\.|[^\/\\\r\n])+\/[gimyu]{0,5}/,greedy:!0}],keyword:{pattern:/(^|(?!-).)\b(?:break|case|catch|class|const|continue|default|do|else|extends|fallthrough|finally|for(?: ever)?|function|if|implements|it|let|loop|new|null|otherwise|own|return|super|switch|that|then|this|throw|try|unless|until|var|void|when|while|yield)(?!-)\b/m,lookbehind:!0},"keyword-operator":{pattern:/(^|[^-])\b(?:(?:delete|require|typeof)!|(?:and|by|delete|export|from|import(?: all)?|in|instanceof|is(?:nt| not)?|not|of|or|til|to|typeof|with|xor)(?!-)\b)/m,lookbehind:!0,alias:"operator"},"boolean":{pattern:/(^|[^-])\b(?:false|no|off|on|true|yes)(?!-)\b/m,lookbehind:!0},argument:{pattern:/(^|(?!\.&\.)[^&])&(?!&)\d*/m,lookbehind:!0,alias:"variable"},number:/\b(?:\d+~[\da-z]+|\d[\d_]*(?:\.\d[\d_]*)?(?:[a-z]\w*)?)/i,identifier:/[a-z_](?:-?[a-z]|\d)*/i,operator:[{pattern:/( )\.(?= )/,lookbehind:!0},/\.(?:[=~]|\.\.?)|\.(?:[&|^]|<<|>>>?)\.|:(?:=|:=?)|&&|\|[|>]|<(?:<<?<?|--?!?|~~?!?|[|=?])?|>[>=?]?|-(?:->?|>)?|\+\+?|@@?|%%?|\*\*?|!(?:~?=|--?>|~?~>)?|~(?:~?>|=)?|==?|\^\^?|[\/?]/],punctuation:/[(){}\[\]|.,:;`]/},Prism.languages.livescript["interpolated-string"].inside.interpolation.inside.rest=Prism.languages.livescript;
\ No newline at end of file
+Prism.languages.livescript={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?\*\//,lookbehind:!0},{pattern:/(^|[^\\])#.*/,lookbehind:!0}],"interpolated-string":{pattern:/(^|[^"])("""|")(?:\\[\s\S]|(?!\2)[^\\])*\2(?!")/,lookbehind:!0,greedy:!0,inside:{variable:{pattern:/(^|[^\\])#[a-z_](?:-?[a-z]|[\d_])*/m,lookbehind:!0},interpolation:{pattern:/(^|[^\\])#\{[^}]+\}/m,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^#\{|\}$/,alias:"variable"}}},string:/[\s\S]+/}},string:[{pattern:/('''|')(?:\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0},{pattern:/<\[[\s\S]*?\]>/,greedy:!0},/\\[^\s,;\])}]+/],regex:[{pattern:/\/\/(\[.+?]|\\.|(?!\/\/)[^\\])+\/\/[gimyu]{0,5}/,greedy:!0,inside:{comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0}}},{pattern:/\/(\[.+?]|\\.|[^\/\\\r\n])+\/[gimyu]{0,5}/,greedy:!0}],keyword:{pattern:/(^|(?!-).)\b(?:break|case|catch|class|const|continue|default|do|else|extends|fallthrough|finally|for(?: ever)?|function|if|implements|it|let|loop|new|null|otherwise|own|return|super|switch|that|then|this|throw|try|unless|until|var|void|when|while|yield)(?!-)\b/m,lookbehind:!0},"keyword-operator":{pattern:/(^|[^-])\b(?:(?:delete|require|typeof)!|(?:and|by|delete|export|from|import(?: all)?|in|instanceof|is(?:nt| not)?|not|of|or|til|to|typeof|with|xor)(?!-)\b)/m,lookbehind:!0,alias:"operator"},"boolean":{pattern:/(^|[^-])\b(?:false|no|off|on|true|yes)(?!-)\b/m,lookbehind:!0},argument:{pattern:/(^|(?!\.&\.)[^&])&(?!&)\d*/m,lookbehind:!0,alias:"variable"},number:/\b(?:\d+~[\da-z]+|\d[\d_]*(?:\.\d[\d_]*)?(?:[a-z]\w*)?)/i,identifier:/[a-z_](?:-?[a-z]|[\d_])*/i,operator:[{pattern:/( )\.(?= )/,lookbehind:!0},/\.(?:[=~]|\.\.?)|\.(?:[&|^]|<<|>>>?)\.|:(?:=|:=?)|&&|\|[|>]|<(?:<<?<?|--?!?|~~?!?|[|=?])?|>[>=?]?|-(?:->?|>)?|\+\+?|@@?|%%?|\*\*?|!(?:~?=|--?>|~?~>)?|~(?:~?>|=)?|==?|\^\^?|[\/?]/],punctuation:/[(){}\[\]|.,:;`]/},Prism.languages.livescript["interpolated-string"].inside.interpolation.inside.rest=Prism.languages.livescript;
\ No newline at end of file
diff --git a/tests/languages/livescript/identifier_feature.test b/tests/languages/livescript/identifier_feature.test
index e0de5e8..0b9fc09 100644
--- a/tests/languages/livescript/identifier_feature.test
+++ b/tests/languages/livescript/identifier_feature.test
@@ -4,6 +4,8 @@ foo-bar42-baz
 yes-no
 function-case
 delete-by
+a-b2
+_-a_
 
 ----------------------------------------------------
 
@@ -13,7 +15,9 @@ delete-by
 	["identifier", "foo-bar42-baz"],
 	["identifier", "yes-no"],
 	["identifier", "function-case"],
-	["identifier", "delete-by"]
+	["identifier", "delete-by"],
+	["identifier", "a-b2"],
+	["identifier", "_-a_"]
 ]
 
 ----------------------------------------------------