mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
Merge pull request #3256 from xixixao/issue3249
Implements #3249, #1994 Escape newlines in heredocs with backslashes
This commit is contained in:
commit
210376f7a9
3 changed files with 85 additions and 14 deletions
|
@ -767,10 +767,17 @@
|
|||
};
|
||||
|
||||
Lexer.prototype.escapeLines = function(str, heredoc) {
|
||||
str = str.replace(/\\[^\S\n]*(\n|\\)\s*/g, function(escaped, character) {
|
||||
if (character === '\n') {
|
||||
return '';
|
||||
} else {
|
||||
return escaped;
|
||||
}
|
||||
});
|
||||
if (heredoc) {
|
||||
return str.replace(MULTILINER, '\\n');
|
||||
} else {
|
||||
return str.replace(/((^|[^\\])(\\\\)+)\n/g, '$1 \\\n').replace(/\\\s*\n\s*/g, '').replace(/\s*\n\s*/g, ' ');
|
||||
return str.replace(/\s*\n\s*/g, ' ');
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -778,8 +785,8 @@
|
|||
if (!body) {
|
||||
return quote + quote;
|
||||
}
|
||||
body = body.replace(/\\([\s\S])/g, function(match, contents) {
|
||||
if (contents === quote || heredoc && contents === '\n') {
|
||||
body = body.replace(RegExp("\\\\(" + quote + "|\\\\)", "g"), function(match, contents) {
|
||||
if (contents === quote) {
|
||||
return contents;
|
||||
} else {
|
||||
return match;
|
||||
|
|
|
@ -691,18 +691,20 @@ exports.Lexer = class Lexer
|
|||
|
||||
# Converts newlines for string literals.
|
||||
escapeLines: (str, heredoc) ->
|
||||
# Ignore escaped backslashes and remove escaped newlines
|
||||
str = str.replace /\\[^\S\n]*(\n|\\)\s*/g, (escaped, character) ->
|
||||
if character is '\n' then '' else escaped
|
||||
if heredoc
|
||||
str.replace MULTILINER, '\\n'
|
||||
else
|
||||
str.replace(/((^|[^\\])(\\\\)+)\n/g, '$1 \\\n') # escaped backslashes
|
||||
.replace(/\\\s*\n\s*/g, '') # backslash at EOL
|
||||
.replace(/\s*\n\s*/g, ' ')
|
||||
str.replace /\s*\n\s*/g, ' '
|
||||
|
||||
# Constructs a string token by escaping quotes and newlines.
|
||||
makeString: (body, quote, heredoc) ->
|
||||
return quote + quote unless body
|
||||
body = body.replace /\\([\s\S])/g, (match, contents) ->
|
||||
if contents is quote or heredoc and contents is '\n' then contents else match
|
||||
# Ignore escaped backslashes and unescape quotes
|
||||
body = body.replace /// \\( #{quote} | \\ ) ///g, (match, contents) ->
|
||||
if contents is quote then contents else match
|
||||
body = body.replace /// #{quote} ///g, '\\$&'
|
||||
quote + @escapeLines(body, heredoc) + quote
|
||||
|
||||
|
|
|
@ -42,6 +42,8 @@ test "#3229, multiline strings", ->
|
|||
indentation
|
||||
doesn\'t
|
||||
matter', 'indentation doesn\'t matter'
|
||||
eq 'trailing ws
|
||||
doesn\'t matter', 'trailing ws doesn\'t matter'
|
||||
|
||||
# Use backslashes at the end of a line to specify whitespace between lines.
|
||||
eq 'a \
|
||||
|
@ -72,6 +74,7 @@ test "#3229, multiline strings", ->
|
|||
}", "a string inside interpolation"
|
||||
|
||||
# Handle escaped backslashes correctly.
|
||||
eq '\\', `'\\'`
|
||||
eq 'escaped backslash at EOL\\
|
||||
next line', 'escaped backslash at EOL\\ next line'
|
||||
eq '\\
|
||||
|
@ -84,8 +87,10 @@ test "#3229, multiline strings", ->
|
|||
next line', 'triple backslash\\next line'
|
||||
eq 'several escaped backslashes\\\\\\
|
||||
ok', 'several escaped backslashes\\\\\\ ok'
|
||||
eq 'several escaped backslashes\\\\\\\
|
||||
ok', 'several escaped backslashes\\\\\\ok'
|
||||
eq 'several escaped backslashes slash\\\\\\\
|
||||
ok', 'several escaped backslashes slash\\\\\\ok'
|
||||
eq 'several escaped backslashes with trailing ws \\\\\\
|
||||
ok', 'several escaped backslashes with trailing ws \\\\\\ ok'
|
||||
|
||||
# Backslashes at beginning of lines.
|
||||
eq 'first line
|
||||
|
@ -100,6 +105,67 @@ test "#3229, multiline strings", ->
|
|||
|
||||
backslash', 'lone backslash'
|
||||
|
||||
test "#3249, escape newlines in heredocs with backslashes", ->
|
||||
# Ignore escaped newlines
|
||||
eq '''
|
||||
Set whitespace \
|
||||
<- this is ignored\
|
||||
none
|
||||
normal indentation
|
||||
''', 'Set whitespace <- this is ignorednone\n normal indentation'
|
||||
eq """
|
||||
Set whitespace \
|
||||
<- this is ignored\
|
||||
none
|
||||
normal indentation
|
||||
""", 'Set whitespace <- this is ignorednone\n normal indentation'
|
||||
|
||||
# Changed from #647
|
||||
eq '''
|
||||
Hello, World\
|
||||
|
||||
''', 'Hello, World'
|
||||
|
||||
# Backslash at the beginning of a literal string.
|
||||
eq '''\
|
||||
ok''', 'ok'
|
||||
eq ''' \
|
||||
ok''', ' ok'
|
||||
|
||||
# Same behavior in interpolated strings.
|
||||
eq """
|
||||
interpolation #{1}
|
||||
follows #{2} \
|
||||
too #{3}\
|
||||
!
|
||||
""", 'interpolation 1\n follows 2 too 3!'
|
||||
|
||||
# TODO: uncomment when #2388 is fixed
|
||||
# eq """a heredoc #{
|
||||
# "inside \
|
||||
# interpolation"
|
||||
# }""", "a heredoc inside interpolation"
|
||||
|
||||
# Handle escaped backslashes correctly.
|
||||
eq '''
|
||||
escaped backslash at EOL\\
|
||||
next line
|
||||
''', 'escaped backslash at EOL\\\n next line'
|
||||
|
||||
# Backslashes at beginning of lines.
|
||||
eq '''first line
|
||||
\ backslash at BOL''', 'first line\n\ backslash at BOL'
|
||||
eq """first line\
|
||||
\ backslash at BOL""", 'first line\ backslash at BOL'
|
||||
|
||||
# Edge case.
|
||||
eq '''lone
|
||||
|
||||
\
|
||||
|
||||
|
||||
|
||||
backslash''', 'lone\n\n backslash'
|
||||
|
||||
#647
|
||||
eq "''Hello, World\\''", '''
|
||||
|
@ -108,10 +174,6 @@ eq "''Hello, World\\''", '''
|
|||
eq '""Hello, World\\""', """
|
||||
"\"Hello, World\\\""
|
||||
"""
|
||||
eq 'Hello, World\n', '''
|
||||
Hello, World\
|
||||
|
||||
'''
|
||||
|
||||
a = """
|
||||
basic heredoc
|
||||
|
|
Loading…
Add table
Reference in a new issue