...

Source file src/github.com/alecthomas/chroma/v2/lexers/http.go

Documentation: github.com/alecthomas/chroma/v2/lexers

     1  package lexers
     2  
     3  import (
     4  	"strings"
     5  
     6  	. "github.com/alecthomas/chroma/v2" // nolint
     7  )
     8  
     9  // HTTP lexer.
    10  var HTTP = Register(httpBodyContentTypeLexer(MustNewLexer(
    11  	&Config{
    12  		Name:         "HTTP",
    13  		Aliases:      []string{"http"},
    14  		Filenames:    []string{},
    15  		MimeTypes:    []string{},
    16  		NotMultiline: true,
    17  		DotAll:       true,
    18  	},
    19  	httpRules,
    20  )))
    21  
    22  func httpRules() Rules {
    23  	return Rules{
    24  		"root": {
    25  			{`(GET|POST|PUT|DELETE|HEAD|OPTIONS|TRACE|PATCH|CONNECT)( +)([^ ]+)( +)(HTTP)(/)([123](?:\.[01])?)(\r?\n|\Z)`, ByGroups(NameFunction, Text, NameNamespace, Text, KeywordReserved, Operator, LiteralNumber, Text), Push("headers")},
    26  			{`(HTTP)(/)([123](?:\.[01])?)( +)(\d{3})( *)([^\r\n]*)(\r?\n|\Z)`, ByGroups(KeywordReserved, Operator, LiteralNumber, Text, LiteralNumber, Text, NameException, Text), Push("headers")},
    27  		},
    28  		"headers": {
    29  			{`([^\s:]+)( *)(:)( *)([^\r\n]+)(\r?\n|\Z)`, EmitterFunc(httpHeaderBlock), nil},
    30  			{`([\t ]+)([^\r\n]+)(\r?\n|\Z)`, EmitterFunc(httpContinuousHeaderBlock), nil},
    31  			{`\r?\n`, Text, Push("content")},
    32  		},
    33  		"content": {
    34  			{`.+`, EmitterFunc(httpContentBlock), nil},
    35  		},
    36  	}
    37  }
    38  
    39  func httpContentBlock(groups []string, state *LexerState) Iterator {
    40  	tokens := []Token{
    41  		{Generic, groups[0]},
    42  	}
    43  	return Literator(tokens...)
    44  }
    45  
    46  func httpHeaderBlock(groups []string, state *LexerState) Iterator {
    47  	tokens := []Token{
    48  		{Name, groups[1]},
    49  		{Text, groups[2]},
    50  		{Operator, groups[3]},
    51  		{Text, groups[4]},
    52  		{Literal, groups[5]},
    53  		{Text, groups[6]},
    54  	}
    55  	return Literator(tokens...)
    56  }
    57  
    58  func httpContinuousHeaderBlock(groups []string, state *LexerState) Iterator {
    59  	tokens := []Token{
    60  		{Text, groups[1]},
    61  		{Literal, groups[2]},
    62  		{Text, groups[3]},
    63  	}
    64  	return Literator(tokens...)
    65  }
    66  
    67  func httpBodyContentTypeLexer(lexer Lexer) Lexer { return &httpBodyContentTyper{lexer} }
    68  
    69  type httpBodyContentTyper struct{ Lexer }
    70  
    71  func (d *httpBodyContentTyper) Tokenise(options *TokeniseOptions, text string) (Iterator, error) { // nolint: gocognit
    72  	var contentType string
    73  	var isContentType bool
    74  	var subIterator Iterator
    75  
    76  	it, err := d.Lexer.Tokenise(options, text)
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  
    81  	return func() Token {
    82  		token := it()
    83  
    84  		if token == EOF {
    85  			if subIterator != nil {
    86  				return subIterator()
    87  			}
    88  			return EOF
    89  		}
    90  
    91  		switch {
    92  		case token.Type == Name && strings.ToLower(token.Value) == "content-type":
    93  			{
    94  				isContentType = true
    95  			}
    96  		case token.Type == Literal && isContentType:
    97  			{
    98  				isContentType = false
    99  				contentType = strings.TrimSpace(token.Value)
   100  				pos := strings.Index(contentType, ";")
   101  				if pos > 0 {
   102  					contentType = strings.TrimSpace(contentType[:pos])
   103  				}
   104  			}
   105  		case token.Type == Generic && contentType != "":
   106  			{
   107  				lexer := MatchMimeType(contentType)
   108  
   109  				// application/calendar+xml can be treated as application/xml
   110  				// if there's not a better match.
   111  				if lexer == nil && strings.Contains(contentType, "+") {
   112  					slashPos := strings.Index(contentType, "/")
   113  					plusPos := strings.LastIndex(contentType, "+")
   114  					contentType = contentType[:slashPos+1] + contentType[plusPos+1:]
   115  					lexer = MatchMimeType(contentType)
   116  				}
   117  
   118  				if lexer == nil {
   119  					token.Type = Text
   120  				} else {
   121  					subIterator, err = lexer.Tokenise(nil, token.Value)
   122  					if err != nil {
   123  						panic(err)
   124  					}
   125  					return EOF
   126  				}
   127  			}
   128  		}
   129  		return token
   130  	}, nil
   131  }
   132  

View as plain text