require "Spreadsheet/HTML/version" require "HTML/AutoTag" # i cannot hasa instantiate HTML::AutoTag inside Spreadsheet::HTML?!? module Auto class Tag < HTML::AutoTag end end module Spreadsheet class HTML def self.gen( *args ) self.new.generate( *args ) end def north( *args ) generate( *args, 'theta' => 0 ) end def portrait( *args ) generate( *args, 'theta' => 0 ) end def west( *args ) generate( *args, 'theta' => -270, 'tgroups' => 0 ) end def landscape( *args ) generate( *args, 'theta' => -270, 'tgroups' => 0 ) end def east( *args ) generate( *args, 'theta' => 90, 'tgroups' => 0, 'pinhead' => 1 ) end def south( *args ) generate( *args, 'theta' => -180, 'tgroups' => 0, 'pinhead' => 1 ) end def generate( *args ) params = _process( args ) if params['theta'] and params['flip'] params['theta'] *= -1 end if !params['theta'] # north if params['flip'] params['data'] = params['data'].map {|a| a.reverse } end elsif params['theta'] == 90 # east if params['pinhead'] and !params['headless'] params['data'] = params['data'].transpose.map{|a| a.push( a.shift ) } else params['data'] = params['data'].transpose.map{|a| a.reverse } end elsif params['theta'] == -90 if params['pinhead'] and !params['headless'] params['data'] = params['data'].transpose.reverse.map {|a| a.push( a.shift ) } else params['data'] = params['data'].transpose.reverse.map {|a| a.reverse } end elsif params['theta'] == 180 if params['pinhead'] and !params['headless'] params['data'] = params['data'].push( params['data'].shift ).map {|a| a.reverse } else params['data'] = params['data'].reverse.map {|a| a.reverse } end elsif params['theta'] == -180 # south if params['pinhead'] and !params['headless'] params['data'] = params['data'].push( params['data'].shift ) else params['data'] = params['data'].reverse end elsif params['theta'] == 270 params['data'] = params['data'].transpose.reverse elsif params['theta'] == -270 # west params['data'] = params['data'].transpose end return _make_table( params ) end def initialize( *args ) (args[0] || []).each do |key,val| self.instance_eval { class << self; self end }.send(:attr_accessor, key) self.send( "#{key}=", val ) end end def _make_table( params ) cdata = [] # TODO: insert caption and colgroup if params['tgroups'] && params['tgroups'] > 0 body = params['data'] head = body.shift() unless params['matrix'] && data.size() > 2 foot = body.pop() if !params['matrix'] && params['tgroups'] > 1 and data.size() > 2 head_row = { 'tag' => 'tr', 'attr' => params['thead.tr'] || {}, 'cdata' => head } foot_row = { 'tag' => 'tr', 'attr' => params['tfoot.tr'] || {}, 'cdata' => foot } body_rows = body.map{ |r| { 'tag' => 'tr', 'attr' => params['tr'] || {}, 'cdata' => r } } cdata.push({ 'tag' => 'thead', 'attr' => params['thead'] || {}, 'cdata' => head_row }) if head cdata.push({ 'tag' => 'tfoot', 'attr' => params['tfoot'] || {}, 'cdata' => foot_row }) if foot cdata.push({ 'tag' => 'tbody', 'attr' => params['tbody'] || {}, 'cdata' => body_rows }) else cdata.push( params['data'].map { |c| { 'tag' => 'tr', 'attr' => params['tr'] || {}, 'cdata' => c } } ) end return params['auto'].tag( 'tag' => 'table', 'attr' => params['table'] || {}, 'cdata' => cdata ) end def _process( args ) params = _args( args ) # headings is an alias for -r0 params['-r0'] = params['headings'] index = {} if params['data'][0].size() # implement index mapping end data = [] empty = params.has_key?('empty') ? params['empty'] : ' ' tag = ( params['matrix'] or params['headless'] ) ? 'td' : 'th' params['data'].each do |row| unless params['_layout'] (params['_max_cols'] - row.size).times { row.push( nil ) } # pad (row.size - params['_max_cols']).times { row.pop } # truncate end r = [] row.each do |col| col = col.to_s col = col.gsub( /^\s*$/, empty ) r.push( { 'tag' => tag, 'attr' => params[tag] || {}, 'cdata' => col } ) end data.push( r ) tag = 'td' end params['data'] = data params['data'].shift if params['headless'] return params end def _args( things ) data = [] args = [] while !things.empty? if things[0].kind_of?(Array) data.push( things.shift() ) if things[0].kind_of?(Array) data.push( things.shift() ) else args.push( things.shift() ) if !things.empty? args.push( things.shift() ) if !things.empty? end else args.push( things.shift() ) if !things.empty? args.push( things.shift() ) if !things.empty? end end params = {} self.instance_variables.each do |attr| params[attr[1..-1]] = self.instance_variable_get attr end (args || []).each do |hash| hash.each do |key,val| params[key] = val end end params['auto'] = Auto::Tag.new( 'encodes' => params.has_key?('encodes') ? params['encodes'] : '', 'indent' => params['indent'], 'level' => params['level'], 'sorted' => params['attr_sort'], ) if !params['data'] and data[0].kind_of?(Array) data = [ data ] if !data[0][0].kind_of?(Array) params['data'] = data[0] end params['_max_rows'] = params['data'].size params['_max_cols'] = params['data'][0].size params['data'] = params['data'].clone return params end end end