LiveScript: Make interpolated strings greedy + fix variable and identifier regexps
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
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_"]
]
----------------------------------------------------