@@ -6,32 +6,27 @@ module Formatters
6
6
class HTMLLegacy < Formatter
7
7
tag 'html_legacy'
8
8
9
- # @option opts [String] :css_class ('highlight')
10
- # @option opts [true/false] :line_numbers (false)
11
- # @option opts [true/false] :linewise (false)
12
- # @option opts [RougeLines::CSSTheme] :inline_theme (nil)
13
- # @option opts [true/false] :wrap (true)
14
- #
15
- # Initialize with options.
16
- #
17
- # If `:inline_theme` is given, then instead of rendering the
18
- # tokens as <span> tags with CSS classes, the styles according to
19
- # the given theme will be inlined in "style" attributes. This is
20
- # useful for formats in which stylesheets are not available.
21
- #
22
- # Content will be wrapped in a tag (`div` if tableized, `pre` if
23
- # not) with the given `:css_class` unless `:wrap` is set to `false`.
24
- def initialize ( opts = { } )
25
- @formatter = opts [ :inline_theme ] ? HTMLInline . new ( opts [ :inline_theme ] )
26
- : HTML . new
27
-
28
- @formatter = HTMLLinewise . new ( @formatter , opts ) if opts [ :linewise ]
29
-
30
- @formatter = HTMLTable . new ( @formatter , opts ) if opts [ :line_numbers ]
31
-
32
- if opts . fetch ( :wrap , true )
33
- @formatter = HTMLPygments . new ( @formatter , opts . fetch ( :css_class , 'codehilite' ) )
34
- end
9
+ DEFAULT_OPTS = {
10
+ css_class : 'highlight' ,
11
+ line_numbers : false ,
12
+ linewise : false ,
13
+ inline_theme : nil ,
14
+ wrap : true
15
+ }
16
+
17
+ def initialize ( opts = { } )
18
+ opts = DEFAULT_OPTS . merge ( opts )
19
+ @formatter = select_formatter ( opts )
20
+ end
21
+
22
+ private
23
+
24
+ def select_formatter ( opts )
25
+ formatter = opts [ :inline_theme ] ? HTMLInline . new ( opts [ :inline_theme ] ) : HTML . new
26
+ formatter = HTMLLinewise . new ( formatter , opts ) if opts [ :linewise ]
27
+ formatter = HTMLTable . new ( formatter , opts ) if opts [ :line_numbers ]
28
+ formatter = HTMLPygments . new ( formatter , opts . fetch ( :css_class , 'codehilite' ) ) if opts . fetch ( :wrap , true )
29
+ formatter
35
30
end
36
31
end
37
32
end
@@ -42,98 +37,53 @@ module Tags
42
37
class HighlightBlock < Liquid ::Block
43
38
include Liquid ::StandardFilters
44
39
40
+ OPTIONS_REGEX = %r!(?:\w ="[^"]*"|\w =\w |\w )+!
41
+ SYNTAX = %r!^([a-zA-Z0-9_+-]+)\s *(\S .*)?$!
42
+
45
43
def initialize ( tag_name , markup , tokens )
46
44
super
47
45
if markup . strip =~ SYNTAX
48
46
@lang = Regexp . last_match ( 1 ) . downcase
49
- @highlight_options = parse_options ( Regexp . last_match ( 2 ) )
47
+ @highlight_options = parse_options ( Regexp . last_match ( 2 ) || "" )
50
48
else
51
- raise SyntaxError , <<-MSG
52
- Syntax Error in tag 'highlight' while parsing the following markup:
53
-
54
- #{ markup }
55
-
56
- Valid syntax: highlight <lang> [linenos] [linedivs]
57
- MSG
49
+ raise SyntaxError , "Syntax Error in tag 'highlight' while parsing: #{ markup . strip } . Valid syntax: highlight <lang> [linenos] [linedivs]"
58
50
end
59
51
end
60
52
61
53
def render ( context )
62
- prefix = " " \
63
- "
64
- <div class=\" code-container\" >
65
- <div class=\" code-window\" >
66
- <div class=\" window-header\" >
67
- <div class=\" window-controls\" >
68
- <svg xmlns=\" http://www.w3.org/2000/svg\" width=\" 54\" height=\" 14\" viewBox=\" 0 0 54 14\" >
69
- <g fill=\" none\" fillRule=\" evenodd\" transform=\" translate(1 1)\" >
70
- <circle cx=\" 6\" cy=\" 6\" r=\" 6\" fill=\" #EC6A5E\" stroke=\" #EC6A5E\" strokeWidth=\" .5\" />
71
- <circle cx=\" 26\" cy=\" 6\" r=\" 6\" fill=\" #F4BF4F\" stroke=\" #F4BF4F\" strokeWidth=\" .5\" />
72
- <circle cx=\" 46\" cy=\" 6\" r=\" 6\" fill=\" #61C554\" stroke=\" #61C554\" strokeWidth=\" .5\" />
73
- </g>
74
- </svg>
75
- </div>
76
- <div class=\" window-copy\" >
77
- <svg xmlns=\" http://www.w3.org/2000/svg\" class=\" window-copy-icon\" height=\" 24\" width=\" 24\" fill=\" none\" viewBox=\" 0 0 24 24\" stroke=\" currentColor\" stroke-width=\" 1.5\" >
78
- <path class=\" with-check\" stroke-linecap=\" round\" stroke-linejoin=\" round\" d=\" M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\" ></path>
79
- <path class=\" without-check\" stroke-linecap=\" round\" stroke-linejoin=\" round\" d=\" M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\" ></path>
80
- </svg>
81
- </div>
82
- </div>
83
- "
84
- suffix = " " \
85
- "
86
- <div class=\" code-label\" >
87
- #{ @lang . capitalize }
88
- </div>
89
- </div>
90
- </div>
91
- "
92
- code = super . to_s . gsub ( %r!\A (\n |\r )+|(\n |\r )+\z ! , "" )
93
-
54
+ code = super . to_s . strip
94
55
is_safe = !!context . registers [ :site ] . safe
95
56
96
- output =
97
- case context . registers [ :site ] . highlighter
98
- when "pygments"
99
- render_pygments ( code , is_safe )
100
- when "rouge"
101
- render_rouge ( code )
102
- else
103
- render_codehighlighter ( code )
104
- end
57
+ output = case context . registers [ :site ] . highlighter
58
+ when "pygments"
59
+ render_pygments ( code , is_safe )
60
+ when "rouge"
61
+ render_rouge ( code )
62
+ else
63
+ render_codehighlighter ( code )
64
+ end
105
65
106
66
rendered_output = add_code_tag ( output )
107
- prefix + rendered_output + suffix
67
+ " #{ prefix_html } #{ rendered_output } #{ suffix_html } "
108
68
end
109
69
110
70
def sanitized_opts ( opts , is_safe )
111
71
if is_safe
112
- Hash [ [
113
- [ :startinline , opts . fetch ( :startinline , nil ) ] ,
114
- [ :hl_lines , opts . fetch ( :hl_lines , nil ) ] ,
115
- [ :linenos , opts . fetch ( :linenos , nil ) ] ,
116
- [ :linedivs , opts . fetch ( :linedivs , nil ) ] ,
117
- [ :encoding , opts . fetch ( :encoding , "utf-8" ) ] ,
118
- [ :cssclass , opts . fetch ( :cssclass , nil ) ] ,
119
- ] . reject { |f | f . last . nil? } ]
72
+ opts . slice ( :startinline , :hl_lines , :linenos , :linedivs , :encoding , :cssclass ) . compact
120
73
else
121
74
opts
122
75
end
123
76
end
124
77
125
- private
126
-
127
- OPTIONS_REGEX = %r!(?:\w ="[^"]*"|\w =\w |\w )+!
78
+ private
128
79
129
80
def parse_options ( input )
130
81
options = { }
131
82
return options if input . empty?
132
83
133
- # Split along 3 possible forms -- key="<quoted list>", key=value, or key
134
84
input . scan ( OPTIONS_REGEX ) do |opt |
135
- key , value = opt . split ( "=" )
136
- # If a quoted list, convert to array
85
+ key , value = opt . split ( "=" , 2 )
86
+ # Si la valeur est une chaîne entre guillemets
137
87
if value && value . include? ( '"' )
138
88
value . delete! ( '"' )
139
89
value = value . split
@@ -147,16 +97,54 @@ def parse_options(input)
147
97
148
98
def render_rouge ( code )
149
99
formatter = ::Rouge ::Formatters ::HTMLLegacy . new (
150
- : line_numbers => @highlight_options [ :linenos ] ,
151
- : linewise => @highlight_options [ :linedivs ] ,
152
- : wrap => false ,
153
- : css_class => "highlight" ,
154
- : gutter_class => "gutter" ,
155
- : code_class => "code"
100
+ line_numbers : @highlight_options [ :linenos ] ,
101
+ linewise : @highlight_options [ :linedivs ] ,
102
+ wrap : false ,
103
+ css_class : "highlight" ,
104
+ gutter_class : "gutter" ,
105
+ code_class : "code"
156
106
)
157
- lexer = ::Rouge ::Lexer . find_fancy ( @lang , code ) || Rouge ::Lexers ::PlainText
107
+ lexer = ::Rouge ::Lexer . find_fancy ( @lang , code )
108
+ unless lexer
109
+ lexer = Rouge ::Lexers ::PlainText
110
+ puts "Warning: Language '#{ @lang } ' not found. Defaulting to plain text."
111
+ end
158
112
formatter . format ( lexer . lex ( code ) )
159
113
end
114
+
115
+ def prefix_html
116
+ <<~HTML
117
+ < div class ="code-container ">
118
+ < div class ="code-window ">
119
+ < div class ="window-header ">
120
+ < div class ="window-controls ">
121
+ < svg xmlns ="http://www.w3.org/2000/svg " width ="54 " height ="14 " viewBox ="0 0 54 14 ">
122
+ < g fill ="none " fill-rule ="evenodd " transform ="translate(1 1) ">
123
+ < circle cx ="6 " cy ="6 " r ="6 " fill ="#EC6A5E " stroke ="#EC6A5E " stroke-width =".5 " />
124
+ < circle cx ="26 " cy ="6 " r ="6 " fill ="#F4BF4F " stroke ="#F4BF4F " stroke-width =".5 " />
125
+ < circle cx ="46 " cy ="6 " r ="6 " fill ="#61C554 " stroke ="#61C554 " stroke-width =".5 " />
126
+ </ g >
127
+ </ svg >
128
+ </ div >
129
+ < div class ="window-copy ">
130
+ < svg xmlns ="http://www.w3.org/2000/svg " class ="window-copy-icon " height ="24 " width ="24 " fill ="none " viewBox ="0 0 24 24 " stroke ="currentColor " stroke-width ="1.5 ">
131
+ < path class ="with-check " stroke-linecap ="round " stroke-linejoin ="round " d ="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4 "> </ path >
132
+ < path class ="without-check " stroke-linecap ="round " stroke-linejoin ="round " d ="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2 "> </ path >
133
+ </ svg >
134
+ </ div >
135
+ </ div >
136
+ HTML
137
+ end
138
+
139
+ def suffix_html
140
+ <<~HTML
141
+ < div class ="code-label ">
142
+ #{ @lang . capitalize }
143
+ </ div>
144
+ </ div>
145
+ </ div>
146
+ HTML
147
+ end
160
148
end
161
149
end
162
150
end
0 commit comments