Class: Crayfish::Html

Inherits:
Object
  • Object
show all
Defined in:
lib/crayfish/html.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(fish, pdf) ⇒ Html

Returns a new instance of Html.



69
70
71
72
# File 'lib/crayfish/html.rb', line 69

def initialize fish,pdf
  @fish    = fish
  @pdf     = pdf
end

Instance Attribute Details

#pdfObject (readonly)

Returns the value of attribute pdf.



67
68
69
# File 'lib/crayfish/html.rb', line 67

def pdf
  @pdf
end

Instance Method Details

#apply_style(cell, style) ⇒ Object



105
106
107
108
109
110
111
112
# File 'lib/crayfish/html.rb', line 105

def apply_style cell,style
  # background-color:#ccccff
  style.split(';').each do |style|
    if /^background-color:#(?<color>.*)$/ =~ style
      cell.background_color = color
    end
  end
end

#asset_pathsObject



74
75
76
# File 'lib/crayfish/html.rb', line 74

def asset_paths
  @@asset_paths ||= ::ActionView::Helpers::AssetTagHelper::AssetPaths.new(::Rails.configuration.action_controller)
end

#compile(node, path = "/#{node.name}", postfix = '', scope = { :table => nil, :tr => nil }) ⇒ Object



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/crayfish/html.rb', line 136

def compile node, path = "/#{node.name}", postfix='',scope={ :table => nil, :tr => nil }
  name = node.name.to_sym

  case name
  when :img
    image = { :image =>  image_fs_path(node.attributes['src'].value) }
    image[:width]  = node.attributes['width'].value.to_f  if node.attributes['width']
    image[:height] = node.attributes['height'].value.to_f if node.attributes['height']
    if node.attributes['align']
      case node.attributes['align'].value.to_s.to_sym
      when :right
        image[:position] = :right
      when :middle
        image[:position] = :center
      end
    end
    return image

  when :table
    table = []
    table_styles = []
    traverse_children node, "#{path}#{postfix}", :table => table, :table_styles => table_styles, :tr => nil

    # apply style
    full_width = 540
    attribs = { :cell_style => { :inline_format => true } }
    if node.attributes['width'] && /^(?<percent>.*)%$/ =~ node.attributes['width'].value
      attribs[:post_resize] = "#{percent}%"
    end
    attribs[:cell_style][:borders] = [] if node.attributes['border'] && node.attributes['border'].value=='0'

    pdf_table = @pdf.make_table(table, attribs)
    table_styles.each do |style|
      apply_style(pdf_table.row(style[:row]).column(style[:col]),style[:style]) 
    end
    scope[:td] << pdf_table if scope[:td]
    return pdf_table

  when :tbody
    traverse_children node, "#{path}#{postfix}", :table => scope[:table], :table_styles => scope[:table_styles], :tr => nil
    return

  when :tr
    row = []
    traverse_children node, "#{path}#{postfix}", :table => scope[:table], :table_styles => scope[:table_styles], :tr => row
    scope[:table] << row
    return :tr => row

  when :td
    cells = []
    traverse_children node, "#{path}#{postfix}", :table => scope[:table], :table_styles => scope[:table_styles], :tr => scope[:tr], :td => cells
    if cells.size <= 1
      cells << "" if cells.size == 0
      cell = { :content => cells.first.kind_of?(String) ? cells.first.strip : cells.first }
      style cell,node,scope
      scope[:tr] << cell
    else
      scope[:tr] << cells
    end
    return

  when :th
    cells = []
    traverse_children node, "#{path}#{postfix}", :table => scope[:table], :table_styles => scope[:table_styles], :tr => scope[:tr], :td => cells
    if cells.size <= 1
      cells << "" if cells.size == 0
      cell = { :content => "<b>#{cells.first.strip}</b>", :align => :center }
      style cell,node,scope
      scope[:tr] << cell
    else
      scope[:tr] << cells
    end
    return

  when :text
    if scope[:td] and node.content.strip.size > 0
      scope[:td] << node.content.strip
    end
  when :html
  when :body
  else
    ::Rails.logger.debug "\e[1;31munknown node #{node.name} in CrayHtml\e[0m"
  end

  traverse_children node, "#{path}#{postfix}"
end

#draw(text) ⇒ Object



