From 90cf0323db24d5fe2e326f9a413d85a49402f5a9 Mon Sep 17 00:00:00 2001 From: Kornelius Kalnbach Date: Sat, 31 Aug 2013 16:09:34 +0200 Subject: [PATCH 1/9] cache escaped tokens, reduce HTML enc setup time --- lib/coderay/encoders/html.rb | 17 ++++++++--- lib/coderay/encoders/html/css.rb | 46 ++++++++++++++--------------- lib/coderay/encoders/html/output.rb | 2 +- 3 files changed, 37 insertions(+), 28 deletions(-) diff --git a/lib/coderay/encoders/html.rb b/lib/coderay/encoders/html.rb index d2ebb5af..0f387265 100644 --- a/lib/coderay/encoders/html.rb +++ b/lib/coderay/encoders/html.rb @@ -178,10 +178,19 @@ def setup options @out = '' end + @tab_replacement = ' ' * options[:tab_width] + @escape_cache = Hash.new do |cache, text| + cache.clear if cache.size >= 100 + + cache[text] = + if text =~ /#{HTML_ESCAPE_PATTERN}/o + text.gsub(/#{HTML_ESCAPE_PATTERN}/o) { |m| m == "\t" ? @tab_replacement : HTML_ESCAPE[m] } + else + text + end + end @break_lines = (options[:break_lines] == true) - @HTML_ESCAPE = HTML_ESCAPE.merge("\t" => ' ' * options[:tab_width]) - @opened = [] @last_opened = nil @css = CSS.new options[:style] @@ -197,7 +206,7 @@ def finish options @last_opened = nil end - if @out.respond_to? :to_str + if options[:wrap] || options[:line_numbers] @out.extend Output @out.css = @css if options[:line_numbers] @@ -220,7 +229,7 @@ def finish options def text_token text, kind style = @span_for_kinds[@last_opened ? [kind, *@opened] : kind] - text = text.gsub(/#{HTML_ESCAPE_PATTERN}/o) { |m| @HTML_ESCAPE[m] } if text =~ /#{HTML_ESCAPE_PATTERN}/o + text = @escape_cache[text] if text.size <= 1 || text =~ /#{HTML_ESCAPE_PATTERN}/o text = break_lines(text, style) if @break_lines && (style || @opened.size > 0) && text.index("\n") if style diff --git a/lib/coderay/encoders/html/css.rb b/lib/coderay/encoders/html/css.rb index 164d7f85..32470b47 100644 --- a/lib/coderay/encoders/html/css.rb +++ b/lib/coderay/encoders/html/css.rb @@ -3,25 +3,23 @@ module Encoders class HTML class CSS # :nodoc: - - attr :stylesheet - - def CSS.load_stylesheet style = nil - CodeRay::Styles[style] - end - def initialize style = :default - @styles = Hash.new - style = CSS.load_stylesheet style - @stylesheet = [ - style::CSS_MAIN_STYLES, - style::TOKEN_COLORS.gsub(/^(?!$)/, '.CodeRay ') + @style = style + end + + def stylesheet + @stylesheet ||= CodeRay::Styles[@style] + end + + def css + [ + stylesheet::CSS_MAIN_STYLES, + stylesheet::TOKEN_COLORS.gsub(/^(?!$)/, '.CodeRay ') ].join("\n") - parse style::TOKEN_COLORS end - + def get_style_for_css_classes css_classes - cl = @styles[css_classes.first] + cl = styles[css_classes.first] return '' unless cl style = '' 1.upto css_classes.size do |offset| @@ -46,14 +44,16 @@ def get_style_for_css_classes css_classes | ( [^\n]+ ) # $3 = error /mx - def parse stylesheet - stylesheet.scan CSS_CLASS_PATTERN do |selectors, style, error| - raise "CSS parse error: '#{error.inspect}' not recognized" if error - for selector in selectors.split(',') - classes = selector.scan(/[-\w]+/) - cl = classes.pop - @styles[cl] ||= Hash.new - @styles[cl][classes] = style.to_s.strip.delete(' ').chomp(';') + def styles + @styles ||= Hash.new.tap do |styles| + stylesheet::TOKEN_COLORS.scan CSS_CLASS_PATTERN do |selectors, style, error| + raise "CSS parse error: '#{error.inspect}' not recognized" if error + for selector in selectors.split(',') + classes = selector.scan(/[-\w]+/) + cl = classes.pop + styles[cl] ||= Hash.new + styles[cl][classes] = style.to_s.strip.delete(' ').chomp(';') + end end end end diff --git a/lib/coderay/encoders/html/output.rb b/lib/coderay/encoders/html/output.rb index de6f6ea1..d3b676ce 100644 --- a/lib/coderay/encoders/html/output.rb +++ b/lib/coderay/encoders/html/output.rb @@ -24,7 +24,7 @@ def extended o # :nodoc: end def make_stylesheet css, in_tag = false # :nodoc: - sheet = css.stylesheet + sheet = css.css sheet = <<-'CSS' if in_tag