diff --git a/lib/org-ruby/highlighter.rb b/lib/org-ruby/highlighter.rb new file mode 100644 index 0000000..91fe0d4 --- /dev/null +++ b/lib/org-ruby/highlighter.rb @@ -0,0 +1,61 @@ +module Orgmode + # Highlight code + module Highlighter + def self.highlight(code, lang) + highlighter = guess_highlighter + highlighter.highlight(code, lang) + end + + def self.guess_highlighter + return RougeHighliter if gem_present?('rouge') + return PygmentsHighliter if gem_present?('pygments.rb') + return CodeRayHighliter if gem_present?('coderay') + + DefaultHighliter + end + + def self.gem_present?(gem) + Gem::Specification.find_all_by_name(gem).any? + end + + # Default highliter does nothing to code + class DefaultHighliter + def self.highlight(buffer, _lang) + buffer + end + end + + # Pygments wrapper + class PygmentsHighliter + def self.highlight(buffer, lang) + require 'pygments' + if Pygments::Lexer.find_by_alias(lang) + Pygments.highlight(buffer, lexer: lang) + else + Pygments.highlight(buffer, lexer: 'text') + end + end + end + + # CodeRay wrapper + class CodeRayHighliter + def self.highlight(buffer, lang) + require 'coderay' + CodeRay.scan(buffer, lang).html(wrap: nil, css: :style) + rescue ArgumentError => _e + CodeRay.scan(buffer, 'text').html(wrap: nil, css: :style) + end + end + + # Rouge wrapper + class RougeHighliter + def self.highlight(buffer, lang) + require 'rouge' + formatter = Rouge::Formatters::HTMLLegacy.new + lexer = Rouge::Lexer.find_fancy(lang, buffer) || + Rouge::Lexers::PlainText + formatter.format(lexer.lex(buffer.strip)) + end + end + end +end diff --git a/lib/org-ruby/html_output_buffer.rb b/lib/org-ruby/html_output_buffer.rb index 180bd80..a3f9724 100644 --- a/lib/org-ruby/html_output_buffer.rb +++ b/lib/org-ruby/html_output_buffer.rb @@ -1,7 +1,7 @@ module Orgmode class HtmlOutputBuffer < OutputBuffer - + require_relative './highlighter.rb' HtmlBlockTag = { :paragraph => "p", :ordered_list => "ol", @@ -37,20 +37,6 @@ def initialize(output, opts = {}) @unclosed_tags = [] @logger.debug "HTML export options: #{@options.inspect}" @custom_blocktags = {} if @options[:markup_file] - - unless @options[:skip_syntax_highlight] - begin - require 'pygments' - rescue LoadError - # Pygments is not supported so we try instead with CodeRay - begin - require 'coderay' - rescue LoadError - # No code syntax highlighting - end - end - end - if @options[:markup_file] do_custom_markup end @@ -64,7 +50,7 @@ def push_mode(mode, indent, properties={}) super(mode, indent, properties) if HtmlBlockTag[mode] unless ((mode_is_table?(mode) and skip_tables?) or - (mode == :src and !@options[:skip_syntax_highlight] and defined? Pygments)) + (mode == :src and !@options[:skip_syntax_highlight])) css_class = case when (mode == :src and @block_lang.empty?) " class=\"src\"" @@ -100,7 +86,7 @@ def pop_mode(mode = nil) m = super(mode) if HtmlBlockTag[m] unless ((mode_is_table?(m) and skip_tables?) or - (m == :src and !@options[:skip_syntax_highlight] and defined? Pygments)) + (m == :src and !@options[:skip_syntax_highlight])) add_paragraph if @new_paragraph @new_paragraph = true @logger.debug "" @@ -110,6 +96,10 @@ def pop_mode(mode = nil) @list_indent_stack.pop end + def highlight(code, lang) + Highlighter.highlight code, lang + end + def flush! return false if @buffer.empty? case @@ -121,29 +111,9 @@ def flush! case when (current_mode == :src and @options[:skip_syntax_highlight]) @buffer = escapeHTML @buffer - when (current_mode == :src and defined? Pygments) + when (current_mode == :src) lang = normalize_lang @block_lang - @output << "\n" unless @new_paragraph == :start - @new_paragraph = true - - begin - @buffer = Pygments.highlight(@buffer, :lexer => lang) - rescue - # Not supported lexer from Pygments, we fallback on using the text lexer - @buffer = Pygments.highlight(@buffer, :lexer => 'text') - end - when (current_mode == :src and defined? CodeRay) - lang = normalize_lang @block_lang - - # CodeRay might throw a warning when unsupported lang is set, - # then fallback to using the text lexer - silence_warnings do - begin - @buffer = CodeRay.scan(@buffer, lang).html(:wrap => nil, :css => :style) - rescue ArgumentError - @buffer = CodeRay.scan(@buffer, 'text').html(:wrap => nil, :css => :style) - end - end + @buffer = highlight @buffer, lang when (current_mode == :html or current_mode == :raw_text) @buffer.gsub!(/\A\n/, "") if @new_paragraph == :start @new_paragraph = true