diff --git a/internal/css_lexer/css_lexer.go b/internal/css_lexer/css_lexer.go index 0a6152c7b7c..1f24d514aa9 100644 --- a/internal/css_lexer/css_lexer.go +++ b/internal/css_lexer/css_lexer.go @@ -4,7 +4,6 @@ import ( "strings" "unicode/utf8" - "github.com/evanw/esbuild/internal/helpers" "github.com/evanw/esbuild/internal/logger" ) @@ -505,7 +504,7 @@ func (lexer *lexer) consumeToEndOfMultiLineComment(startRange logger.Range) { // Record legal comments if text := lexer.source.Contents[startRange.Loc.Start:commentEnd]; isLegalComment || containsAtPreserveOrAtLicense(text) { - text = helpers.RemoveMultiLineCommentIndent(lexer.source.Contents[:startRange.Loc.Start], text) + text = lexer.source.CommentTextWithoutIndent(logger.Range{Loc: startRange.Loc, Len: int32(commentEnd) - startRange.Loc.Start}) lexer.legalCommentsBefore = append(lexer.legalCommentsBefore, Comment{Loc: startRange.Loc, Text: text}) } return diff --git a/internal/helpers/comment.go b/internal/helpers/comment.go index 6cb02e620e9..95b86845c21 100644 --- a/internal/helpers/comment.go +++ b/internal/helpers/comment.go @@ -2,71 +2,8 @@ package helpers import ( "strings" - "unicode/utf8" ) -func RemoveMultiLineCommentIndent(prefix string, text string) string { - // Figure out the initial indent - indent := 0 -seekBackwardToNewline: - for len(prefix) > 0 { - c, size := utf8.DecodeLastRuneInString(prefix) - switch c { - case '\r', '\n', '\u2028', '\u2029': - break seekBackwardToNewline - } - prefix = prefix[:len(prefix)-size] - indent++ - } - - // Split the comment into lines - var lines []string - start := 0 - for i, c := range text { - switch c { - case '\r', '\n': - // Don't double-append for Windows style "\r\n" newlines - if start <= i { - lines = append(lines, text[start:i]) - } - - start = i + 1 - - // Ignore the second part of Windows style "\r\n" newlines - if c == '\r' && start < len(text) && text[start] == '\n' { - start++ - } - - case '\u2028', '\u2029': - lines = append(lines, text[start:i]) - start = i + 3 - } - } - lines = append(lines, text[start:]) - - // Find the minimum indent over all lines after the first line - for _, line := range lines[1:] { - lineIndent := 0 - for _, c := range line { - if c != ' ' && c != '\t' { - break - } - lineIndent++ - } - if indent > lineIndent { - indent = lineIndent - } - } - - // Trim the indent off of all lines after the first line - for i, line := range lines { - if i > 0 { - lines[i] = line[indent:] - } - } - return strings.Join(lines, "\n") -} - func EscapeClosingTag(text string, slashTag string) string { if slashTag == "" { return text diff --git a/internal/js_lexer/js_lexer.go b/internal/js_lexer/js_lexer.go index 3fc7ac093f3..637a828138a 100644 --- a/internal/js_lexer/js_lexer.go +++ b/internal/js_lexer/js_lexer.go @@ -239,7 +239,7 @@ type MaybeSubstring struct { } type Lexer struct { - LegalCommentsBeforeToken []js_ast.Comment + LegalCommentsBeforeToken []logger.Range WebpackComments *[]js_ast.Comment AllOriginalComments []logger.Range Identifier MaybeSubstring @@ -2648,21 +2648,14 @@ func (lexer *Lexer) scanCommentText() { } } - if isMultiLineComment && (hasLegalAnnotation || isWebpackComment) { - text = helpers.RemoveMultiLineCommentIndent(lexer.source.Contents[:lexer.start], text) - } - if hasLegalAnnotation { - lexer.LegalCommentsBeforeToken = append(lexer.LegalCommentsBeforeToken, js_ast.Comment{ - Loc: logger.Loc{Start: int32(lexer.start)}, - Text: text, - }) + lexer.LegalCommentsBeforeToken = append(lexer.LegalCommentsBeforeToken, lexer.Range()) } if isWebpackComment { *lexer.WebpackComments = append(*lexer.WebpackComments, js_ast.Comment{ Loc: logger.Loc{Start: int32(lexer.start)}, - Text: text, + Text: lexer.source.CommentTextWithoutIndent(lexer.Range()), }) } } diff --git a/internal/js_parser/js_parser.go b/internal/js_parser/js_parser.go index 3626317bf56..5b883404c2b 100644 --- a/internal/js_parser/js_parser.go +++ b/internal/js_parser/js_parser.go @@ -7368,7 +7368,7 @@ func (p *parser) parseStmtsUpTo(end js_lexer.T, opts parseStmtOpts) []js_ast.Stm stmts = append(stmts, js_ast.Stmt{ Loc: comment.Loc, Data: &js_ast.SComment{ - Text: comment.Text, + Text: p.source.CommentTextWithoutIndent(comment), IsLegalComment: true, }, }) diff --git a/internal/logger/logger.go b/internal/logger/logger.go index b861c7e7827..b77d58255cc 100644 --- a/internal/logger/logger.go +++ b/internal/logger/logger.go @@ -455,6 +455,74 @@ func (s *Source) RangeOfLegacyOctalEscape(loc Loc) (r Range) { return } +func (s *Source) CommentTextWithoutIndent(r Range) string { + text := s.Contents[r.Loc.Start:r.End()] + if len(text) < 2 || !strings.HasPrefix(text, "/*") { + return text + } + prefix := s.Contents[:r.Loc.Start] + + // Figure out the initial indent + indent := 0 +seekBackwardToNewline: + for len(prefix) > 0 { + c, size := utf8.DecodeLastRuneInString(prefix) + switch c { + case '\r', '\n', '\u2028', '\u2029': + break seekBackwardToNewline + } + prefix = prefix[:len(prefix)-size] + indent++ + } + + // Split the comment into lines + var lines []string + start := 0 + for i, c := range text { + switch c { + case '\r', '\n': + // Don't double-append for Windows style "\r\n" newlines + if start <= i { + lines = append(lines, text[start:i]) + } + + start = i + 1 + + // Ignore the second part of Windows style "\r\n" newlines + if c == '\r' && start < len(text) && text[start] == '\n' { + start++ + } + + case '\u2028', '\u2029': + lines = append(lines, text[start:i]) + start = i + 3 + } + } + lines = append(lines, text[start:]) + + // Find the minimum indent over all lines after the first line + for _, line := range lines[1:] { + lineIndent := 0 + for _, c := range line { + if c != ' ' && c != '\t' { + break + } + lineIndent++ + } + if indent > lineIndent { + indent = lineIndent + } + } + + // Trim the indent off of all lines after the first line + for i, line := range lines { + if i > 0 { + lines[i] = line[indent:] + } + } + return strings.Join(lines, "\n") +} + func plural(prefix string, count int, shown int, someAreMissing bool) string { var text string if count == 1 {