270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
# File 'lib/crayfish/html.rb', line 270

def draw text
  doc = Nokogiri::HTML(text)

  doc.children.map do |element|
    compile element
  end.flatten.each do |prawn|
    if prawn.kind_of? Hash
      if prawn.has_key? :image
        pdf.image prawn[:image], prawn
      end
    else
      post_resize prawn,540
      prawn.draw
    end
  end
end

#image_fs_path(image) ⇒ Object



100
101
102
103
# File 'lib/crayfish/html.rb', line 100

def image_fs_path image
  public_path = asset_paths.compute_public_path(image, 'images')
  public_path_to_fs_path(public_path)
end

#post_resize(node, parent_width) ⇒ Object



223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/crayfish/html.rb', line 223

def post_resize node,parent_width
  if node.kind_of?(Prawn::Table::Cell::Subtable)
    post_resize node.subtable,parent_width
  elsif node.kind_of?(Prawn::Table)
    if node.post_resize
      if /^(?<size>.*)%$/ =~ node.post_resize
        new_width = parent_width * size.to_f / 100.0
        column_widths = node.column_widths.dup
        scale = new_width / column_widths.sum
        node.instance_variable_set '@column_widths', nil

        # reset constraints
        (0..node.row_length).map do |n|
          row = node.row(n).columns(0..-1)
          row.each_with_index do |cell,i|
             cell.instance_variable_set '@max_width', column_widths[i]*scale
          end
        end
        node.width = new_width
        node.send(:set_column_widths)
        node.send(:position_cells)
      end
    end

    column_widths = node.column_widths
    (0..node.row_length).map do |n|

      row = node.row(n).columns(0..-1)
      
      row.each_with_index do |cell,i|
        colspan = 1
        row.to_a[i+1..-1].each do |cell|
          break unless cell.kind_of?(Prawn::Table::Cell::SpanDummy)
          colspan += 1
        end
        post_resize cell,column_widths[i..(i+colspan-1)].sum
      end
    end
  elsif node.kind_of? Array
    node.each{ |c| post_resize c,parent_width }
  elsif node.kind_of? Hash
    node.each do |k,v|
      post_resize v,parent_width
    end
  end
end

#public_path_to_fs_path(path) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/crayfish/html.rb', line 78

def public_path_to_fs_path path
  if /^(?<stripped>[^\?]*)\?[0-9]*$/ =~ path
    path = stripped
  end

  search_paths = [::Rails.public_path] + ::Rails.configuration.assets.paths
  search_paths.each do |search_path|
    if File.exists?("#{search_path}/#{path}")
      return "#{search_path}/#{path}"
    end
  end

  if /^\/assets\/(?<path>.*)$/ =~ path
    search_paths.each do |search_path|
      if File.exists?("#{search_path}/#{path}")
        return "#{search_path}/#{path}"
      end
    end
  end
  raise "Could not locate #{path} in #{search_paths.inspect}"
end

#style(cell, node, scope) ⇒ Object



128
129
130
131
132
133
134
# File 'lib/crayfish/html.rb', line 128

def style cell,node,scope
  cell[:colspan] = node.attributes['colspan'].value.to_i if node.attributes['colspan']
  cell[:rowspan] = node.attributes['rowspan'].value.to_i if node.attributes['rowspan']
  cell[:valign]  = :center if cell[:rowspan]
  cell[:align]   = node.attributes['align'].value.to_sym if node.attributes['align']
  scope[:table_styles] << { :row => scope[:table].size, :col => scope[:tr].size, :style => node.attributes['style'].value } if node.attributes['style']
end

#traverse_children(node, path, params = { :table => nil, :tr => nil }) ⇒ Object



114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/crayfish/html.rb', line 114

def traverse_children node,path,params={ :table => nil, :tr => nil }
  count = {}
  node.children.each{ |node| count[node.name.to_sym] = (count[node.name.to_sym]||0) + 1 }
  counters = Hash[*count.map{ |k,v| [k,0] }.flatten]
  node.children.map do |node|
    postfix = ''
    if count[node.name.to_sym] > 1
      postfix = "[#{counters[node.name.to_sym]}]"
      counters[node.name.to_sym] += 1
    end
    compile node, "#{path}/#{node.name}#{postfix}", '', params
  end
end