lib/middleman-syntax/extension.rb in middleman-syntax-1.2.1 vs lib/middleman-syntax/extension.rb in middleman-syntax-2.0.0
- old
+ new
@@ -1,87 +1,113 @@
+require 'rouge'
+
module Middleman
module Syntax
- class << self
+ class SyntaxExtension < Extension
+ option :css_class, 'highlight', 'Class name applied to the syntax-highlighted output.'
+ option :line_numbers, false, 'Generate line numbers.'
+ option :inline_theme, nil, 'A Rouge::CSSTheme that will be used to highlight the output with inline styles instead of using CSS classes.'
+ option :wrap, true, 'Wrap the highlighted content in a container (<pre> or <div>, depending on whether :line_numbers is on).'
+ option :lexer_options, {}, 'Options for the Rouge lexers.'
- def options
- @@options
+ def after_configuration
+ Middleman::Syntax::Highlighter.options = options
+
+ if app.config[:markdown_engine] == :redcarpet
+ require 'middleman-core/renderers/redcarpet'
+ Middleman::Renderers::MiddlemanRedcarpetHTML.send :include, RedcarpetCodeRenderer
+ elsif app.config[:markdown_engine] == :kramdown
+ require 'kramdown'
+ Kramdown::Converter::Html.class_eval do
+ def convert_codeblock(el, indent)
+ attr = el.attr.dup
+ language = extract_code_language!(attr)
+ Middleman::Syntax::Highlighter.highlight(el.value, language)
+ end
+ end
+ end
end
- def registered(app, options_hash={})
- require 'rouge'
+ helpers do
+ # Output highlighted code. Use like:
+ #
+ # <% code('ruby') do %>
+ # my code
+ # <% end %>
+ #
+ # To produce the following structure:
+ #
+ # <div class="highlight">
+ # <pre>#{your code}
+ # </pre>
+ # </div>
+ #
+ # @param [String] language the Rouge lexer to use
+ # @param [Hash] Options to pass to the Rouge formatter & lexer, overriding global options set by :highlighter_options.
+ def code(language=nil, options={}, &block)
+ raise 'The code helper requires a block to be provided.' unless block_given?
- @@options = options_hash
- yield @@options if block_given?
+ # Save current buffer for later
+ @_out_buf, _buf_was = "", @_out_buf
- app.send :include, Helper
-
- app.after_configuration do
- if markdown_engine == :redcarpet
- require 'middleman-core/renderers/redcarpet'
- Middleman::Renderers::MiddlemanRedcarpetHTML.send :include, MarkdownCodeRenderer
- elsif markdown_engine == :kramdown
- require 'kramdown'
- Kramdown::Converter::Html.class_eval do
- def convert_codeblock(el, indent)
- attr = el.attr.dup
- language = extract_code_language!(attr)
- Middleman::Syntax::Highlighter.highlight(el.value, language)
- end
- end
+ begin
+ content = capture_html(&block)
+ ensure
+ # Reset stored buffer
+ @_out_buf = _buf_was
end
+ content = content.encode(Encoding::UTF_8)
+
+ concat_content Middleman::Syntax::Highlighter.highlight(content, language).html_safe
end
end
- alias :included :registered
end
- module Highlighter
- # A helper module for highlighting code
- def self.highlight(code, language)
- opts = ::Middleman::Syntax.options.dup
- lexer = Rouge::Lexer.find_fancy(language, code) || Rouge::Lexers::Text
- formatter = Rouge::Formatters::HTML.new(opts.reverse_merge({ :css_class => "highlight #{lexer.tag}" }))
- formatter.format(lexer.lex(code, opts))
+ # A mixin for the Redcarpet Markdown renderer that will highlight
+ # code.
+ module RedcarpetCodeRenderer
+ def block_code(code, language)
+ Middleman::Syntax::Highlighter.highlight(code, language)
end
end
- module Helper
+ module Highlighter
+ mattr_accessor :options
- # Output highlighted code. Use like:
- #
- # <% code('ruby') do %>
- # my code
- # <% end %>
- #
- # To produce the following structure:
- #
- # <div class="highlight">
- # <pre>#{your code}
- # </pre>
- # </div>
- #
- # @param [String] language the Pygments lexer to use
- def code(language=nil, &block)
- # Save current buffer for later
- @_out_buf, _buf_was = "", @_out_buf
+ # A helper module for highlighting code
+ def self.highlight(code, language=nil, opts={})
+ lexer = Rouge::Lexer.find_fancy(language, code) || Rouge::Lexers::PlainText
- begin
- content = if block_given?
- capture_html(&block)
- else
- ""
- end
- ensure
- # Reset stored buffer
- @_out_buf = _buf_was
- end
+ highlighter_options = options.to_h.merge(opts)
+ highlighter_options[:css_class] = [ highlighter_options[:css_class], lexer.tag ].join(' ')
+ lexer_options = highlighter_options.delete(:lexer_options)
- concat_content Middleman::Syntax::Highlighter.highlight(content, language)
+ formatter = Rouge::Formatters::HTML.new(highlighter_options)
+ formatter.format(lexer.lex(code, options.lexer_options))
end
end
+ end
+end
- module MarkdownCodeRenderer
- def block_code(code, language)
- Middleman::Syntax::Highlighter.highlight(code, language)
+# If Haml is around, define a :code filter that can be used to more conveniently output highlighted code.
+if defined? Haml
+ module Haml
+ module Filters
+ module Code
+ include Base
+
+ def render(code)
+ code = code.encode(Encoding::UTF_8)
+
+ # Allow language to be specified via a special comment like:
+ # # lang: ruby
+ if code.lines.first =~ /\A\s*#\s*lang:\s*(\w+)$/
+ language = $1
+ code = code.lines.to_a[1..-1].join # Strip first line
+ end
+
+ Middleman::Syntax::Highlighter.highlight(code, language)
+ end
end
end
end
end