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
|
# -*- coding: utf-8 -*- #
# frozen_string_literal: true
module Rouge
module Lexers
class HTTP < RegexLexer
tag 'http'
title "HTTP"
desc 'http requests and responses'
option :content, "the language for the content (default: auto-detect)"
def self.http_methods
@http_methods ||= %w(GET POST PUT DELETE HEAD OPTIONS TRACE PATCH QUERY)
end
def content_lexer
@content_lexer ||= (lexer_option(:content) || guess_content_lexer)
end
def guess_content_lexer
return Lexers::PlainText unless @content_type
Lexer.guess_by_mimetype(@content_type)
rescue Lexer::AmbiguousGuess
Lexers::PlainText
end
start { @content_type = 'text/plain' }
state :root do
# request
rule %r(
(#{HTTP.http_methods.join('|')})([ ]+) # method
([^ ]+)([ ]+) # path
(HTTPS?)(/)(\d(?:\.\d)?)(\r?\n|$) # http version
)ox do
groups(
Name::Function, Text,
Name::Namespace, Text,
Keyword, Operator, Num, Text
)
push :headers
end
# response
rule %r(
(HTTPS?)(/)(\d(?:\.\d)?)([ ]+) # http version
(\d{3})([ ]+)? # status
([^\r\n]*)?(\r?\n|$) # status message
)x do
groups(
Keyword, Operator, Num, Text,
Num, Text,
Name::Exception, Text
)
push :headers
end
end
state :headers do
rule %r/([^\s:]+)( *)(:)( *)([^\r\n]+)(\r?\n|$)/ do |m|
key = m[1]
value = m[5]
if key.strip.casecmp('content-type').zero?
@content_type = value.split(';')[0].downcase
end
groups Name::Attribute, Text, Punctuation, Text, Str, Text
end
rule %r/([^\r\n]+)(\r?\n|$)/ do
groups Str, Text
end
rule %r/\r?\n/, Text, :content
end
state :content do
rule %r/.+/m do
delegate(content_lexer)
end
end
end
end
end
|