Skip to content

Commit

Permalink
Add an option to use Rouge's Escape lexer
Browse files Browse the repository at this point in the history
  • Loading branch information
joshuap committed Feb 1, 2023
1 parent d1b3edd commit 6d983bc
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 2 deletions.
1 change: 1 addition & 0 deletions lib/middleman-syntax/extension.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module Middleman
module Syntax
class SyntaxExtension < Extension
option :css_class, 'highlight', 'Class name applied to the syntax-highlighted output.'
option :escape, false, 'Allow escaping in code blocks using "<! … !>". WARNING: Can be a security risk if you don’t control the input. See https://github.com/rouge-ruby/rouge/pull/1152 for details.'
option :line_numbers, false, 'Generate line numbers.'
option :line_numbers_div, false, 'Generate line numbers with wrapping divs.'
option :start_line, 1, 'Start the line numbering (if enabled) at the desired integer'
Expand Down
36 changes: 34 additions & 2 deletions lib/middleman-syntax/highlighter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,42 @@ module Highlighter

# A helper module for highlighting code
def self.highlight(code, language=nil, opts={})
lexer = Rouge::Lexer.find_fancy(language, code) || Rouge::Lexers::PlainText
raw_lexer = Rouge::Lexer.find_fancy(language, code) || Rouge::Lexers::PlainText

if options[:escape]
# #reset! is normally called once by #lex, but since #lex is never
# called on the raw lexer, we need to call it manually. (The escape
# lexer only calls #continue_lex)
# See https://github.com/rouge-ruby/rouge/blob/a4ed658d2778a3e2d3e68873f7221b91149a2ed4/lib/rouge/lexer.rb#LL468C7-L468C13
# and https://github.com/rouge-ruby/rouge/blob/a4ed658d2778a3e2d3e68873f7221b91149a2ed4/lib/rouge/lexers/escape.rb#L44
#
# Otherwise you'll get weird errors w/ some lexers:
#
# NoMethodError: undefined method `continue_lex' for nil:NilClass
# ~/.asdf/installs/ruby/2.7.2/lib/ruby/gems/2.7.0/gems/rouge-3.30.0/lib/rouge/regex_lexer.rb:424:in `delegate'
# ~/.asdf/installs/ruby/2.7.2/lib/ruby/gems/2.7.0/gems/rouge-3.30.0/lib/rouge/lexers/jsx.rb:44:in `block (2 levels) in <class:JSX>'
# ~/.asdf/installs/ruby/2.7.2/lib/ruby/gems/2.7.0/gems/rouge-3.30.0/lib/rouge/regex_lexer.rb:364:in `instance_exec'
# ~/.asdf/installs/ruby/2.7.2/lib/ruby/gems/2.7.0/gems/rouge-3.30.0/lib/rouge/regex_lexer.rb:364:in `block in step'
# ~/.asdf/installs/ruby/2.7.2/lib/ruby/gems/2.7.0/gems/rouge-3.30.0/lib/rouge/regex_lexer.rb:346:in `each'
# ~/.asdf/installs/ruby/2.7.2/lib/ruby/gems/2.7.0/gems/rouge-3.30.0/lib/rouge/regex_lexer.rb:346:in `step'
# ~/.asdf/installs/ruby/2.7.2/lib/ruby/gems/2.7.0/gems/rouge-3.30.0/lib/rouge/regex_lexer.rb:327:in `stream_tokens'
# ~/.asdf/installs/ruby/2.7.2/lib/ruby/gems/2.7.0/gems/rouge-3.30.0/lib/rouge/lexer.rb:480:in `continue_lex'
# ~/.asdf/installs/ruby/2.7.2/lib/ruby/gems/2.7.0/gems/rouge-3.30.0/lib/rouge/lexers/escape.rb:44:in `block in stream_tokens'
raw_lexer.reset!

# See https://github.com/rouge-ruby/rouge/pull/1152
Rouge::Formatter.enable_escape!
lexer = Rouge::Lexers::Escape.new(
start: "<!",
end: "!>",
lang: raw_lexer
)
else
lexer = raw_lexer
end

highlighter_options = options.to_h.merge(opts)
highlighter_options[:css_class] = [ highlighter_options[:css_class], lexer.tag ].join(' ')
highlighter_options[:css_class] = [highlighter_options[:css_class], raw_lexer.tag].join(" ")
lexer_options = highlighter_options.delete(:lexer_options)

formatter = Middleman::Syntax::Formatters::HTML.new(highlighter_options)
Expand Down

0 comments on commit 6d983bc

Please sign in to comment.