Skip to content

Commit

Permalink
Allow nested images inside tables and sections (sandrods#103)
Browse files Browse the repository at this point in the history
* move image handling to a proper class
* testing images
* bin - scripts for debugging
* store images data in Image class
* working on tables & sections
* image specs
  • Loading branch information
sandrods authored Feb 6, 2020
1 parent e1bfd46 commit 96a2173
Show file tree
Hide file tree
Showing 38 changed files with 737 additions and 265 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ doc
test/result
spec/result
Gemfile.lock
.DS_Store
10 changes: 10 additions & 0 deletions bin/odt-extract
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env ruby

require 'launchy'

arg = ARGV[0]
dir = File.basename(arg, File.extname(arg))

%x( rm -rf #{dir}; unzip -d #{dir} #{arg} )

Launchy.open dir
18 changes: 18 additions & 0 deletions bin/odt-viewer
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env ruby

require 'launchy'
require "nokogiri"
require "zip"

xml = ""

Zip::File.open(ARGV[0]) do |zip|
content = zip.get_entry('content.xml').get_input_stream.read
xml = Nokogiri::XML(content).to_xml
end

filename = File.join(Dir.mktmpdir, "#{File.basename(ARGV[0])}.result.xml")

File.open(filename, 'w') { |f| f.write xml }

Launchy.open filename
19 changes: 11 additions & 8 deletions lib/odf-report.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@
require 'zip'
require 'fileutils'
require 'nokogiri'
require 'mime/types'
require 'securerandom'

require File.expand_path('../odf-report/parser/default', __FILE__)

require File.expand_path('../odf-report/images', __FILE__)
require File.expand_path('../odf-report/field', __FILE__)
require File.expand_path('../odf-report/text', __FILE__)
require File.expand_path('../odf-report/template', __FILE__)
require File.expand_path('../odf-report/nested', __FILE__)
require File.expand_path('../odf-report/section', __FILE__)
require File.expand_path('../odf-report/table', __FILE__)
require File.expand_path('../odf-report/report', __FILE__)
require File.expand_path('../odf-report/data_source', __FILE__)
require File.expand_path('../odf-report/field', __FILE__)
require File.expand_path('../odf-report/text', __FILE__)
require File.expand_path('../odf-report/template', __FILE__)
require File.expand_path('../odf-report/image', __FILE__)
require File.expand_path('../odf-report/nestable', __FILE__)
require File.expand_path('../odf-report/section', __FILE__)
require File.expand_path('../odf-report/table', __FILE__)
require File.expand_path('../odf-report/report', __FILE__)
64 changes: 64 additions & 0 deletions lib/odf-report/data_source.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
module ODFReport
class DataSource

attr_reader :value

def initialize(opts, &block)
@value = opts[:value] || opts[:collection]
@data_field = opts[:data_field] || opts[:collection_field] || opts[:name]
@block = block
end

def set_source(record)
@value = extract_value_from_item(record)
end

def each(&block)
@value.each(&block)
end

def empty?
@value.nil? || @value.empty?
end

private

def extract_value_from_item(record)

if @block
@block.call(record)

elsif record.is_a?(Hash)
key = @data_field
record[key] || record[key.to_s.downcase] || record[key.to_s.upcase] || record[key.to_s.downcase.to_sym]

elsif @data_field.is_a?(Array)
execute_methods_on_item(record)

elsif @data_field.is_a?(Hash) && record.respond_to?(@data_field.keys[0])
record.send(@data_field.keys[0], @data_field.values[0])

elsif record.respond_to?(@data_field)
record.send(@data_field)

else
raise "Can't find [#{@data_field.to_s}] in this #{record.class}"

end

end

def execute_methods_on_item(record)
tmp = record.dup
@data_field.each do |f|
if f.is_a?(Hash)
tmp = tmp.send(f.keys[0], f.values[0])
else
tmp = tmp.send(f)
end
end
tmp
end

end
end
47 changes: 7 additions & 40 deletions lib/odf-report/field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,56 +5,25 @@ class Field

def initialize(opts, &block)
@name = opts[:name]
@data_field = opts[:data_field]

unless @value = opts[:value]

if block_given?
@block = block

else
@block = lambda { |item| self.extract_value(item) }
end

end
@data_source = DataSource.new(opts, &block)
end

def set_source(record)
@data_source.set_source(record)
self
end

def replace!(content, data_item = nil)

txt = content.inner_html

val = get_value(data_item)

txt.gsub!(to_placeholder, sanitize(val))
txt.gsub!(to_placeholder, sanitize(@data_source.value))

content.inner_html = txt

end

def get_value(data_item = nil)
@value || @block.call(data_item) || ''
end

def extract_value(data_item)
return unless data_item

key = @data_field || @name

if data_item.is_a?(Hash)
data_item[key] || data_item[key.to_s.downcase] || data_item[key.to_s.upcase] || data_item[key.to_s.downcase.to_sym]

elsif data_item.respond_to?(key.to_s.downcase.to_sym)
data_item.send(key.to_s.downcase.to_sym)

else
raise "Can't find field [#{key}] in this #{data_item.class}"

end

end

private
private

def to_placeholder
if DELIMITERS.is_a?(Array)
Expand Down Expand Up @@ -82,7 +51,5 @@ def odf_linebreak(s)
s.to_s.gsub("\n", "<text:line-break/>")
end



end
end
52 changes: 52 additions & 0 deletions lib/odf-report/image.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
module ODFReport
class Image < Field

IMAGE_DIR_NAME = "Pictures"

attr_reader :files

def initialize(opts, &block)
@files = []
super
end

def replace!(doc, data_item = nil)

frame = doc.xpath("//draw:frame[@draw:name='#{@name}']").first
image = doc.xpath("//draw:frame[@draw:name='#{@name}']/draw:image").first

return unless image

file = @data_source.value

image.attribute('href').content = File.join(IMAGE_DIR_NAME, File.basename(file))
frame.attribute('name').content = SecureRandom.uuid

@files << file
end

def self.include_image_file(zip_file, image_file)
return unless image_file

href = File.join(IMAGE_DIR_NAME, File.basename(image_file))

zip_file.update_file(href, File.read(image_file))
end

def self.include_manifest_entry(content, image_file)
return unless image_file

return unless root_node = content.at("//manifest:manifest")

href = File.join(IMAGE_DIR_NAME, File.basename(image_file))

entry = content.create_element('manifest:file-entry')
entry['manifest:full-path'] = href
entry['manifest:media-type'] = MIME::Types.type_for(href)[0].content_type

root_node.add_child entry

end

end
end
44 changes: 0 additions & 44 deletions lib/odf-report/images.rb

This file was deleted.

65 changes: 65 additions & 0 deletions lib/odf-report/nestable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
module ODFReport
class Nestable

def initialize(opts)
@name = opts[:name]

@data_source = DataSource.new(opts)

@fields = []
@texts = []
@tables = []
@sections = []
@images = []

end

def set_source(data_item)
@data_source.set_source(data_item)
self
end

def add_field(name, data_field=nil, &block)
opts = { name: name, data_field: data_field }
@fields << Field.new(opts, &block)
end
alias_method :add_column, :add_field

def add_text(name, data_field=nil, &block)
opts = {name: name, data_field: data_field}
@texts << Text.new(opts, &block)
end

def add_image(name, data_field=nil, &block)
opts = {name: name, data_field: data_field}
@images << Image.new(opts, &block)
end

def add_table(table_name, collection_field, opts={})
opts.merge!(name: table_name, collection_field: collection_field)
tab = Table.new(opts)
@tables << tab

yield(tab)
end

def add_section(section_name, collection_field, opts={})
opts.merge!(name: section_name, collection_field: collection_field)
sec = Section.new(opts)
@sections << sec

yield(sec)
end

def all_images
(@images.map(&:files) + @sections.map(&:all_images) + @tables.map(&:all_images)).flatten
end

def wrap_with_ns(node)
<<-XML
<root xmlns:draw="a" xmlns:xlink="b" xmlns:text="c" xmlns:table="d">#{node.to_xml}</root>
XML
end

end
end
Loading

0 comments on commit 96a2173

Please sign in to comment.