Class: CodeHighlighter

Inherits:
Object
  • Object
show all
Defined in:
lib/highlight-code.rb

Constant Summary collapse

CODERAY_CSS_FILE_NAME =
"coderay.css"
HIGHLIGHTED_EXTENSION =
".highlighted.xhtml"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = { }) ⇒ CodeHighlighter

Returns a new instance of CodeHighlighter.



14
15
16
17
18
19
# File 'lib/highlight-code.rb', line 14

def initialize(options = { })
  self.code_nodes = Array.new
  self.output_file_path = nil
  self.options = options
  return self
end

Instance Attribute Details

#code_nodesObject

Returns the value of attribute code_nodes.



9
10
11
# File 'lib/highlight-code.rb', line 9

def code_nodes
  @code_nodes
end

#docObject

Returns the value of attribute doc.



9
10
11
# File 'lib/highlight-code.rb', line 9

def doc
  @doc
end

#optionsObject

Returns the value of attribute options.



9
10
11
# File 'lib/highlight-code.rb', line 9

def options
  @options
end

#output_file_pathObject

Returns the value of attribute output_file_path.



9
10
11
# File 'lib/highlight-code.rb', line 9

def output_file_path
  @output_file_path
end

Class Method Details

.highlight(path, options = { }) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/highlight-code.rb', line 27

def self.highlight(path, options = { })
  ch = CodeHighlighter.parse path, options
  return nil unless ch.doc
  
  begin
    ch.highlight
    ch.save
  rescue Object => ex
    puts "Cannot highlight #{path} due to: #{ex}"
  end
  
  @output_file_path
end

.parse(path, options = { }) ⇒ Object



21
22
23
24
25
# File 'lib/highlight-code.rb', line 21

def self.parse(path, options = { })
  ch = CodeHighlighter.new options
  ch.parse path
  ch
end

Instance Method Details

#highlightObject



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/highlight-code.rb', line 63

def highlight
  puts "Highlight with options: #{@options}"
  
  @code_nodes.each do | code_node |
    brush = code_node['class']
    brush_spec = brush ? brush.split(' ') : [ ]
    language_code = (brush_spec.count > 1) ? brush_spec.last : "N/A"
    
    if language_code != "N/A"
      puts "Found node #{language_code} #{code_node.text}"
      
      # Highlight the code 
      highlighted_code = CodeRay.scan(code_node.text.strip, language_code.to_sym).div(:css => :class, :tab_width => 4, :line_numbers => :inline)

      # Transform the pre node into a div
      code_node.name = "div"
      code_node['class'] = "code"
      code_node.content=  ''
      
      highlighted_code_node = Nokogiri::XML(highlighted_code)
      code_node.add_child highlighted_code_node.children.first
    else
      puts "Found unrecognizable language in source: #{code_node.text}"        
    end #if
  end #each
end

#include_cssObject

def



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/highlight-code.rb', line 90

def include_css
  code_ray_css_node = @doc.css("link[href*='" + CODERAY_CSS_FILE_NAME + "']")
  return unless code_ray_css_node.count == 0
  
  src_css_file_path  = File.dirname(__FILE__) + '/../resources/' + CODERAY_CSS_FILE_NAME

  dest_directory     = File.dirname(@path)
  css_path = @options[:csspath] || dest_directory
  dest_css_file_path = dest_directory + '/' + CODERAY_CSS_FILE_NAME
  FileUtils.copy_file(src_css_file_path, dest_css_file_path)
  puts "Created the CSS file: #{dest_css_file_path}"
  
  code_ray_css_node = Nokogiri::XML::Node.new "link", @doc
  code_ray_css_node['rel'] = 'stylesheet'
  code_ray_css_node['type'] = 'text/css'
  code_ray_css_node['href'] = CODERAY_CSS_FILE_NAME
  
  head_node = @doc.css('head').first
  unless head_node
    head_node = Nokogiri::XML::Node.new "head", @doc
    body_node = @doc.css('body').first
    body_node.add_child head_node
  end
  
  head_node.add_child code_ray_css_node
  puts "Added CSS: #{code_ray_css_node}"
end

#parse(path) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/highlight-code.rb', line 41

def parse (path)
  begin
    # get the file contents
    @path = path
    puts "Parsing #{@path}"
    f = File.open(@path)
    
    # parse the file
    @doc = Nokogiri::XML(f)
    
    # find code/pre or both tag(s)
    tag = @options[:tag] || 'both'
    tag = 'code,pre' if tag == 'both'
    @code_nodes = doc.css(tag)
    puts "Found #{@code_nodes.length} nodes"
  rescue Object => ex
    puts "Cannot open #{path} due to: #{ex}"
  ensure
    f.close
  end
end

#saveObject



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/highlight-code.rb', line 118

def save
  include_css
  
  begin
    extension = @options[:extension] || HIGHLIGHTED_EXTENSION
    @output_file_path = @path + extension
    puts "Saving result to #{@output_file_path} ..."
    f = File.open(@output_file_path, "w")
    f.write(@doc.to_xhtml)
  rescue Object => ex
    puts "Cannot save the result to #{@path} due to: #{ex}"
  ensure
    f.close
  end
end